hotspot/src/share/vm/interpreter/rewriter.cpp
changeset 13728 882756847a04
parent 13391 30245956af37
child 13929 8da0dc50a6e4
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Fri Aug 31 16:39:35 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Sat Sep 01 13:25:18 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, 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
@@ -27,6 +27,7 @@
 #include "interpreter/interpreter.hpp"
 #include "interpreter/rewriter.hpp"
 #include "memory/gcLocker.hpp"
+#include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/generateOopMap.hpp"
@@ -41,7 +42,7 @@
 // Marks entries in CP which require additional processing.
 void Rewriter::compute_index_maps() {
   const int length  = _pool->length();
-  init_cp_map(length);
+  init_maps(length);
   bool saw_mh_symbol = false;
   for (int i = 0; i < length; i++) {
     int tag = _pool->tag_at(i).value();
@@ -49,10 +50,13 @@
       case JVM_CONSTANT_InterfaceMethodref:
       case JVM_CONSTANT_Fieldref          : // fall through
       case JVM_CONSTANT_Methodref         : // fall through
+        add_cp_cache_entry(i);
+        break;
+      case JVM_CONSTANT_String:
+      case JVM_CONSTANT_Object:
       case JVM_CONSTANT_MethodHandle      : // fall through
       case JVM_CONSTANT_MethodType        : // fall through
-      case JVM_CONSTANT_InvokeDynamic     : // fall through
-        add_cp_cache_entry(i);
+        add_resolved_references_entry(i);
         break;
       case JVM_CONSTANT_Utf8:
         if (_pool->symbol_at(i) == vmSymbols::java_lang_invoke_MethodHandle())
@@ -61,6 +65,9 @@
     }
   }
 
+  // Record limits of resolved reference map for constant pool cache indices
+  record_map_limits();
+
   guarantee((int)_cp_cache_map.length()-1 <= (int)((u2)-1),
             "all cp cache indexes fit in a u2");
 
@@ -73,7 +80,7 @@
   int len = _methods->length();
 
   for (int i = len-1; i >= 0; i--) {
-    methodOop method = (methodOop)_methods->obj_at(i);
+    Method* method = _methods->at(i);
     scan_method(method, true);
   }
 }
@@ -81,10 +88,17 @@
 // Creates a constant pool cache given a CPC map
 void Rewriter::make_constant_pool_cache(TRAPS) {
   const int length = _cp_cache_map.length();
-  constantPoolCacheOop cache =
-      oopFactory::new_constantPoolCache(length, CHECK);
+  ClassLoaderData* loader_data = _pool->pool_holder()->class_loader_data();
+  ConstantPoolCache* cache =
+      ConstantPoolCache::allocate(loader_data, length, CHECK);
+
+  // initialize object cache in constant pool
+  _pool->initialize_resolved_references(loader_data, _resolved_references_map,
+                                        _resolved_reference_limit,
+                                        CHECK);
+
   No_Safepoint_Verifier nsv;
-  cache->initialize(_cp_cache_map);
+  cache->initialize(_cp_cache_map, _invokedynamic_references_map);
   _pool->set_cache(cache);
   cache->set_constant_pool(_pool());
 }
@@ -138,19 +152,19 @@
     int  cache_index = cp_entry_to_cp_cache(cp_index);
     Bytes::put_native_u2(p, cache_index);
     if (!_method_handle_invokers.is_empty())
-      maybe_rewrite_invokehandle(p - 1, cp_index, reverse);
+      maybe_rewrite_invokehandle(p - 1, cp_index, cache_index, reverse);
   } else {
     int cache_index = Bytes::get_native_u2(p);
     int pool_index = cp_cache_entry_pool_index(cache_index);
     Bytes::put_Java_u2(p, pool_index);
     if (!_method_handle_invokers.is_empty())
-      maybe_rewrite_invokehandle(p - 1, pool_index, reverse);
+      maybe_rewrite_invokehandle(p - 1, pool_index, cache_index, reverse);
   }
 }
 
 
 // Adjust the invocation bytecode for a signature-polymorphic method (MethodHandle.invoke, etc.)
-void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, bool reverse) {
+void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse) {
   if (!reverse) {
     if ((*opc) == (u1)Bytecodes::_invokevirtual ||
         // allow invokespecial as an alias, although it would be very odd:
@@ -163,10 +177,13 @@
       if (status == 0) {
         if (_pool->klass_ref_at_noresolve(cp_index) == vmSymbols::java_lang_invoke_MethodHandle() &&
             MethodHandles::is_signature_polymorphic_name(SystemDictionary::MethodHandle_klass(),
-                                                         _pool->name_ref_at(cp_index)))
+                                                         _pool->name_ref_at(cp_index))) {
+          // we may need a resolved_refs entry for the appendix
+          add_invokedynamic_resolved_references_entry(cp_index, cache_index);
           status = +1;
-        else
+        } else {
           status = -1;
+        }
         _method_handle_invokers[cp_index] = status;
       }
       // We use a special internal bytecode for such methods (if non-static).
@@ -193,9 +210,8 @@
   assert(p[-1] == Bytecodes::_invokedynamic, "not invokedynamic bytecode");
   if (!reverse) {
     int cp_index = Bytes::get_Java_u2(p);
-    int cpc  = maybe_add_cp_cache_entry(cp_index);  // add lazily
-    int cpc2 = add_secondary_cp_cache_entry(cpc);
-
+    int cache_index = add_invokedynamic_cp_cache_entry(cp_index);
+    add_invokedynamic_resolved_references_entry(cp_index, cache_index);
     // Replace the trailing four bytes with a CPC index for the dynamic
     // call site.  Unlike other CPC entries, there is one per bytecode,
     // not just one per distinct CP entry.  In other words, the
@@ -204,17 +220,17 @@
     // all these entries.  That is the main reason invokedynamic
     // must have a five-byte instruction format.  (Of course, other JVM
     // implementations can use the bytes for other purposes.)
-    Bytes::put_native_u4(p, constantPoolCacheOopDesc::encode_secondary_index(cpc2));
+    Bytes::put_native_u4(p, ConstantPool::encode_invokedynamic_index(cache_index));
     // Note: We use native_u4 format exclusively for 4-byte indexes.
   } else {
-    int cache_index = constantPoolCacheOopDesc::decode_secondary_index(
+    // callsite index
+    int cache_index = ConstantPool::decode_invokedynamic_index(
                         Bytes::get_native_u4(p));
-    int secondary_index = cp_cache_secondary_entry_main_index(cache_index);
-    int pool_index = cp_cache_entry_pool_index(secondary_index);
-    assert(_pool->tag_at(pool_index).is_invoke_dynamic(), "wrong index");
+    int cp_index = cp_cache_entry_pool_index(cache_index);
+    assert(_pool->tag_at(cp_index).is_invoke_dynamic(), "wrong index");
     // zero out 4 bytes
     Bytes::put_Java_u4(p, 0);
-    Bytes::put_Java_u2(p, pool_index);
+    Bytes::put_Java_u2(p, cp_index);
   }
 }
 
@@ -227,16 +243,16 @@
     address p = bcp + offset;
     int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p);
     constantTag tag = _pool->tag_at(cp_index).value();
-    if (tag.is_method_handle() || tag.is_method_type()) {
-      int cache_index = cp_entry_to_cp_cache(cp_index);
+    if (tag.is_method_handle() || tag.is_method_type() || tag.is_string() || tag.is_object()) {
+      int ref_index = cp_entry_to_resolved_references(cp_index);
       if (is_wide) {
         (*bcp) = Bytecodes::_fast_aldc_w;
-        assert(cache_index == (u2)cache_index, "index overflow");
-        Bytes::put_native_u2(p, cache_index);
+        assert(ref_index == (u2)ref_index, "index overflow");
+        Bytes::put_native_u2(p, ref_index);
       } else {
         (*bcp) = Bytecodes::_fast_aldc;
-        assert(cache_index == (u1)cache_index, "index overflow");
-        (*p) = (u1)cache_index;
+        assert(ref_index == (u1)ref_index, "index overflow");
+        (*p) = (u1)ref_index;
       }
     }
   } else {
@@ -244,8 +260,8 @@
               (is_wide ? Bytecodes::_fast_aldc_w : Bytecodes::_fast_aldc);
     if ((*bcp) == rewritten_bc) {
       address p = bcp + offset;
-      int cache_index = is_wide ? Bytes::get_native_u2(p) : (u1)(*p);
-      int pool_index = cp_cache_entry_pool_index(cache_index);
+      int ref_index = is_wide ? Bytes::get_native_u2(p) : (u1)(*p);
+      int pool_index = resolved_references_entry_to_pool_index(ref_index);
       if (is_wide) {
         (*bcp) = Bytecodes::_ldc_w;
         assert(pool_index == (u2)pool_index, "index overflow");
@@ -261,14 +277,14 @@
 
 
 // Rewrites a method given the index_map information
-void Rewriter::scan_method(methodOop method, bool reverse) {
+void Rewriter::scan_method(Method* method, bool reverse) {
 
   int nof_jsrs = 0;
   bool has_monitor_bytecodes = false;
 
   {
     // We cannot tolerate a GC in this block, because we've
-    // cached the bytecodes in 'code_base'. If the methodOop
+    // cached the bytecodes in 'code_base'. If the Method*
     // moves, the bytecodes will also move.
     No_Safepoint_Verifier nsv;
     Bytecodes::Code c;
@@ -371,16 +387,6 @@
   ResolveOopMapConflicts romc(method);
   methodHandle original_method = method;
   method = romc.do_potential_rewrite(CHECK_(methodHandle()));
-  if (method() != original_method()) {
-    // Insert invalid bytecode into original methodOop and set
-    // interpreter entrypoint, so that a executing this method
-    // will manifest itself in an easy recognizable form.
-    address bcp = original_method->bcp_from(0);
-    *bcp = (u1)Bytecodes::_shouldnotreachhere;
-    int kind = Interpreter::method_kind(original_method);
-    original_method->set_interpreter_kind(kind);
-  }
-
   // Update monitor matching info.
   if (romc.monitor_safe()) {
     method->set_guaranteed_monitor_matching();
@@ -396,28 +402,28 @@
 }
 
 
-void Rewriter::rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS) {
+void Rewriter::rewrite(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS) {
   ResourceMark rm(THREAD);
   Rewriter     rw(klass, cpool, methods, CHECK);
   // (That's all, folks.)
 }
 
 
-Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS)
+Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS)
   : _klass(klass),
     _pool(cpool),
     _methods(methods)
 {
   assert(_pool->cache() == NULL, "constant pool cache must not be set yet");
 
-  // determine index maps for methodOop rewriting
+  // determine index maps for Method* rewriting
   compute_index_maps();
 
   if (RegisterFinalizersAtInit && _klass->name() == vmSymbols::java_lang_Object()) {
     bool did_rewrite = false;
     int i = _methods->length();
     while (i-- > 0) {
-      methodOop method = (methodOop)_methods->obj_at(i);
+      Method* method = _methods->at(i);
       if (method->intrinsic_id() == vmIntrinsics::_Object_init) {
         // rewrite the return bytecodes of Object.<init> to register the
         // object for finalization if needed.
@@ -434,7 +440,7 @@
   int len = _methods->length();
 
   for (int i = len-1; i >= 0; i--) {
-    methodOop method = (methodOop)_methods->obj_at(i);
+    Method* method = _methods->at(i);
     scan_method(method);
   }
 
@@ -455,20 +461,19 @@
 // Link and check jvmti dependencies while we're iterating over the methods.
 // JSR292 code calls with a different set of methods, so two entry points.
 void Rewriter::relocate_and_link(instanceKlassHandle this_oop, TRAPS) {
-  objArrayHandle methods(THREAD, this_oop->methods());
-  relocate_and_link(this_oop, methods, THREAD);
+  relocate_and_link(this_oop, this_oop->methods(), THREAD);
 }
 
 void Rewriter::relocate_and_link(instanceKlassHandle this_oop,
-                                 objArrayHandle methods, TRAPS) {
+                                 Array<Method*>* methods, TRAPS) {
   int len = methods->length();
   for (int i = len-1; i >= 0; i--) {
-    methodHandle m(THREAD, (methodOop)methods->obj_at(i));
+    methodHandle m(THREAD, methods->at(i));
 
     if (m->has_jsrs()) {
       m = rewrite_jsrs(m, CHECK);
       // Method might have gotten rewritten.
-      methods->obj_at_put(i, m());
+      methods->at_put(i, m());
     }
 
     // Set up method entry points for compiler and interpreter    .
@@ -481,7 +486,7 @@
       for (int j = i; j >= 0 && j >= i-4; j--) {
         if ((++nmc % 1000) == 0)  tty->print_cr("Have run MethodComparator %d times...", nmc);
         bool z = MethodComparator::methods_EMCP(m(),
-                   (methodOop)methods->obj_at(j));
+                   methods->at(j));
         if (j == i && !z) {
           tty->print("MethodComparator FAIL: "); m->print(); m->print_codes();
           assert(z, "method must compare equal to itself");