--- 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");