changeset 56910:5261a2b6a653 records-and-sealed

fixing several bugs plus adding reflection test
author vromero
date Thu, 27 Jun 2019 14:45:22 -0400
parents 8cbd278a7204
children 43a6ba90748b ccb9986a609c
files src/hotspot/share/classfile/classFileParser.cpp src/hotspot/share/classfile/classFileParser.hpp src/hotspot/share/oops/instanceKlass.hpp src/hotspot/share/prims/jvm.cpp src/java.base/share/classes/java/lang/Class.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java test/langtools/tools/javac/records/reflection/RecordReflectionTest.java
diffstat 7 files changed, 81 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/classfile/classFileParser.cpp	Thu Jun 27 10:55:30 2019 -0400
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Thu Jun 27 14:45:22 2019 -0400
@@ -3259,16 +3259,16 @@
 void ClassFileParser::parse_classfile_record_attribute(const ClassFileStream* const cfs,
                                                            const u1* const record_attribute_start,
                                                            ConstantPool* cp,
-                                                           u2* const record_params_count_ptr,
+                                                           int* const record_params_count_ptr,
                                                            TRAPS) {
   assert(NULL == _record_params, "invariant");
 
   const u1* const current_mark = cfs->current();
-  u2 num_of_params = 0;
+  int num_of_params = 0;
   if (record_attribute_start != NULL) {
     cfs->set_current(record_attribute_start);
     cfs->guarantee_more(2, CHECK);  // length
-    num_of_params = cfs->get_u2_fast();
+    num_of_params = (int)cfs->get_u2_fast();
     // DEBUG
     // tty->print_cr("this record has %d parameters", num_of_params);
   }
--- a/src/hotspot/share/classfile/classFileParser.hpp	Thu Jun 27 10:55:30 2019 -0400
+++ b/src/hotspot/share/classfile/classFileParser.hpp	Thu Jun 27 14:45:22 2019 -0400
@@ -154,7 +154,7 @@
   u2 _super_class_index;
   u2 _itfs_len;
   u2 _java_fields_count;
-  u2 _record_params_count;
+  int _record_params_count;
 
   bool _need_verify;
   bool _relax_verify;
@@ -297,7 +297,7 @@
   void parse_classfile_record_attribute(const ClassFileStream* const cfs,
                                         const u1* const record_attribute_start,
                                         ConstantPool* cp,
-                                        u2* const record_params_count_ptr,
+                                        int* const record_params_count_ptr,
                                         TRAPS);
 
   void parse_classfile_attributes(const ClassFileStream* const cfs,
--- a/src/hotspot/share/oops/instanceKlass.hpp	Thu Jun 27 10:55:30 2019 -0400
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Thu Jun 27 14:45:22 2019 -0400
@@ -209,7 +209,7 @@
   u2              _source_file_name_index;
   u2              _static_oop_field_count;// number of static oop fields in this klass
   u2              _java_fields_count;    // The number of declared Java fields
-  u2              _record_params_count;  // The number of record parameters
+  int              _record_params_count;  // The number of record parameters
   int             _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
 
   int             _itable_len;           // length of Java itable (in words)
@@ -461,10 +461,10 @@
   Symbol* record_param_signature(int index) const { return record_param(index)->signature(constants()); }
   Symbol* record_param_descriptor(int index) const { return record_param(index)->signature(constants()); }
 
-  int record_params_count() const       { return (int)_record_params_count; }
+  int record_params_count() const       { return _record_params_count; }
 
   Array<u2>* record_params() const       { return _record_params; }
-  void set_record_params(Array<u2>* record_params, u2 record_params_count) {
+  void set_record_params(Array<u2>* record_params, int record_params_count) {
     guarantee(_record_params == NULL || record_params == NULL, "Just checking");
     _record_params = record_params;
     _record_params_count = record_params_count;
--- a/src/hotspot/share/prims/jvm.cpp	Thu Jun 27 10:55:30 2019 -0400
+++ b/src/hotspot/share/prims/jvm.cpp	Thu Jun 27 14:45:22 2019 -0400
@@ -1679,8 +1679,8 @@
   // DEBUG
   //tty->print_cr("num_record_params == %d", num_record_params);
 
-  if (num_record_params == 0) {
-    oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL);
+  if (num_record_params <= 0) {
+    oop res = oopFactory::new_objArray(SystemDictionary::String_klass(), 0, CHECK_NULL);
     return (jobjectArray) JNIHandles::make_local(env, res);
   }
 
@@ -1701,7 +1701,7 @@
 JVM_ENTRY(jboolean, JVM_IsRecord(JNIEnv *env, jclass cls))
   JVMWrapper("JVM_IsRecord");
   InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)));
-  return (jboolean) k->record_params_count() >= 0;
+  return (jboolean) (k->record_params_count() >= 0);
 JVM_END
 
 static bool select_method(const methodHandle& method, bool want_constructor) {
--- a/src/java.base/share/classes/java/lang/Class.java	Thu Jun 27 10:55:30 2019 -0400
+++ b/src/java.base/share/classes/java/lang/Class.java	Thu Jun 27 14:45:22 2019 -0400
@@ -2273,6 +2273,7 @@
         int i = 0;
         for (String componentName : componentNames) {
             result[i] = getMethod(componentName);
+            i++;
         }
         return result;
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Jun 27 10:55:30 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Jun 27 14:45:22 2019 -0400
@@ -1632,15 +1632,6 @@
         public Type erasure(Types types) {
             if (erasure_field == null) {
                 erasure_field = types.erasure(type);
-                if (!accessors.isEmpty()) {
-                    for (Pair<Accessors.Kind, MethodSymbol> accessorPair : accessors) {
-                        if (accessorPair.fst == Accessors.Kind.GET) {
-                            ((MethodType)accessorPair.snd.type).restype = erasure_field;
-                        } else {
-                            // set accessors are not yet generated
-                        }
-                    }
-                }
             }
             return erasure_field;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/records/reflection/RecordReflectionTest.java	Thu Jun 27 14:45:22 2019 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary reflection test for records
+ * @modules jdk.compiler/com.sun.tools.javac.util
+ */
+
+import java.lang.reflect.*;
+import java.util.List;
+import com.sun.tools.javac.util.Assert;
+
+public class RecordReflectionTest {
+
+    class NoRecord {}
+
+    record R1();
+
+    record R2(int i, int j);
+
+    record R3(List<String> ls);
+
+    public static void main(String... args) throws Throwable {
+        Class<?> noRecordClass = NoRecord.class;
+        Assert.check(!noRecordClass.isRecord());
+        Assert.check(noRecordClass.getRecordAccessors().length == 0);
+
+        RecordReflectionTest recordReflectionTest = new RecordReflectionTest();
+        recordReflectionTest.checkRecordReflection(new R1(), 0, null, null);
+        recordReflectionTest.checkRecordReflection(new R2(1, 2), 2, new Object[]{1, 2}, new String[]{"int", "int"});
+        recordReflectionTest.checkRecordReflection(new R3(List.of("1")), 1, new Object[]{List.of("1")}, new String[]{"java.util.List<java.lang.String>"});
+    }
+
+    void checkRecordReflection(Object recordOb, int numberOfComponents, Object[] values, String[] signatures) throws Throwable {
+        Class<?> recordClass = recordOb.getClass();
+        Assert.check(recordClass.isRecord());
+        Method[] accessors = recordClass.getRecordAccessors();
+        Assert.check(accessors.length == numberOfComponents);
+        int i = 0;
+        for (Method m : accessors) {
+            Assert.check(m.invoke(recordOb).equals(values[i]));
+            Assert.check(m.getGenericReturnType().toString().equals(signatures[i]), String.format("signature of method \"%s\" different from expected signature \"%s\"", m.getGenericReturnType(), signatures[i]));
+            i++;
+        }
+    }
+}