Mercurial > hg > graal-compiler
diff src/share/vm/interpreter/rewriter.cpp @ 6275:957c266d8bc5
Merge with http://hg.openjdk.java.net/hsx/hsx24/hotspot/
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 21 Aug 2012 10:39:19 +0200 |
parents | 723df37192d6 1d7922586cf6 |
children | e522a00b91aa |
line wrap: on
line diff
--- a/src/share/vm/interpreter/rewriter.cpp Mon Aug 20 15:21:31 2012 +0200 +++ b/src/share/vm/interpreter/rewriter.cpp Tue Aug 21 10:39:19 2012 +0200 @@ -33,6 +33,7 @@ #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" #include "prims/methodComparator.hpp" +#include "prims/methodHandles.hpp" // Computes a CPC map (new_index -> original_index) for constant pool entries // that are referred to by the interpreter at runtime via the constant pool cache. @@ -41,10 +42,9 @@ void Rewriter::compute_index_maps() { const int length = _pool->length(); init_cp_map(length); - jint tag_mask = 0; + bool saw_mh_symbol = false; for (int i = 0; i < length; i++) { int tag = _pool->tag_at(i).value(); - tag_mask |= (1 << tag); switch (tag) { case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_Fieldref : // fall through @@ -54,13 +54,18 @@ case JVM_CONSTANT_InvokeDynamic : // fall through add_cp_cache_entry(i); break; + case JVM_CONSTANT_Utf8: + if (_pool->symbol_at(i) == vmSymbols::java_lang_invoke_MethodHandle()) + saw_mh_symbol = true; + break; } } guarantee((int)_cp_cache_map.length()-1 <= (int)((u2)-1), "all cp cache indexes fit in a u2"); - _have_invoke_dynamic = ((tag_mask & (1 << JVM_CONSTANT_InvokeDynamic)) != 0); + if (saw_mh_symbol) + _method_handle_invokers.initialize(length, (int)0); } // Unrewrite the bytecodes if an error occurs. @@ -80,22 +85,6 @@ oopFactory::new_constantPoolCache(length, CHECK); No_Safepoint_Verifier nsv; cache->initialize(_cp_cache_map); - - // Don't bother with the next pass if there is no JVM_CONSTANT_InvokeDynamic. - if (_have_invoke_dynamic) { - for (int i = 0; i < length; i++) { - int pool_index = cp_cache_entry_pool_index(i); - if (pool_index >= 0 && - _pool->tag_at(pool_index).is_invoke_dynamic()) { - int bsm_index = _pool->invoke_dynamic_bootstrap_method_ref_index_at(pool_index); - assert(_pool->tag_at(bsm_index).is_method_handle(), "must be a MH constant"); - // There is a CP cache entry holding the BSM for these calls. - int bsm_cache_index = cp_entry_to_cp_cache(bsm_index); - cache->entry_at(i)->initialize_bootstrap_method_index_in_cache(bsm_cache_index); - } - } - } - _pool->set_cache(cache); cache->set_constant_pool(_pool()); } @@ -152,10 +141,53 @@ int cp_index = Bytes::get_Java_u2(p); 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); } 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); + } +} + + +// Adjust the invocation bytecode for a signature-polymorphic method (MethodHandle.invoke, etc.) +void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, bool reverse) { + if (!reverse) { + if ((*opc) == (u1)Bytecodes::_invokevirtual || + // allow invokespecial as an alias, although it would be very odd: + (*opc) == (u1)Bytecodes::_invokespecial) { + assert(_pool->tag_at(cp_index).is_method(), "wrong index"); + // Determine whether this is a signature-polymorphic method. + if (cp_index >= _method_handle_invokers.length()) return; + int status = _method_handle_invokers[cp_index]; + assert(status >= -1 && status <= 1, "oob tri-state"); + 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))) + status = +1; + else + status = -1; + _method_handle_invokers[cp_index] = status; + } + // We use a special internal bytecode for such methods (if non-static). + // The basic reason for this is that such methods need an extra "appendix" argument + // to transmit the call site's intended call type. + if (status > 0) { + (*opc) = (u1)Bytecodes::_invokehandle; + } + } + } else { + // Do not need to look at cp_index. + if ((*opc) == (u1)Bytecodes::_invokehandle) { + (*opc) = (u1)Bytecodes::_invokevirtual; + // Ignore corner case of original _invokespecial instruction. + // This is safe because (a) the signature polymorphic method was final, and + // (b) the implementation of MethodHandle will not call invokespecial on it. + } } } @@ -303,17 +335,18 @@ case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : case Bytecodes::_invokeinterface: + case Bytecodes::_invokehandle : // if reverse=true rewrite_member_reference(bcp, prefix_length+1, reverse); break; case Bytecodes::_invokedynamic: rewrite_invokedynamic(bcp, prefix_length+1, reverse); break; case Bytecodes::_ldc: - case Bytecodes::_fast_aldc: + case Bytecodes::_fast_aldc: // if reverse=true maybe_rewrite_ldc(bcp, prefix_length+1, false, reverse); break; case Bytecodes::_ldc_w: - case Bytecodes::_fast_aldc_w: + case Bytecodes::_fast_aldc_w: // if reverse=true maybe_rewrite_ldc(bcp, prefix_length+1, true, reverse); break; case Bytecodes::_jsr : // fall through