hotspot/src/share/vm/classfile/classFileParser.cpp
changeset 2534 08dac9ce0cd7
parent 2269 ee9da33d43ab
child 3273 6acf7084b1d3
child 3575 224791e7ecab
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Apr 08 00:12:59 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Apr 08 10:56:49 2009 -0700
@@ -1842,6 +1842,11 @@
     _has_vanilla_constructor = true;
   }
 
+  if (EnableMethodHandles && m->is_method_handle_invoke()) {
+    THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
+               "Method handle invokers must be defined internally to the VM", nullHandle);
+  }
+
   return m;
 }
 
@@ -2465,9 +2470,84 @@
 }
 
 
+// Force MethodHandle.vmentry to be an unmanaged pointer.
+// There is no way for a classfile to express this, so we must help it.
+void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp,
+                                                    typeArrayHandle* fields_ptr,
+                                                    FieldAllocationCount *fac_ptr,
+                                                    TRAPS) {
+  // Add fake fields for java.dyn.MethodHandle instances
+  //
+  // This is not particularly nice, but since there is no way to express
+  // a native wordSize field in Java, we must do it at this level.
+
+  if (!EnableMethodHandles)  return;
+
+  int word_sig_index = 0;
+  const int cp_size = cp->length();
+  for (int index = 1; index < cp_size; index++) {
+    if (cp->tag_at(index).is_utf8() &&
+        cp->symbol_at(index) == vmSymbols::machine_word_signature()) {
+      word_sig_index = index;
+      break;
+    }
+  }
+
+  if (word_sig_index == 0)
+    THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
+              "missing I or J signature (for vmentry) in java.dyn.MethodHandle");
+
+  bool found_vmentry = false;
+
+  const int n = (*fields_ptr)()->length();
+  for (int i = 0; i < n; i += instanceKlass::next_offset) {
+    int name_index = (*fields_ptr)->ushort_at(i + instanceKlass::name_index_offset);
+    int sig_index  = (*fields_ptr)->ushort_at(i + instanceKlass::signature_index_offset);
+    int acc_flags  = (*fields_ptr)->ushort_at(i + instanceKlass::access_flags_offset);
+    symbolOop f_name = cp->symbol_at(name_index);
+    symbolOop f_sig  = cp->symbol_at(sig_index);
+    if (f_sig == vmSymbols::byte_signature() &&
+        f_name == vmSymbols::vmentry_name() &&
+        (acc_flags & JVM_ACC_STATIC) == 0) {
+      // Adjust the field type from byte to an unmanaged pointer.
+      assert(fac_ptr->nonstatic_byte_count > 0, "");
+      fac_ptr->nonstatic_byte_count -= 1;
+      (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset,
+                                   word_sig_index);
+      if (wordSize == jintSize) {
+        fac_ptr->nonstatic_word_count += 1;
+      } else {
+        fac_ptr->nonstatic_double_count += 1;
+      }
+
+      FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i+4);
+      assert(atype == NONSTATIC_BYTE, "");
+      FieldAllocationType new_atype = NONSTATIC_WORD;
+      if (wordSize > jintSize) {
+        if (Universe::field_type_should_be_aligned(T_LONG)) {
+          atype = NONSTATIC_ALIGNED_DOUBLE;
+        } else {
+          atype = NONSTATIC_DOUBLE;
+        }
+      }
+      (*fields_ptr)->ushort_at_put(i+4, new_atype);
+
+      found_vmentry = true;
+      break;
+    }
+  }
+
+  if (!found_vmentry)
+    THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
+              "missing vmentry byte field in java.dyn.MethodHandle");
+
+}
+
+
 instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
                                                     Handle class_loader,
                                                     Handle protection_domain,
+                                                    KlassHandle host_klass,
                                                     GrowableArray<Handle>* cp_patches,
                                                     symbolHandle& parsed_name,
                                                     TRAPS) {
@@ -2500,6 +2580,7 @@
     }
   }
 
+  _host_klass = host_klass;
   _cp_patches = cp_patches;
 
   instanceKlassHandle nullHandle;
@@ -2808,6 +2889,11 @@
       java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle));
     }
 
+    // adjust the vmentry field declaration in java.dyn.MethodHandle
+    if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) {
+      java_dyn_MethodHandle_fix_pre(cp, &fields, &fac, CHECK_(nullHandle));
+    }
+
     // Add a fake "discovered" field if it is not present
     // for compatibility with earlier jdk's.
     if (class_name() == vmSymbols::java_lang_ref_Reference()
@@ -3134,7 +3220,7 @@
     this_klass->set_method_ordering(method_ordering());
     this_klass->set_initial_method_idnum(methods->length());
     this_klass->set_name(cp->klass_name_at(this_class_index));
-    if (LinkWellKnownClasses)  // I am well known to myself
+    if (LinkWellKnownClasses || is_anonymous())  // I am well known to myself
       cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
     this_klass->set_protection_domain(protection_domain());
     this_klass->set_fields_annotations(fields_annotations());