changeset 52909:9fca582660cc datum

adding support for native method: getRecordParameters
author vromero
date Tue, 23 Oct 2018 23:21:26 -0400
parents 4dbbe4e4d001
children 84c4bed32dd2 fcd04bbc2cd2
files make/hotspot/symbols/symbols-unix src/hotspot/share/include/jvm.h src/hotspot/share/oops/recordParamInfo.hpp src/hotspot/share/oops/recordParamStreams.hpp src/hotspot/share/prims/jvm.cpp src/java.base/share/classes/java/lang/Class.java src/java.base/share/native/libjava/Class.c
diffstat 7 files changed, 89 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/make/hotspot/symbols/symbols-unix	Tue Oct 23 23:21:22 2018 -0400
+++ b/make/hotspot/symbols/symbols-unix	Tue Oct 23 23:21:26 2018 -0400
@@ -123,6 +123,7 @@
 JVM_GetNestMembers
 JVM_GetPrimitiveArrayElement
 JVM_GetProtectionDomain
+JVM_GetRecordParameters
 JVM_GetSimpleBinaryName
 JVM_GetStackAccessControlContext
 JVM_GetSystemPackage
--- a/src/hotspot/share/include/jvm.h	Tue Oct 23 23:21:22 2018 -0400
+++ b/src/hotspot/share/include/jvm.h	Tue Oct 23 23:21:26 2018 -0400
@@ -515,6 +515,9 @@
 JNIEXPORT jobjectArray JNICALL
 JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly);
 
+JNIEXPORT jobjectArray JNICALL
+JVM_GetRecordParameters(JNIEnv *env, jclass ofClass);
+
 /* Differs from JVM_GetClassModifiers in treatment of inner classes.
    This returns the access flags for the class as specified in the
    class file rather than searching the InnerClasses attribute (if
--- a/src/hotspot/share/oops/recordParamInfo.hpp	Tue Oct 23 23:21:22 2018 -0400
+++ b/src/hotspot/share/oops/recordParamInfo.hpp	Tue Oct 23 23:21:26 2018 -0400
@@ -37,6 +37,8 @@
 
 class RecordParamInfo {
   friend class ClassFileParser;
+  friend class RecordParameterStreamBase;
+  friend class JavaRecordParameterStream;
   enum ParamOffset {
     access_flags_offset      = 0,
     name_index_offset        = 1,
@@ -48,13 +50,13 @@
 private:
   u2 _shorts[param_slots];
 
-  void set_name_index(u2 val)                    { _shorts[name_index_offset] = val;         }
-  void set_descriptor_index(u2 val)              { _shorts[descriptor_index_offset] = val;   }
-  void set_signature_index(u2 val)               { _shorts[signature_index_offset] = val;    }
+  void set_name_index(u2 val)                              { _shorts[name_index_offset] = val;         }
+  void set_descriptor_index(u2 val)                        { _shorts[descriptor_index_offset] = val;   }
+  void set_signature_index(u2 val)                         { _shorts[signature_index_offset] = val;    }
 
-  u2 name_index() const                          { return _shorts[name_index_offset];        }
-  u2 descriptor_index() const                    { return _shorts[descriptor_index_offset];  }
-  u2 signature_index() const                     { return _shorts[signature_index_offset];   }
+  u2 name_index() const                                    { return _shorts[name_index_offset];        }
+  u2 descriptor_index() const                              { return _shorts[descriptor_index_offset];  }
+  u2 signature_index() const                               { return _shorts[signature_index_offset];   }
 public:
   static RecordParamInfo* from_record_params_array(Array<u2>* record_params, int index) {
     return ((RecordParamInfo*)record_params->adr_at(index * param_slots));
@@ -63,19 +65,11 @@
     return ((RecordParamInfo*)(record_params + index * param_slots));
   }
 
-  u2 access_flags() const                        { return _shorts[access_flags_offset];      }
-
-  Symbol* name(const constantPoolHandle& cp) const {
-    return cp->symbol_at(name_index());
-  }
-
-  Symbol* signature(const constantPoolHandle& cp) const {
-    return cp->symbol_at(signature_index());
-  }
-
-  Symbol* descriptor(const constantPoolHandle& cp) const {
-    return cp->symbol_at(descriptor_index());
-  }
+  u2 access_flags() const                                   { return _shorts[access_flags_offset];      }
+  Symbol* name(const constantPoolHandle& cp) const          { return cp->symbol_at(name_index());       }
+  Symbol* signature(const constantPoolHandle& cp) const     { return cp->symbol_at(signature_index());  }
+  Symbol* descriptor(const constantPoolHandle& cp) const    { return cp->symbol_at(descriptor_index()); }
+  void set_access_flags(u2 val)                             { _shorts[access_flags_offset] = val;       }
 };
 
 #endif // SHARE_VM_OOPS_RECORDPARAMINFO_HPP
--- a/src/hotspot/share/oops/recordParamStreams.hpp	Tue Oct 23 23:21:22 2018 -0400
+++ b/src/hotspot/share/oops/recordParamStreams.hpp	Tue Oct 23 23:21:26 2018 -0400
@@ -26,8 +26,7 @@
 #define SHARE_VM_OOPS_RECORDPARAMSTREAMS_HPP
 
 #include "oops/instanceKlass.hpp"
-#include "oops/RecordParamInfo.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "oops/recordParamInfo.hpp"
 
 // The is the base class for iteration over the record parameters array
 // describing the parameters in a record.
@@ -38,7 +37,7 @@
   int                 _index;
   int                 _limit;
 
-  RecordParamInfo* record_param() const { return RecordParamInfo::from_field_array(_record_parameters, _index); }
+  RecordParamInfo* record_param() const { return RecordParamInfo::from_record_params_array(_record_parameters, _index); }
   InstanceKlass* record_param_holder() const { return _constants->pool_holder(); }
 
   RecordParameterStreamBase(Array<u2>* record_params, const constantPoolHandle& constants, int start, int limit) {
@@ -54,7 +53,7 @@
   }
 
   RecordParameterStreamBase(Array<u2>* record_params, const constantPoolHandle& constants) {
-    _record_parameters = fields;
+    _record_parameters = record_params;
     _constants = constants;
     _index = 0;
     _limit = record_params->length() / RecordParamInfo::param_slots;;
@@ -62,7 +61,7 @@
 
  public:
   RecordParameterStreamBase(InstanceKlass* klass) {
-    _record_parameters = klass->fields();
+    _record_parameters = klass->record_params();
     _constants = klass->constants();
     _index = 0;
     _limit = klass->record_params_count();
@@ -77,7 +76,7 @@
   }
   bool done() const { return _index >= _limit; }
 
-  // Accessors for current field
+  // Accessors for current record parameter
   AccessFlags access_flags() const {
     AccessFlags flags;
     flags.set_flags(record_param()->access_flags());
@@ -108,7 +107,7 @@
 // Iterate over the record parameters
 class JavaRecordParameterStream : public RecordParameterStreamBase {
  public:
-  JavaRecordParameterStream(const InstanceKlass* k): RecordParameterStreamBase(k->record_params(), k->constants(), 0, k->record_parameters_count()) {}
+  JavaRecordParameterStream(const InstanceKlass* k): RecordParameterStreamBase(k->record_params(), k->constants(), 0, k->record_params_count()) {}
 
   int name_index() const {
     return record_param()->name_index();
--- a/src/hotspot/share/prims/jvm.cpp	Tue Oct 23 23:21:22 2018 -0400
+++ b/src/hotspot/share/prims/jvm.cpp	Tue Oct 23 23:21:26 2018 -0400
@@ -51,6 +51,7 @@
 #include "oops/objArrayKlass.hpp"
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/recordParamStreams.hpp"
 #include "prims/jvm_misc.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/jvmtiThreadState.hpp"
@@ -1787,6 +1788,69 @@
 }
 JVM_END
 
+JVM_ENTRY(jobjectArray, JVM_GetRecordParameters(JNIEnv *env, jclass ofClass))
+{
+  JVMWrapper("JVM_GetRecordParameters");
+  JvmtiVMObjectAllocEventCollector oam;
+
+  // Exclude primitive types and array types
+  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
+      java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) {
+    // Return empty array
+    oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL);
+    return (jobjectArray) JNIHandles::make_local(env, res);
+  }
+
+  InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)));
+  constantPoolHandle cp(THREAD, k->constants());
+
+  // Ensure class is linked
+  k->link_class(CHECK_NULL);
+
+  // Allocate result
+  int num_record_params = k->record_params_count();
+  if (num_record_params == 0) {
+    oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL);
+    return (jobjectArray) JNIHandles::make_local(env, res);
+  }
+
+  // all record components are public
+  int num_of_public_fields = 0;
+  for (JavaFieldStream fileStream(k); !fileStream.done(); fileStream.next()) {
+    if (fileStream.access_flags().is_public()) ++num_of_public_fields;
+  }
+
+  objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), num_record_params, CHECK_NULL);
+  objArrayHandle result (THREAD, r);
+
+  int out_idx = 0;
+  fieldDescriptor fd;
+  if (num_record_params == num_of_public_fields) {
+    // all the fields are record components so just return the fields
+    for (JavaFieldStream fileStream(k); !fileStream.done(); fileStream.next()) {
+      fd.reinitialize(k, fileStream.index());
+      oop field = Reflection::new_field(&fd, CHECK_NULL);
+      result->obj_at_put(out_idx, field);
+      ++out_idx;
+    }
+  } else {
+    // it gets a bit more complicated some fields are record params and some not
+    for (JavaRecordParameterStream recordParamsStream(k); !recordParamsStream.done(); recordParamsStream.next()) {
+      for (JavaFieldStream fileStream(k); !fileStream.done(); fileStream.next()) {
+        if (fileStream.name() == recordParamsStream.name()) {
+          fd.reinitialize(k, fileStream.index());
+          oop field = Reflection::new_field(&fd, CHECK_NULL);
+          result->obj_at_put(out_idx, field);
+          ++out_idx;
+        }
+      }
+    }
+  }
+  assert(out_idx == num_record_params, "just checking");
+  return (jobjectArray) JNIHandles::make_local(env, result());
+}
+JVM_END
+
 static bool select_method(const methodHandle& method, bool want_constructor) {
   if (want_constructor) {
     return (method->is_initializer() && !method->is_static());
--- a/src/java.base/share/classes/java/lang/Class.java	Tue Oct 23 23:21:22 2018 -0400
+++ b/src/java.base/share/classes/java/lang/Class.java	Tue Oct 23 23:21:26 2018 -0400
@@ -3394,6 +3394,7 @@
     private native Method[]      getDeclaredMethods0(boolean publicOnly);
     private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly);
     private native Class<?>[]   getDeclaredClasses0();
+    private native Field[]      getRecordParameters0();
 
     /**
      * Helper method to get the method name from arguments.
--- a/src/java.base/share/native/libjava/Class.c	Tue Oct 23 23:21:22 2018 -0400
+++ b/src/java.base/share/native/libjava/Class.c	Tue Oct 23 23:21:26 2018 -0400
@@ -76,6 +76,7 @@
     {"getRawTypeAnnotations", "()" BA,      (void *)&JVM_GetClassTypeAnnotations},
     {"getNestHost0",         "()" CLS,      (void *)&JVM_GetNestHost},
     {"getNestMembers0",      "()[" CLS,     (void *)&JVM_GetNestMembers},
+    {"getRecordParameters0",  "()[" FLD,     (void *)&JVM_GetRecordParameters},
 };
 
 #undef OBJ