From ccc44d4bd40849e17138a781ca722c1995e66f8c Mon Sep 17 00:00:00 2001 From: Angelos Bimpoudis Date: Mon, 27 May 2024 05:59:55 +0200 Subject: [PATCH] Detecting pattern attribute --- .../share/classfile/classFileParser.cpp | 66 ++++++++++++++++++- src/hotspot/share/classfile/vmSymbols.hpp | 1 + src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 2 +- src/hotspot/share/oops/constMethod.hpp | 6 ++ src/hotspot/share/oops/method.hpp | 4 ++ src/hotspot/share/prims/jvm.cpp | 2 +- .../SimplePatternDeclarationsTest.java | 11 ++++ 7 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 734b425cb45..f424f6c109f 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -2341,6 +2341,11 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, const u1* annotation_default = nullptr; int annotation_default_length = 0; + int pattern_length = 0; + const u1* pattern_runtime_visible_parameter_annotations = nullptr; + int pattern_runtime_visible_parameter_annotations_length = 0; + bool is_pattern = false; + // Parse code and exceptions attribute u2 method_attributes_count = cfs->get_u2_fast(); while (method_attributes_count--) { @@ -2675,7 +2680,64 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, assert(runtime_invisible_type_annotations != nullptr, "null invisible type annotations"); } cfs->skip_u1(method_attribute_length, CHECK_NULL); - } else { + } + else if (method_attribute_name == vmSymbols::tag_pattern()) { + cfs->guarantee_more(6, CHECK_NULL); // pattern_name_index, pattern_flags, pattern_methodtype_index + + const u2 pattern_name_index = cfs->get_u2_fast(); + check_property( + valid_symbol_at(pattern_name_index), + "Invalid pattern attribute name index %u in class file %s", + pattern_name_index, CHECK_NULL); + const Symbol *const pattern_name = cp->symbol_at(pattern_name_index); + + const u2 pattern_flags = cfs->get_u2_fast(); + + const u2 pattern_methodtype_index = cfs->get_u2_fast(); + guarantee_property( + valid_symbol_at(pattern_methodtype_index), + "Illegal constant pool index %u for pattern method type in class file %s", + pattern_methodtype_index, CHECK_NULL); + const Symbol* const signature = cp->symbol_at(pattern_methodtype_index); + + is_pattern = true; + + cfs->guarantee_more(2, CHECK_NULL); // pattern_method_attributes_count + + u2 pattern_method_attributes_count = cfs->get_u2_fast(); + while (pattern_method_attributes_count--) { + cfs->guarantee_more(6, CHECK_NULL); // method_attribute_name_index, method_attribute_length + const u2 pattern_method_attribute_name_index = cfs->get_u2_fast(); + const u4 pattern_method_attribute_length = cfs->get_u4_fast(); + check_property( + valid_symbol_at(pattern_method_attribute_name_index), + "Invalid pattern method attribute name index %u in class file %s", + pattern_method_attribute_name_index, CHECK_NULL); + + const Symbol *const pattern_method_attribute_name = cp->symbol_at(pattern_method_attribute_name_index); + + if (pattern_method_attribute_name == vmSymbols::tag_method_parameters()) { + const int pattern_method_parameters_length = cfs->get_u1_fast(); + + cfs->skip_u2_fast(pattern_method_parameters_length); + cfs->skip_u2_fast(pattern_method_parameters_length); + } + else if (pattern_method_attribute_name == vmSymbols::tag_signature()) { + const int pattern_signature_data = parse_generic_signature_attribute(cfs, CHECK_NULL); + } else if (pattern_method_attribute_name == vmSymbols::tag_runtime_visible_parameter_annotations()) { + if (runtime_visible_type_annotations != nullptr) { + classfile_parse_error( + "Multiple RuntimeVisibleTypeAnnotations attributes for pattern method in class file %s", + THREAD); + return nullptr; + } + pattern_runtime_visible_parameter_annotations_length = pattern_method_attribute_length; + pattern_runtime_visible_parameter_annotations = cfs->current(); + cfs->skip_u1(pattern_runtime_visible_parameter_annotations_length, CHECK_NULL); + } + } + } + else { // Skip unknown attributes cfs->skip_u1(method_attribute_length, CHECK_NULL); } @@ -2730,6 +2792,8 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, m->set_constants(_cp); m->set_name_index(name_index); m->set_signature_index(signature_index); + m->set_is_pattern(is_pattern); + m->constMethod()->compute_from_signature(cp->symbol_at(signature_index), access_flags.is_static()); assert(args_size < 0 || args_size == m->size_of_parameters(), ""); diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index f79af705f0b..b1b38333516 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -207,6 +207,7 @@ class SerializeClosure; template(tag_enclosing_method, "EnclosingMethod") \ template(tag_bootstrap_methods, "BootstrapMethods") \ template(tag_permitted_subclasses, "PermittedSubclasses") \ + template(tag_pattern, "Pattern") \ \ /* exception klasses: at least all exceptions thrown by the VM have entries here */ \ template(java_lang_ArithmeticException, "java/lang/ArithmeticException") \ diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 3f58db0f415..dc119adc510 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2175,7 +2175,7 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredPatternDeclarations, (JNIEnv* env, job GrowableArray methods_array; for (int i = 0; i < iklass->methods()->length(); i++) { Method* m = iklass->methods()->at(i); - if (!m->is_initializer() && !m->is_overpass()) { + if (!m->is_initializer() && !m->is_overpass() && m->is_pattern()) { methods_array.append(m); } } diff --git a/src/hotspot/share/oops/constMethod.hpp b/src/hotspot/share/oops/constMethod.hpp index 5f0c49f9319..9328f36348a 100644 --- a/src/hotspot/share/oops/constMethod.hpp +++ b/src/hotspot/share/oops/constMethod.hpp @@ -200,6 +200,8 @@ class ConstMethod : public MetaspaceObj { u2 _code_size; u2 _name_index; // Method name (index in constant pool) u2 _signature_index; // Method signature (index in constant pool) + bool _is_pattern_flag; // Pattern method (index in constant pool) + u2 _method_idnum; // unique identification number for the method within the class // initially corresponds to the index into the methods array. // but this may change with redefinition @@ -296,6 +298,10 @@ class ConstMethod : public MetaspaceObj { u2 signature_index() const { return _signature_index; } void set_signature_index(int index) { _signature_index = checked_cast(index); } + // pattern + bool is_pattern() const { return _is_pattern_flag; } + void set_is_pattern(bool b) { _is_pattern_flag = b; } + // generics support u2 generic_signature_index() const { if (has_generic_signature()) { diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index b5634c8a099..9ff6f21db4f 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -148,6 +148,10 @@ class Method : public Metadata { u2 signature_index() const { return constMethod()->signature_index(); } void set_signature_index(int index) { constMethod()->set_signature_index(index); } + // pattern + u2 is_pattern() const { return constMethod()->is_pattern(); } + void set_is_pattern(bool b) { constMethod()->set_is_pattern(b); } + // generics support Symbol* generic_signature() const { int idx = generic_signature_index(); return ((idx != 0) ? constants()->symbol_at(idx) : nullptr); } u2 generic_signature_index() const { return constMethod()->generic_signature_index(); } diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 67bc570c9dd..c927217457f 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -1974,7 +1974,7 @@ static jobjectArray get_class_declared_pattern_declarations_helper( for (int i = 0; i < methods_length; i++) { methodHandle method(THREAD, methods->at(i)); if (select_method(method, want_constructor)) { - if (!publicOnly || method->is_public()) { + if ((!publicOnly || method->is_public()) && method->is_pattern()) { idnums->push(method->method_idnum()); ++num_methods; } diff --git a/test/jdk/java/lang/reflect/PatternDeclaration/SimplePatternDeclarationsTest.java b/test/jdk/java/lang/reflect/PatternDeclaration/SimplePatternDeclarationsTest.java index 7622f7a606a..7889a986739 100644 --- a/test/jdk/java/lang/reflect/PatternDeclaration/SimplePatternDeclarationsTest.java +++ b/test/jdk/java/lang/reflect/PatternDeclaration/SimplePatternDeclarationsTest.java @@ -54,6 +54,7 @@ class Person1 { private final String username; private boolean capitalize; + // 2 declared contructors public Person1(String name) { this(name, "default", false); } @@ -64,6 +65,7 @@ public Person1(String name, String username, boolean capitalize) { this.capitalize = capitalize; } + // 2 declared pattern declarations public pattern Person1(String name, String username) { match Person1(this.name, this.username); } @@ -75,4 +77,13 @@ public pattern Person1(String name) { match Person1(this.name); } } + + // 2 methods + public void test1() { + + } + + public int test2(int i) { + return i++; + } } \ No newline at end of file