Skip to content

Commit bf45138

Browse files
biboudislahodajvicente-romero-oracle
committed
8333725: Compiler Prototyping for Deconstructors
Co-authored-by: Angelos Bimpoudis <angelos.bimpoudis@oracle.com> Co-authored-by: Jan Lahoda <jan.lahoda@oracle.com> Co-authored-by: Vicente Romero <vicente.romero@oracle.com>
1 parent 3634a91 commit bf45138

File tree

121 files changed

+5312
-199
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+5312
-199
lines changed

src/hotspot/share/classfile/classFileParser.cpp

+65-1
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,11 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
23412341
const u1* annotation_default = nullptr;
23422342
int annotation_default_length = 0;
23432343

2344+
int pattern_length = 0;
2345+
const u1* pattern_runtime_visible_parameter_annotations = nullptr;
2346+
int pattern_runtime_visible_parameter_annotations_length = 0;
2347+
bool is_pattern = false;
2348+
23442349
// Parse code and exceptions attribute
23452350
u2 method_attributes_count = cfs->get_u2_fast();
23462351
while (method_attributes_count--) {
@@ -2675,7 +2680,64 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
26752680
assert(runtime_invisible_type_annotations != nullptr, "null invisible type annotations");
26762681
}
26772682
cfs->skip_u1(method_attribute_length, CHECK_NULL);
2678-
} else {
2683+
}
2684+
else if (method_attribute_name == vmSymbols::tag_pattern()) {
2685+
cfs->guarantee_more(6, CHECK_NULL); // pattern_name_index, pattern_flags, pattern_methodtype_index
2686+
2687+
const u2 pattern_name_index = cfs->get_u2_fast();
2688+
check_property(
2689+
valid_symbol_at(pattern_name_index),
2690+
"Invalid pattern attribute name index %u in class file %s",
2691+
pattern_name_index, CHECK_NULL);
2692+
const Symbol *const pattern_name = cp->symbol_at(pattern_name_index);
2693+
2694+
const u2 pattern_flags = cfs->get_u2_fast();
2695+
2696+
const u2 pattern_methodtype_index = cfs->get_u2_fast();
2697+
guarantee_property(
2698+
valid_symbol_at(pattern_methodtype_index),
2699+
"Illegal constant pool index %u for pattern method type in class file %s",
2700+
pattern_methodtype_index, CHECK_NULL);
2701+
const Symbol* const signature = cp->symbol_at(pattern_methodtype_index);
2702+
2703+
is_pattern = true;
2704+
2705+
cfs->guarantee_more(2, CHECK_NULL); // pattern_method_attributes_count
2706+
2707+
u2 pattern_method_attributes_count = cfs->get_u2_fast();
2708+
while (pattern_method_attributes_count--) {
2709+
cfs->guarantee_more(6, CHECK_NULL); // method_attribute_name_index, method_attribute_length
2710+
const u2 pattern_method_attribute_name_index = cfs->get_u2_fast();
2711+
const u4 pattern_method_attribute_length = cfs->get_u4_fast();
2712+
check_property(
2713+
valid_symbol_at(pattern_method_attribute_name_index),
2714+
"Invalid pattern method attribute name index %u in class file %s",
2715+
pattern_method_attribute_name_index, CHECK_NULL);
2716+
2717+
const Symbol *const pattern_method_attribute_name = cp->symbol_at(pattern_method_attribute_name_index);
2718+
2719+
if (pattern_method_attribute_name == vmSymbols::tag_method_parameters()) {
2720+
const int pattern_method_parameters_length = cfs->get_u1_fast();
2721+
2722+
cfs->skip_u2_fast(pattern_method_parameters_length);
2723+
cfs->skip_u2_fast(pattern_method_parameters_length);
2724+
}
2725+
else if (pattern_method_attribute_name == vmSymbols::tag_signature()) {
2726+
const int pattern_signature_data = parse_generic_signature_attribute(cfs, CHECK_NULL);
2727+
} else if (pattern_method_attribute_name == vmSymbols::tag_runtime_visible_parameter_annotations()) {
2728+
if (runtime_visible_type_annotations != nullptr) {
2729+
classfile_parse_error(
2730+
"Multiple RuntimeVisibleTypeAnnotations attributes for pattern method in class file %s",
2731+
THREAD);
2732+
return nullptr;
2733+
}
2734+
pattern_runtime_visible_parameter_annotations_length = pattern_method_attribute_length;
2735+
pattern_runtime_visible_parameter_annotations = cfs->current();
2736+
cfs->skip_u1(pattern_runtime_visible_parameter_annotations_length, CHECK_NULL);
2737+
}
2738+
}
2739+
}
2740+
else {
26792741
// Skip unknown attributes
26802742
cfs->skip_u1(method_attribute_length, CHECK_NULL);
26812743
}
@@ -2730,6 +2792,8 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
27302792
m->set_constants(_cp);
27312793
m->set_name_index(name_index);
27322794
m->set_signature_index(signature_index);
2795+
m->set_is_pattern(is_pattern);
2796+
27332797
m->constMethod()->compute_from_signature(cp->symbol_at(signature_index), access_flags.is_static());
27342798
assert(args_size < 0 || args_size == m->size_of_parameters(), "");
27352799

src/hotspot/share/classfile/vmSymbols.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ class SerializeClosure;
193193
template(tag_enclosing_method, "EnclosingMethod") \
194194
template(tag_bootstrap_methods, "BootstrapMethods") \
195195
template(tag_permitted_subclasses, "PermittedSubclasses") \
196+
template(tag_pattern, "Pattern") \
196197
\
197198
/* exception klasses: at least all exceptions thrown by the VM have entries here */ \
198199
template(java_lang_ArithmeticException, "java/lang/ArithmeticException") \

src/hotspot/share/include/jvm.h

+2
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,8 @@ JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly);
611611
JNIEXPORT jobjectArray JNICALL
612612
JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly);
613613

614+
JNIEXPORT jobjectArray JNICALL
615+
JVM_GetClassDeclaredDeconstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly);
614616

615617
/* Differs from JVM_GetClassModifiers in treatment of inner classes.
616618
This returns the access flags for the class as specified in the

src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -2161,6 +2161,33 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, ARGUME
21612161
return JVMCIENV->get_jobjectArray(methods);
21622162
C2V_END
21632163

2164+
C2V_VMENTRY_NULL(jobjectArray, getDeclaredDeconstructors, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass)))
2165+
Klass* klass = UNPACK_PAIR(Klass, klass);
2166+
if (klass == nullptr) {
2167+
JVMCI_THROW_0(NullPointerException);
2168+
}
2169+
if (!klass->is_instance_klass()) {
2170+
JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(0, JVMCI_CHECK_NULL);
2171+
return JVMCIENV->get_jobjectArray(methods);
2172+
}
2173+
2174+
InstanceKlass* iklass = InstanceKlass::cast(klass);
2175+
GrowableArray<Method*> methods_array;
2176+
for (int i = 0; i < iklass->methods()->length(); i++) {
2177+
Method* m = iklass->methods()->at(i);
2178+
if (!m->is_initializer() && !m->is_overpass() && m->is_pattern()) {
2179+
methods_array.append(m);
2180+
}
2181+
}
2182+
JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(methods_array.length(), JVMCI_CHECK_NULL);
2183+
for (int i = 0; i < methods_array.length(); i++) {
2184+
methodHandle mh(THREAD, methods_array.at(i));
2185+
JVMCIObject method = JVMCIENV->get_jvmci_method(mh, JVMCI_CHECK_NULL);
2186+
JVMCIENV->put_object_at(methods, i, method);
2187+
}
2188+
return JVMCIENV->get_jobjectArray(methods);
2189+
C2V_END
2190+
21642191
C2V_VMENTRY_NULL(jobjectArray, getDeclaredFieldsInfo, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass)))
21652192
Klass* klass = UNPACK_PAIR(Klass, klass);
21662193
if (klass == nullptr) {
@@ -3285,6 +3312,7 @@ JNINativeMethod CompilerToVM::methods[] = {
32853312
{CC "boxPrimitive", CC "(" OBJECT ")" OBJECTCONSTANT, FN_PTR(boxPrimitive)},
32863313
{CC "getDeclaredConstructors", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredConstructors)},
32873314
{CC "getDeclaredMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredMethods)},
3315+
{CC "getDeclaredDeconstructors", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredDeconstructors)},
32883316
{CC "getDeclaredFieldsInfo", CC "(" HS_KLASS2 ")[" FIELDINFO, FN_PTR(getDeclaredFieldsInfo)},
32893317
{CC "readStaticFieldValue", CC "(" HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readStaticFieldValue)},
32903318
{CC "readFieldValue", CC "(" OBJECTCONSTANT HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readFieldValue)},

src/hotspot/share/oops/constMethod.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ class ConstMethod : public MetaspaceObj {
200200
u2 _code_size;
201201
u2 _name_index; // Method name (index in constant pool)
202202
u2 _signature_index; // Method signature (index in constant pool)
203+
bool _is_pattern_flag; // Pattern method (index in constant pool)
204+
203205
u2 _method_idnum; // unique identification number for the method within the class
204206
// initially corresponds to the index into the methods array.
205207
// but this may change with redefinition
@@ -296,6 +298,10 @@ class ConstMethod : public MetaspaceObj {
296298
u2 signature_index() const { return _signature_index; }
297299
void set_signature_index(int index) { _signature_index = checked_cast<u2>(index); }
298300

301+
// pattern
302+
bool is_pattern() const { return _is_pattern_flag; }
303+
void set_is_pattern(bool b) { _is_pattern_flag = b; }
304+
299305
// generics support
300306
u2 generic_signature_index() const {
301307
if (has_generic_signature()) {

src/hotspot/share/oops/method.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ class Method : public Metadata {
148148
u2 signature_index() const { return constMethod()->signature_index(); }
149149
void set_signature_index(int index) { constMethod()->set_signature_index(index); }
150150

151+
// pattern
152+
u2 is_pattern() const { return constMethod()->is_pattern(); }
153+
void set_is_pattern(bool b) { constMethod()->set_is_pattern(b); }
154+
151155
// generics support
152156
Symbol* generic_signature() const { int idx = generic_signature_index(); return ((idx != 0) ? constants()->symbol_at(idx) : nullptr); }
153157
u2 generic_signature_index() const { return constMethod()->generic_signature_index(); }

src/hotspot/share/prims/jvm.cpp

+78
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,84 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass,
19391939
}
19401940
JVM_END
19411941

1942+
static jobjectArray get_class_declared_deconstructors_helper(
1943+
JNIEnv *env,
1944+
jclass ofClass, jboolean publicOnly,
1945+
bool want_constructor,
1946+
Klass* klass, TRAPS) {
1947+
1948+
JvmtiVMObjectAllocEventCollector oam;
1949+
1950+
oop ofMirror = JNIHandles::resolve_non_null(ofClass);
1951+
// Exclude primitive types and array types
1952+
if (java_lang_Class::is_primitive(ofMirror)
1953+
|| java_lang_Class::as_Klass(ofMirror)->is_array_klass()) {
1954+
// Return empty array
1955+
oop res = oopFactory::new_objArray(klass, 0, CHECK_NULL);
1956+
return (jobjectArray) JNIHandles::make_local(THREAD, res);
1957+
}
1958+
1959+
InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(ofMirror));
1960+
1961+
// Ensure class is linked
1962+
k->link_class(CHECK_NULL);
1963+
1964+
Array<Method*>* methods = k->methods();
1965+
int methods_length = methods->length();
1966+
1967+
// Save original method_idnum in case of redefinition, which can change
1968+
// the idnum of obsolete methods. The new method will have the same idnum
1969+
// but if we refresh the methods array, the counts will be wrong.
1970+
ResourceMark rm(THREAD);
1971+
GrowableArray<int>* idnums = new GrowableArray<int>(methods_length);
1972+
int num_methods = 0;
1973+
1974+
for (int i = 0; i < methods_length; i++) {
1975+
methodHandle method(THREAD, methods->at(i));
1976+
if (select_method(method, want_constructor)) {
1977+
if ((!publicOnly || method->is_public()) && method->is_pattern()) {
1978+
idnums->push(method->method_idnum());
1979+
++num_methods;
1980+
}
1981+
}
1982+
}
1983+
1984+
// Allocate result
1985+
objArrayOop r = oopFactory::new_objArray(klass, num_methods, CHECK_NULL);
1986+
objArrayHandle result (THREAD, r);
1987+
1988+
// Now just put the methods that we selected above, but go by their idnum
1989+
// in case of redefinition. The methods can be redefined at any safepoint,
1990+
// so above when allocating the oop array and below when creating reflect
1991+
// objects.
1992+
for (int i = 0; i < num_methods; i++) {
1993+
methodHandle method(THREAD, k->method_with_idnum(idnums->at(i)));
1994+
if (method.is_null()) {
1995+
// Method may have been deleted and seems this API can handle null
1996+
// Otherwise should probably put a method that throws NSME
1997+
result->obj_at_put(i, nullptr);
1998+
} else {
1999+
oop m;
2000+
if (want_constructor) {
2001+
m = Reflection::new_constructor(method, CHECK_NULL);
2002+
} else {
2003+
m = Reflection::new_method(method, false, CHECK_NULL);
2004+
}
2005+
result->obj_at_put(i, m);
2006+
}
2007+
}
2008+
2009+
return (jobjectArray) JNIHandles::make_local(THREAD, result());
2010+
}
2011+
2012+
JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredDeconstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly))
2013+
{
2014+
return get_class_declared_deconstructors_helper(env, ofClass, publicOnly,
2015+
/*want_constructor*/ false,
2016+
vmClasses::reflect_Method_klass(), THREAD);
2017+
}
2018+
JVM_END
2019+
19422020
JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly))
19432021
{
19442022
return get_class_declared_methods_helper(env, ofClass, publicOnly,

0 commit comments

Comments
 (0)