1 /*
2 * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "ci/ciKlass.hpp"
26 #include "ci/ciMethodData.hpp"
27 #include "ci/ciReplay.hpp"
28 #include "ci/ciSymbol.hpp"
29 #include "ci/ciUtilities.inline.hpp"
30 #include "classfile/javaClasses.hpp"
31 #include "classfile/symbolTable.hpp"
32 #include "classfile/systemDictionary.hpp"
33 #include "compiler/compilationPolicy.hpp"
34 #include "compiler/compileBroker.hpp"
35 #include "compiler/compilerDefinitions.inline.hpp"
36 #include "interpreter/linkResolver.hpp"
37 #include "jvm.h"
38 #include "memory/allocation.inline.hpp"
39 #include "memory/oopFactory.hpp"
40 #include "memory/resourceArea.hpp"
41 #include "oops/constantPool.inline.hpp"
42 #include "oops/cpCache.inline.hpp"
43 #include "oops/fieldStreams.inline.hpp"
44 #include "oops/klass.inline.hpp"
45 #include "oops/method.inline.hpp"
46 #include "oops/oop.inline.hpp"
47 #include "oops/resolvedIndyEntry.hpp"
48 #include "prims/jvmtiExport.hpp"
49 #include "prims/methodHandles.hpp"
50 #include "runtime/fieldDescriptor.inline.hpp"
51 #include "runtime/globals_extension.hpp"
52 #include "runtime/handles.inline.hpp"
53 #include "runtime/java.hpp"
54 #include "runtime/jniHandles.inline.hpp"
55 #include "runtime/threads.hpp"
56 #include "utilities/copy.hpp"
57 #include "utilities/macros.hpp"
58 #include "utilities/utf8.hpp"
59
60 // ciReplay
61
62 typedef struct _ciMethodDataRecord {
63 const char* _klass_name;
64 const char* _method_name;
65 const char* _signature;
66
494 return nullptr;
495 }
496 if (strcmp(field, ";") == 0) {
497 break;
498 }
499 // raw Method*
500 if (strcmp(field, "<vmtarget>") == 0) {
501 Method* vmtarget = java_lang_invoke_MemberName::vmtarget(obj);
502 k = (vmtarget == nullptr) ? nullptr : vmtarget->method_holder();
503 if (k == nullptr) {
504 report_error("null vmtarget found");
505 return nullptr;
506 }
507 if (!parse_terminator()) {
508 report_error("missing terminator");
509 return nullptr;
510 }
511 return k;
512 }
513 obj = ciReplay::obj_field(obj, field);
514 // array
515 if (obj != nullptr && obj->is_objArray()) {
516 objArrayOop arr = (objArrayOop)obj;
517 int index = parse_int("index");
518 if (index >= arr->length()) {
519 report_error("bad array index");
520 return nullptr;
521 }
522 obj = arr->obj_at(index);
523 }
524 } while (obj != nullptr);
525 if (obj == nullptr) {
526 report_error("null field found");
527 return nullptr;
528 }
529 k = obj->klass();
530 return k;
531 }
532
533 // Parse a valid klass name and look it up
534 // syntax: <name>
535 // syntax: <constant pool ref>
536 Klass* parse_klass(TRAPS) {
845
846 rec->_orig_data = parse_data("orig", rec->_orig_data_length);
847 if (rec->_orig_data == nullptr) {
848 return;
849 }
850 rec->_data = parse_intptr_data("data", rec->_data_length);
851 if (rec->_data == nullptr) {
852 return;
853 }
854 if (!parse_tag_and_count("oops", rec->_classes_length)) {
855 return;
856 }
857 rec->_classes = NEW_RESOURCE_ARRAY(Klass*, rec->_classes_length);
858 rec->_classes_offsets = NEW_RESOURCE_ARRAY(int, rec->_classes_length);
859 for (int i = 0; i < rec->_classes_length; i++) {
860 int offset = parse_int("offset");
861 if (had_error()) {
862 return;
863 }
864 Klass* k = parse_klass(CHECK);
865 rec->_classes_offsets[i] = offset;
866 rec->_classes[i] = k;
867 }
868
869 if (!parse_tag_and_count("methods", rec->_methods_length)) {
870 return;
871 }
872 rec->_methods = NEW_RESOURCE_ARRAY(Method*, rec->_methods_length);
873 rec->_methods_offsets = NEW_RESOURCE_ARRAY(int, rec->_methods_length);
874 for (int i = 0; i < rec->_methods_length; i++) {
875 int offset = parse_int("offset");
876 if (had_error()) {
877 return;
878 }
879 Method* m = parse_method(CHECK);
880 rec->_methods_offsets[i] = offset;
881 rec->_methods[i] = m;
882 }
883 }
884
885 // instanceKlass <name>
886 // instanceKlass <constant pool ref> # <original hidden class name>
887 //
888 // Loads and initializes the klass 'name'. This can be used to
889 // create particular class loading environments
890 void process_instanceKlass(TRAPS) {
891 // just load the referenced class
892 Klass* k = parse_klass(CHECK);
893
894 if (k == nullptr) {
895 return;
896 }
897 const char* comment = parse_string();
898 bool is_comment = comment != nullptr && strcmp(comment, "#") == 0;
899 if (k->is_hidden() != is_comment) {
900 report_error("hidden class with comment expected");
901 return;
902 }
903 // comment, print or ignore
904 if (is_comment) {
944 ConstantPool* cp = k->constants();
945 if (length != cp->length()) {
946 report_error("constant pool length mismatch: wrong class files?");
947 return;
948 }
949
950 int parsed_two_word = 0;
951 for (int i = 1; i < length; i++) {
952 int tag = parse_int("tag");
953 if (had_error()) {
954 return;
955 }
956 switch (cp->tag_at(i).value()) {
957 case JVM_CONSTANT_UnresolvedClass: {
958 if (tag == JVM_CONSTANT_Class) {
959 tty->print_cr("Resolving klass %s at %d", cp->klass_name_at(i)->as_utf8(), i);
960 Klass* k = cp->klass_at(i, CHECK);
961 }
962 break;
963 }
964 case JVM_CONSTANT_Long:
965 case JVM_CONSTANT_Double:
966 parsed_two_word = i + 1;
967
968 case JVM_CONSTANT_ClassIndex:
969 case JVM_CONSTANT_StringIndex:
970 case JVM_CONSTANT_String:
971 case JVM_CONSTANT_UnresolvedClassInError:
972 case JVM_CONSTANT_Fieldref:
973 case JVM_CONSTANT_Methodref:
974 case JVM_CONSTANT_InterfaceMethodref:
975 case JVM_CONSTANT_NameAndType:
976 case JVM_CONSTANT_Utf8:
977 case JVM_CONSTANT_Integer:
978 case JVM_CONSTANT_Float:
979 case JVM_CONSTANT_MethodHandle:
980 case JVM_CONSTANT_MethodType:
981 case JVM_CONSTANT_Dynamic:
982 case JVM_CONSTANT_InvokeDynamic:
983 if (tag != cp->tag_at(i).value()) {
990 if (tag == JVM_CONSTANT_UnresolvedClass) {
991 Klass* k = cp->klass_at(i, CHECK);
992 tty->print_cr("Warning: entry was unresolved in the replay data: %s", k->name()->as_utf8());
993 } else if (tag != JVM_CONSTANT_Class) {
994 report_error("Unexpected tag");
995 return;
996 }
997 break;
998
999 case 0:
1000 if (parsed_two_word == i) continue;
1001
1002 default:
1003 fatal("Unexpected tag: %d", cp->tag_at(i).value());
1004 break;
1005 }
1006
1007 }
1008 }
1009
1010 // staticfield <klass> <name> <signature> <value>
1011 //
1012 // Initialize a class and fill in the value for a static field.
1013 // This is useful when the compile was dependent on the value of
1014 // static fields but it's impossible to properly rerun the static
1015 // initializer.
1016 void process_staticfield(TRAPS) {
1017 InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
1018
1019 if (k == nullptr || ReplaySuppressInitializers == 0 ||
1020 (ReplaySuppressInitializers == 2 && k->class_loader() == nullptr)) {
1021 skip_remaining();
1022 return;
1023 }
1024
1025 assert(k->is_initialized(), "must be");
1026
1027 const char* field_name = parse_escaped_string();
1028 const char* field_signature = parse_string();
1029 fieldDescriptor fd;
1030 Symbol* name = SymbolTable::new_symbol(field_name);
1031 Symbol* sig = SymbolTable::new_symbol(field_signature);
1032 if (!k->find_local_field(name, sig, &fd) ||
1033 !fd.is_static() ||
1034 fd.has_initial_value()) {
1035 report_error(field_name);
1036 return;
1037 }
1038
1039 oop java_mirror = k->java_mirror();
1040 if (field_signature[0] == JVM_SIGNATURE_ARRAY) {
1041 int length = parse_int("array length");
1042 oop value = nullptr;
1043
1044 if (length != -1) {
1045 if (field_signature[1] == JVM_SIGNATURE_ARRAY) {
1046 // multi dimensional array
1047 ArrayKlass* kelem = (ArrayKlass *)parse_klass(CHECK);
1048 if (kelem == nullptr) {
1049 return;
1050 }
1051 int rank = 0;
1052 while (field_signature[rank] == JVM_SIGNATURE_ARRAY) {
1053 rank++;
1054 }
1055 jint* dims = NEW_RESOURCE_ARRAY(jint, rank);
1056 dims[0] = length;
1057 for (int i = 1; i < rank; i++) {
1058 dims[i] = 1; // These aren't relevant to the compiler
1059 }
1060 value = kelem->multi_allocate(rank, dims, CHECK);
1061 } else {
1062 if (strcmp(field_signature, "[B") == 0) {
1063 value = oopFactory::new_byteArray(length, CHECK);
1064 } else if (strcmp(field_signature, "[Z") == 0) {
1065 value = oopFactory::new_boolArray(length, CHECK);
1066 } else if (strcmp(field_signature, "[C") == 0) {
1067 value = oopFactory::new_charArray(length, CHECK);
1068 } else if (strcmp(field_signature, "[S") == 0) {
1069 value = oopFactory::new_shortArray(length, CHECK);
1070 } else if (strcmp(field_signature, "[F") == 0) {
1071 value = oopFactory::new_floatArray(length, CHECK);
1072 } else if (strcmp(field_signature, "[D") == 0) {
1073 value = oopFactory::new_doubleArray(length, CHECK);
1074 } else if (strcmp(field_signature, "[I") == 0) {
1075 value = oopFactory::new_intArray(length, CHECK);
1076 } else if (strcmp(field_signature, "[J") == 0) {
1077 value = oopFactory::new_longArray(length, CHECK);
1078 } else if (field_signature[0] == JVM_SIGNATURE_ARRAY &&
1079 field_signature[1] == JVM_SIGNATURE_CLASS) {
1080 Klass* actual_array_klass = parse_klass(CHECK);
1081 Klass* kelem = ObjArrayKlass::cast(actual_array_klass)->element_klass();
1082 value = oopFactory::new_objArray(kelem, length, CHECK);
1083 } else {
1084 report_error("unhandled array staticfield");
1085 }
1086 }
1087 }
1088 java_mirror->obj_field_put(fd.offset(), value);
1089 } else {
1090 const char* string_value = parse_escaped_string();
1091 if (strcmp(field_signature, "I") == 0) {
1092 int value = atoi(string_value);
1093 java_mirror->int_field_put(fd.offset(), value);
1094 } else if (strcmp(field_signature, "B") == 0) {
1095 int value = atoi(string_value);
1096 java_mirror->byte_field_put(fd.offset(), value);
1097 } else if (strcmp(field_signature, "C") == 0) {
1098 int value = atoi(string_value);
1099 java_mirror->char_field_put(fd.offset(), value);
1100 } else if (strcmp(field_signature, "S") == 0) {
1101 int value = atoi(string_value);
1102 java_mirror->short_field_put(fd.offset(), value);
1103 } else if (strcmp(field_signature, "Z") == 0) {
1104 int value = atoi(string_value);
1105 java_mirror->bool_field_put(fd.offset(), value);
1106 } else if (strcmp(field_signature, "J") == 0) {
1107 jlong value;
1108 if (sscanf(string_value, JLONG_FORMAT, &value) != 1) {
1109 fprintf(stderr, "Error parsing long: %s\n", string_value);
1110 return;
1111 }
1112 java_mirror->long_field_put(fd.offset(), value);
1113 } else if (strcmp(field_signature, "F") == 0) {
1114 float value = atof(string_value);
1115 java_mirror->float_field_put(fd.offset(), value);
1116 } else if (strcmp(field_signature, "D") == 0) {
1117 double value = atof(string_value);
1118 java_mirror->double_field_put(fd.offset(), value);
1119 } else if (strcmp(field_signature, "Ljava/lang/String;") == 0) {
1120 Handle value = java_lang_String::create_from_str(string_value, CHECK);
1121 java_mirror->obj_field_put(fd.offset(), value());
1122 } else if (field_signature[0] == JVM_SIGNATURE_CLASS) {
1123 oop value = nullptr;
1124 if (string_value != nullptr) {
1125 Klass* k = resolve_klass(string_value, CHECK);
1126 value = InstanceKlass::cast(k)->allocate_instance(CHECK);
1127 }
1128 java_mirror->obj_field_put(fd.offset(), value);
1129 } else {
1130 report_error("unhandled staticfield");
1131 }
1132 }
1133 }
1134
1135 #if INCLUDE_JVMTI
1136 // JvmtiExport <field> <value>
1137 void process_JvmtiExport(TRAPS) {
1138 const char* field = parse_string();
1139 bool value = parse_int("JvmtiExport flag") != 0;
1140 if (strcmp(field, "can_access_local_variables") == 0) {
1141 JvmtiExport::set_can_access_local_variables(value);
1142 } else if (strcmp(field, "can_hotswap_or_post_breakpoint") == 0) {
1143 JvmtiExport::set_can_hotswap_or_post_breakpoint(value);
1144 } else if (strcmp(field, "can_post_on_exceptions") == 0) {
1145 JvmtiExport::set_can_post_on_exceptions(value);
1146 } else {
1147 report_error("Unrecognized JvmtiExport directive");
1148 }
1149 }
|
1 /*
2 * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "ci/ciKlass.hpp"
26 #include "ci/ciMethodData.hpp"
27 #include "ci/ciReplay.hpp"
28 #include "ci/ciSymbol.hpp"
29 #include "ci/ciUtilities.inline.hpp"
30 #include "classfile/javaClasses.hpp"
31 #include "classfile/symbolTable.hpp"
32 #include "classfile/systemDictionary.hpp"
33 #include "compiler/compilationPolicy.hpp"
34 #include "compiler/compileBroker.hpp"
35 #include "compiler/compilerDefinitions.inline.hpp"
36 #include "interpreter/linkResolver.hpp"
37 #include "jvm.h"
38 #include "memory/allocation.inline.hpp"
39 #include "memory/oopFactory.hpp"
40 #include "memory/resourceArea.hpp"
41 #include "oops/arrayProperties.hpp"
42 #include "oops/constantPool.inline.hpp"
43 #include "oops/cpCache.inline.hpp"
44 #include "oops/fieldStreams.inline.hpp"
45 #include "oops/inlineKlass.inline.hpp"
46 #include "oops/klass.inline.hpp"
47 #include "oops/method.inline.hpp"
48 #include "oops/oop.inline.hpp"
49 #include "oops/oopCast.inline.hpp"
50 #include "oops/resolvedIndyEntry.hpp"
51 #include "prims/jvmtiExport.hpp"
52 #include "prims/methodHandles.hpp"
53 #include "runtime/fieldDescriptor.inline.hpp"
54 #include "runtime/globals_extension.hpp"
55 #include "runtime/handles.inline.hpp"
56 #include "runtime/java.hpp"
57 #include "runtime/jniHandles.inline.hpp"
58 #include "runtime/threads.hpp"
59 #include "utilities/copy.hpp"
60 #include "utilities/macros.hpp"
61 #include "utilities/utf8.hpp"
62
63 // ciReplay
64
65 typedef struct _ciMethodDataRecord {
66 const char* _klass_name;
67 const char* _method_name;
68 const char* _signature;
69
497 return nullptr;
498 }
499 if (strcmp(field, ";") == 0) {
500 break;
501 }
502 // raw Method*
503 if (strcmp(field, "<vmtarget>") == 0) {
504 Method* vmtarget = java_lang_invoke_MemberName::vmtarget(obj);
505 k = (vmtarget == nullptr) ? nullptr : vmtarget->method_holder();
506 if (k == nullptr) {
507 report_error("null vmtarget found");
508 return nullptr;
509 }
510 if (!parse_terminator()) {
511 report_error("missing terminator");
512 return nullptr;
513 }
514 return k;
515 }
516 obj = ciReplay::obj_field(obj, field);
517 // TODO 8350865 I think we need to handle null-free/flat arrays here
518 if (obj != nullptr && obj->is_refArray()) {
519 refArrayOop arr = oop_cast<refArrayOop>(obj);
520 int index = parse_int("index");
521 if (index >= arr->length()) {
522 report_error("bad array index");
523 return nullptr;
524 }
525 obj = arr->obj_at(index);
526 }
527 } while (obj != nullptr);
528 if (obj == nullptr) {
529 report_error("null field found");
530 return nullptr;
531 }
532 k = obj->klass();
533 return k;
534 }
535
536 // Parse a valid klass name and look it up
537 // syntax: <name>
538 // syntax: <constant pool ref>
539 Klass* parse_klass(TRAPS) {
848
849 rec->_orig_data = parse_data("orig", rec->_orig_data_length);
850 if (rec->_orig_data == nullptr) {
851 return;
852 }
853 rec->_data = parse_intptr_data("data", rec->_data_length);
854 if (rec->_data == nullptr) {
855 return;
856 }
857 if (!parse_tag_and_count("oops", rec->_classes_length)) {
858 return;
859 }
860 rec->_classes = NEW_RESOURCE_ARRAY(Klass*, rec->_classes_length);
861 rec->_classes_offsets = NEW_RESOURCE_ARRAY(int, rec->_classes_length);
862 for (int i = 0; i < rec->_classes_length; i++) {
863 int offset = parse_int("offset");
864 if (had_error()) {
865 return;
866 }
867 Klass* k = parse_klass(CHECK);
868 if (had_error()) {
869 return;
870 }
871 if (_version >= 3 && k != nullptr && k->is_objArray_klass()) {
872 k = create_concrete_object_array_klass(ObjArrayKlass::cast(k), THREAD);
873 }
874 rec->_classes_offsets[i] = offset;
875 rec->_classes[i] = k;
876 }
877
878 if (!parse_tag_and_count("methods", rec->_methods_length)) {
879 return;
880 }
881 rec->_methods = NEW_RESOURCE_ARRAY(Method*, rec->_methods_length);
882 rec->_methods_offsets = NEW_RESOURCE_ARRAY(int, rec->_methods_length);
883 for (int i = 0; i < rec->_methods_length; i++) {
884 int offset = parse_int("offset");
885 if (had_error()) {
886 return;
887 }
888 Method* m = parse_method(CHECK);
889 rec->_methods_offsets[i] = offset;
890 rec->_methods[i] = m;
891 }
892 }
893
894 ObjArrayKlass* create_concrete_object_array_klass(ObjArrayKlass* obj_array_klass, TRAPS) {
895 const ArrayProperties array_properties(checked_cast<ArrayProperties::Type>(parse_int("array_properties")));
896 if (!Arguments::is_valhalla_enabled()) {
897 // Ignore array properties.
898 return obj_array_klass;
899 }
900
901 guarantee(array_properties.is_valid(), "invalid array_properties: %d", array_properties.value());
902
903 return obj_array_klass->klass_with_properties(array_properties, THREAD);
904 }
905
906 // instanceKlass <name>
907 // instanceKlass <constant pool ref> # <original hidden class name>
908 //
909 // Loads and initializes the klass 'name'. This can be used to
910 // create particular class loading environments
911 void process_instanceKlass(TRAPS) {
912 // just load the referenced class
913 Klass* k = parse_klass(CHECK);
914
915 if (k == nullptr) {
916 return;
917 }
918 const char* comment = parse_string();
919 bool is_comment = comment != nullptr && strcmp(comment, "#") == 0;
920 if (k->is_hidden() != is_comment) {
921 report_error("hidden class with comment expected");
922 return;
923 }
924 // comment, print or ignore
925 if (is_comment) {
965 ConstantPool* cp = k->constants();
966 if (length != cp->length()) {
967 report_error("constant pool length mismatch: wrong class files?");
968 return;
969 }
970
971 int parsed_two_word = 0;
972 for (int i = 1; i < length; i++) {
973 int tag = parse_int("tag");
974 if (had_error()) {
975 return;
976 }
977 switch (cp->tag_at(i).value()) {
978 case JVM_CONSTANT_UnresolvedClass: {
979 if (tag == JVM_CONSTANT_Class) {
980 tty->print_cr("Resolving klass %s at %d", cp->klass_name_at(i)->as_utf8(), i);
981 Klass* k = cp->klass_at(i, CHECK);
982 }
983 break;
984 }
985
986 case JVM_CONSTANT_Long:
987 case JVM_CONSTANT_Double:
988 parsed_two_word = i + 1;
989
990 case JVM_CONSTANT_ClassIndex:
991 case JVM_CONSTANT_StringIndex:
992 case JVM_CONSTANT_String:
993 case JVM_CONSTANT_UnresolvedClassInError:
994 case JVM_CONSTANT_Fieldref:
995 case JVM_CONSTANT_Methodref:
996 case JVM_CONSTANT_InterfaceMethodref:
997 case JVM_CONSTANT_NameAndType:
998 case JVM_CONSTANT_Utf8:
999 case JVM_CONSTANT_Integer:
1000 case JVM_CONSTANT_Float:
1001 case JVM_CONSTANT_MethodHandle:
1002 case JVM_CONSTANT_MethodType:
1003 case JVM_CONSTANT_Dynamic:
1004 case JVM_CONSTANT_InvokeDynamic:
1005 if (tag != cp->tag_at(i).value()) {
1012 if (tag == JVM_CONSTANT_UnresolvedClass) {
1013 Klass* k = cp->klass_at(i, CHECK);
1014 tty->print_cr("Warning: entry was unresolved in the replay data: %s", k->name()->as_utf8());
1015 } else if (tag != JVM_CONSTANT_Class) {
1016 report_error("Unexpected tag");
1017 return;
1018 }
1019 break;
1020
1021 case 0:
1022 if (parsed_two_word == i) continue;
1023
1024 default:
1025 fatal("Unexpected tag: %d", cp->tag_at(i).value());
1026 break;
1027 }
1028
1029 }
1030 }
1031
1032 class InlineTypeFieldInitializer : public FieldClosure {
1033 oop _vt;
1034 CompileReplay* _replay;
1035 public:
1036 InlineTypeFieldInitializer(oop vt, CompileReplay* replay)
1037 : _vt(vt), _replay(replay) {}
1038
1039 void do_field(fieldDescriptor* fd) {
1040 BasicType bt = fd->field_type();
1041 const char* string_value = fd->is_null_free_inline_type() ? nullptr : _replay->parse_escaped_string();
1042 switch (bt) {
1043 case T_BYTE: {
1044 int value = atoi(string_value);
1045 _vt->byte_field_put(fd->offset(), value);
1046 break;
1047 }
1048 case T_BOOLEAN: {
1049 int value = atoi(string_value);
1050 _vt->bool_field_put(fd->offset(), value);
1051 break;
1052 }
1053 case T_SHORT: {
1054 int value = atoi(string_value);
1055 _vt->short_field_put(fd->offset(), value);
1056 break;
1057 }
1058 case T_CHAR: {
1059 int value = atoi(string_value);
1060 _vt->char_field_put(fd->offset(), value);
1061 break;
1062 }
1063 case T_INT: {
1064 int value = atoi(string_value);
1065 _vt->int_field_put(fd->offset(), value);
1066 break;
1067 }
1068 case T_LONG: {
1069 jlong value;
1070 if (sscanf(string_value, JLONG_FORMAT, &value) != 1) {
1071 fprintf(stderr, "Error parsing long: %s\n", string_value);
1072 break;
1073 }
1074 _vt->long_field_put(fd->offset(), value);
1075 break;
1076 }
1077 case T_FLOAT: {
1078 float value = atof(string_value);
1079 _vt->float_field_put(fd->offset(), value);
1080 break;
1081 }
1082 case T_DOUBLE: {
1083 double value = atof(string_value);
1084 _vt->double_field_put(fd->offset(), value);
1085 break;
1086 }
1087 case T_ARRAY:
1088 case T_OBJECT:
1089 if (fd->is_null_free_inline_type() && fd->is_flat()) {
1090 InlineKlass* vk = InlineKlass::cast(fd->field_holder()->get_inline_type_field_klass(fd->index()));
1091 int field_offset = fd->offset() - vk->payload_offset();
1092 oop obj = cast_to_oop(cast_from_oop<address>(_vt) + field_offset);
1093 InlineTypeFieldInitializer init_fields(obj, _replay);
1094 vk->do_nonstatic_fields(&init_fields);
1095 } else {
1096 JavaThread* THREAD = JavaThread::current();
1097 bool res = _replay->process_staticfield_reference(string_value, _vt, fd, THREAD);
1098 assert(res, "should succeed for arrays & objects");
1099 }
1100 default: {
1101 fatal("Unhandled type: %s", type2name(bt));
1102 }
1103 }
1104 }
1105 };
1106
1107 bool process_staticfield_reference(const char* field_signature, oop java_mirror, fieldDescriptor* fd, TRAPS) {
1108 if (field_signature[0] == JVM_SIGNATURE_ARRAY) {
1109 int length = parse_int("array length");
1110 oop value = nullptr;
1111
1112 if (length != -1) {
1113 if (field_signature[1] == JVM_SIGNATURE_ARRAY) {
1114 // multi dimensional array
1115 Klass* k = resolve_klass(field_signature, CHECK_(true));
1116 ArrayKlass* kelem = (ArrayKlass *)k;
1117 int rank = 0;
1118 while (field_signature[rank] == JVM_SIGNATURE_ARRAY) {
1119 rank++;
1120 }
1121 jint* dims = NEW_RESOURCE_ARRAY(jint, rank);
1122 dims[0] = length;
1123 for (int i = 1; i < rank; i++) {
1124 dims[i] = 1; // These aren't relevant to the compiler
1125 }
1126 value = kelem->multi_allocate(rank, dims, CHECK_(true));
1127 } else {
1128 if (strcmp(field_signature, "[B") == 0) {
1129 value = oopFactory::new_byteArray(length, CHECK_(true));
1130 } else if (strcmp(field_signature, "[Z") == 0) {
1131 value = oopFactory::new_boolArray(length, CHECK_(true));
1132 } else if (strcmp(field_signature, "[C") == 0) {
1133 value = oopFactory::new_charArray(length, CHECK_(true));
1134 } else if (strcmp(field_signature, "[S") == 0) {
1135 value = oopFactory::new_shortArray(length, CHECK_(true));
1136 } else if (strcmp(field_signature, "[F") == 0) {
1137 value = oopFactory::new_floatArray(length, CHECK_(true));
1138 } else if (strcmp(field_signature, "[D") == 0) {
1139 value = oopFactory::new_doubleArray(length, CHECK_(true));
1140 } else if (strcmp(field_signature, "[I") == 0) {
1141 value = oopFactory::new_intArray(length, CHECK_(true));
1142 } else if (strcmp(field_signature, "[J") == 0) {
1143 value = oopFactory::new_longArray(length, CHECK_(true));
1144 } else if (field_signature[0] == JVM_SIGNATURE_ARRAY &&
1145 field_signature[1] == JVM_SIGNATURE_CLASS) {
1146 Klass* actual_array_klass = parse_klass(CHECK_(true));
1147 // TODO 8350865 I think we need to handle null-free/flat arrays here
1148 // This handling will change the array property argument passed to the
1149 // factory below
1150 Klass* kelem = ObjArrayKlass::cast(actual_array_klass)->element_klass();
1151 value = oopFactory::new_objArray(kelem, length, CHECK_(true));
1152 } else {
1153 report_error("unhandled array staticfield");
1154 }
1155 }
1156 java_mirror->obj_field_put(fd->offset(), value);
1157 return true;
1158 }
1159 } else if (strcmp(field_signature, "Ljava/lang/String;") == 0) {
1160 const char* string_value = parse_escaped_string();
1161 Handle value = java_lang_String::create_from_str(string_value, CHECK_(true));
1162 java_mirror->obj_field_put(fd->offset(), value());
1163 return true;
1164 } else if (field_signature[0] == JVM_SIGNATURE_CLASS) {
1165 const char* instance = parse_escaped_string();
1166 oop value = nullptr;
1167 if (instance != nullptr) {
1168 Klass* k = resolve_klass(instance, CHECK_(true));
1169 value = InstanceKlass::cast(k)->allocate_instance(CHECK_(true));
1170 }
1171 java_mirror->obj_field_put(fd->offset(), value);
1172 return true;
1173 }
1174 return false;
1175 }
1176
1177 // Initialize a class and fill in the value for a static field.
1178 // This is useful when the compile was dependent on the value of
1179 // static fields but it's impossible to properly rerun the static
1180 // initializer.
1181 void process_staticfield(TRAPS) {
1182 InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
1183
1184 if (k == nullptr || ReplaySuppressInitializers == 0 ||
1185 (ReplaySuppressInitializers == 2 && k->class_loader() == nullptr)) {
1186 skip_remaining();
1187 return;
1188 }
1189
1190 assert(k->is_initialized(), "must be");
1191
1192 const char* field_name = parse_escaped_string();
1193 const char* field_signature = parse_string();
1194 fieldDescriptor fd;
1195 Symbol* name = SymbolTable::new_symbol(field_name);
1196 Symbol* sig = SymbolTable::new_symbol(field_signature);
1197 if (!k->find_local_field(name, sig, &fd) ||
1198 !fd.is_static() ||
1199 fd.has_initial_value()) {
1200 report_error(field_name);
1201 return;
1202 }
1203
1204 oop java_mirror = k->java_mirror();
1205 if (strcmp(field_signature, "I") == 0) {
1206 const char* string_value = parse_escaped_string();
1207 int value = atoi(string_value);
1208 java_mirror->int_field_put(fd.offset(), value);
1209 } else if (strcmp(field_signature, "B") == 0) {
1210 const char* string_value = parse_escaped_string();
1211 int value = atoi(string_value);
1212 java_mirror->byte_field_put(fd.offset(), value);
1213 } else if (strcmp(field_signature, "C") == 0) {
1214 const char* string_value = parse_escaped_string();
1215 int value = atoi(string_value);
1216 java_mirror->char_field_put(fd.offset(), value);
1217 } else if (strcmp(field_signature, "S") == 0) {
1218 const char* string_value = parse_escaped_string();
1219 int value = atoi(string_value);
1220 java_mirror->short_field_put(fd.offset(), value);
1221 } else if (strcmp(field_signature, "Z") == 0) {
1222 const char* string_value = parse_escaped_string();
1223 int value = atoi(string_value);
1224 java_mirror->bool_field_put(fd.offset(), value);
1225 } else if (strcmp(field_signature, "J") == 0) {
1226 const char* string_value = parse_escaped_string();
1227 jlong value;
1228 if (sscanf(string_value, JLONG_FORMAT, &value) != 1) {
1229 fprintf(stderr, "Error parsing long: %s\n", string_value);
1230 return;
1231 }
1232 java_mirror->long_field_put(fd.offset(), value);
1233 } else if (strcmp(field_signature, "F") == 0) {
1234 const char* string_value = parse_escaped_string();
1235 float value = atof(string_value);
1236 java_mirror->float_field_put(fd.offset(), value);
1237 } else if (strcmp(field_signature, "D") == 0) {
1238 const char* string_value = parse_escaped_string();
1239 double value = atof(string_value);
1240 java_mirror->double_field_put(fd.offset(), value);
1241 } else if (fd.is_null_free_inline_type()) {
1242 Klass* kelem = resolve_klass(field_signature, CHECK);
1243 InlineKlass* vk = InlineKlass::cast(kelem);
1244 oop value = vk->allocate_instance(CHECK);
1245 InlineTypeFieldInitializer init_fields(value, this);
1246 vk->do_nonstatic_fields(&init_fields);
1247 java_mirror->obj_field_put(fd.offset(), value);
1248 } else {
1249 bool res = process_staticfield_reference(field_signature, java_mirror, &fd, CHECK);
1250 if (!res) {
1251 report_error("unhandled staticfield");
1252 }
1253 }
1254 }
1255
1256 #if INCLUDE_JVMTI
1257 // JvmtiExport <field> <value>
1258 void process_JvmtiExport(TRAPS) {
1259 const char* field = parse_string();
1260 bool value = parse_int("JvmtiExport flag") != 0;
1261 if (strcmp(field, "can_access_local_variables") == 0) {
1262 JvmtiExport::set_can_access_local_variables(value);
1263 } else if (strcmp(field, "can_hotswap_or_post_breakpoint") == 0) {
1264 JvmtiExport::set_can_hotswap_or_post_breakpoint(value);
1265 } else if (strcmp(field, "can_post_on_exceptions") == 0) {
1266 JvmtiExport::set_can_post_on_exceptions(value);
1267 } else {
1268 report_error("Unrecognized JvmtiExport directive");
1269 }
1270 }
|