Mercurial > hg > graal-jvmci-8
comparison src/share/vm/interpreter/rewriter.cpp @ 6266:1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
6984705: JSR 292 method handle creation should not go through JNI
Summary: remove assembly code for JDK 7 chained method handles
Reviewed-by: jrose, twisti, kvn, mhaupt
Contributed-by: John Rose <john.r.rose@oracle.com>, Christian Thalinger <christian.thalinger@oracle.com>, Michael Haupt <michael.haupt@oracle.com>
author | twisti |
---|---|
date | Tue, 24 Jul 2012 10:51:00 -0700 |
parents | d3b9f2be46ab |
children | 957c266d8bc5 da91efe96a93 |
comparison
equal
deleted
inserted
replaced
6241:aba91a731143 | 6266:1d7922586cf6 |
---|---|
31 #include "memory/resourceArea.hpp" | 31 #include "memory/resourceArea.hpp" |
32 #include "oops/generateOopMap.hpp" | 32 #include "oops/generateOopMap.hpp" |
33 #include "oops/objArrayOop.hpp" | 33 #include "oops/objArrayOop.hpp" |
34 #include "oops/oop.inline.hpp" | 34 #include "oops/oop.inline.hpp" |
35 #include "prims/methodComparator.hpp" | 35 #include "prims/methodComparator.hpp" |
36 #include "prims/methodHandles.hpp" | |
36 | 37 |
37 // Computes a CPC map (new_index -> original_index) for constant pool entries | 38 // Computes a CPC map (new_index -> original_index) for constant pool entries |
38 // that are referred to by the interpreter at runtime via the constant pool cache. | 39 // that are referred to by the interpreter at runtime via the constant pool cache. |
39 // Also computes a CP map (original_index -> new_index). | 40 // Also computes a CP map (original_index -> new_index). |
40 // Marks entries in CP which require additional processing. | 41 // Marks entries in CP which require additional processing. |
41 void Rewriter::compute_index_maps() { | 42 void Rewriter::compute_index_maps() { |
42 const int length = _pool->length(); | 43 const int length = _pool->length(); |
43 init_cp_map(length); | 44 init_cp_map(length); |
44 jint tag_mask = 0; | 45 bool saw_mh_symbol = false; |
45 for (int i = 0; i < length; i++) { | 46 for (int i = 0; i < length; i++) { |
46 int tag = _pool->tag_at(i).value(); | 47 int tag = _pool->tag_at(i).value(); |
47 tag_mask |= (1 << tag); | |
48 switch (tag) { | 48 switch (tag) { |
49 case JVM_CONSTANT_InterfaceMethodref: | 49 case JVM_CONSTANT_InterfaceMethodref: |
50 case JVM_CONSTANT_Fieldref : // fall through | 50 case JVM_CONSTANT_Fieldref : // fall through |
51 case JVM_CONSTANT_Methodref : // fall through | 51 case JVM_CONSTANT_Methodref : // fall through |
52 case JVM_CONSTANT_MethodHandle : // fall through | 52 case JVM_CONSTANT_MethodHandle : // fall through |
53 case JVM_CONSTANT_MethodType : // fall through | 53 case JVM_CONSTANT_MethodType : // fall through |
54 case JVM_CONSTANT_InvokeDynamic : // fall through | 54 case JVM_CONSTANT_InvokeDynamic : // fall through |
55 add_cp_cache_entry(i); | 55 add_cp_cache_entry(i); |
56 break; | 56 break; |
57 case JVM_CONSTANT_Utf8: | |
58 if (_pool->symbol_at(i) == vmSymbols::java_lang_invoke_MethodHandle()) | |
59 saw_mh_symbol = true; | |
60 break; | |
57 } | 61 } |
58 } | 62 } |
59 | 63 |
60 guarantee((int)_cp_cache_map.length()-1 <= (int)((u2)-1), | 64 guarantee((int)_cp_cache_map.length()-1 <= (int)((u2)-1), |
61 "all cp cache indexes fit in a u2"); | 65 "all cp cache indexes fit in a u2"); |
62 | 66 |
63 _have_invoke_dynamic = ((tag_mask & (1 << JVM_CONSTANT_InvokeDynamic)) != 0); | 67 if (saw_mh_symbol) |
68 _method_handle_invokers.initialize(length, (int)0); | |
64 } | 69 } |
65 | 70 |
66 // Unrewrite the bytecodes if an error occurs. | 71 // Unrewrite the bytecodes if an error occurs. |
67 void Rewriter::restore_bytecodes() { | 72 void Rewriter::restore_bytecodes() { |
68 int len = _methods->length(); | 73 int len = _methods->length(); |
78 const int length = _cp_cache_map.length(); | 83 const int length = _cp_cache_map.length(); |
79 constantPoolCacheOop cache = | 84 constantPoolCacheOop cache = |
80 oopFactory::new_constantPoolCache(length, CHECK); | 85 oopFactory::new_constantPoolCache(length, CHECK); |
81 No_Safepoint_Verifier nsv; | 86 No_Safepoint_Verifier nsv; |
82 cache->initialize(_cp_cache_map); | 87 cache->initialize(_cp_cache_map); |
83 | |
84 // Don't bother with the next pass if there is no JVM_CONSTANT_InvokeDynamic. | |
85 if (_have_invoke_dynamic) { | |
86 for (int i = 0; i < length; i++) { | |
87 int pool_index = cp_cache_entry_pool_index(i); | |
88 if (pool_index >= 0 && | |
89 _pool->tag_at(pool_index).is_invoke_dynamic()) { | |
90 int bsm_index = _pool->invoke_dynamic_bootstrap_method_ref_index_at(pool_index); | |
91 assert(_pool->tag_at(bsm_index).is_method_handle(), "must be a MH constant"); | |
92 // There is a CP cache entry holding the BSM for these calls. | |
93 int bsm_cache_index = cp_entry_to_cp_cache(bsm_index); | |
94 cache->entry_at(i)->initialize_bootstrap_method_index_in_cache(bsm_cache_index); | |
95 } | |
96 } | |
97 } | |
98 | |
99 _pool->set_cache(cache); | 88 _pool->set_cache(cache); |
100 cache->set_constant_pool(_pool()); | 89 cache->set_constant_pool(_pool()); |
101 } | 90 } |
102 | 91 |
103 | 92 |
146 address p = bcp + offset; | 135 address p = bcp + offset; |
147 if (!reverse) { | 136 if (!reverse) { |
148 int cp_index = Bytes::get_Java_u2(p); | 137 int cp_index = Bytes::get_Java_u2(p); |
149 int cache_index = cp_entry_to_cp_cache(cp_index); | 138 int cache_index = cp_entry_to_cp_cache(cp_index); |
150 Bytes::put_native_u2(p, cache_index); | 139 Bytes::put_native_u2(p, cache_index); |
140 if (!_method_handle_invokers.is_empty()) | |
141 maybe_rewrite_invokehandle(p - 1, cp_index, reverse); | |
151 } else { | 142 } else { |
152 int cache_index = Bytes::get_native_u2(p); | 143 int cache_index = Bytes::get_native_u2(p); |
153 int pool_index = cp_cache_entry_pool_index(cache_index); | 144 int pool_index = cp_cache_entry_pool_index(cache_index); |
154 Bytes::put_Java_u2(p, pool_index); | 145 Bytes::put_Java_u2(p, pool_index); |
146 if (!_method_handle_invokers.is_empty()) | |
147 maybe_rewrite_invokehandle(p - 1, pool_index, reverse); | |
148 } | |
149 } | |
150 | |
151 | |
152 // Adjust the invocation bytecode for a signature-polymorphic method (MethodHandle.invoke, etc.) | |
153 void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, bool reverse) { | |
154 if (!reverse) { | |
155 if ((*opc) == (u1)Bytecodes::_invokevirtual || | |
156 // allow invokespecial as an alias, although it would be very odd: | |
157 (*opc) == (u1)Bytecodes::_invokespecial) { | |
158 assert(_pool->tag_at(cp_index).is_method(), "wrong index"); | |
159 // Determine whether this is a signature-polymorphic method. | |
160 if (cp_index >= _method_handle_invokers.length()) return; | |
161 int status = _method_handle_invokers[cp_index]; | |
162 assert(status >= -1 && status <= 1, "oob tri-state"); | |
163 if (status == 0) { | |
164 if (_pool->klass_ref_at_noresolve(cp_index) == vmSymbols::java_lang_invoke_MethodHandle() && | |
165 MethodHandles::is_signature_polymorphic_name(SystemDictionary::MethodHandle_klass(), | |
166 _pool->name_ref_at(cp_index))) | |
167 status = +1; | |
168 else | |
169 status = -1; | |
170 _method_handle_invokers[cp_index] = status; | |
171 } | |
172 // We use a special internal bytecode for such methods (if non-static). | |
173 // The basic reason for this is that such methods need an extra "appendix" argument | |
174 // to transmit the call site's intended call type. | |
175 if (status > 0) { | |
176 (*opc) = (u1)Bytecodes::_invokehandle; | |
177 } | |
178 } | |
179 } else { | |
180 // Do not need to look at cp_index. | |
181 if ((*opc) == (u1)Bytecodes::_invokehandle) { | |
182 (*opc) = (u1)Bytecodes::_invokevirtual; | |
183 // Ignore corner case of original _invokespecial instruction. | |
184 // This is safe because (a) the signature polymorphic method was final, and | |
185 // (b) the implementation of MethodHandle will not call invokespecial on it. | |
186 } | |
155 } | 187 } |
156 } | 188 } |
157 | 189 |
158 | 190 |
159 void Rewriter::rewrite_invokedynamic(address bcp, int offset, bool reverse) { | 191 void Rewriter::rewrite_invokedynamic(address bcp, int offset, bool reverse) { |
295 case Bytecodes::_putfield : // fall through | 327 case Bytecodes::_putfield : // fall through |
296 case Bytecodes::_invokevirtual : // fall through | 328 case Bytecodes::_invokevirtual : // fall through |
297 case Bytecodes::_invokespecial : // fall through | 329 case Bytecodes::_invokespecial : // fall through |
298 case Bytecodes::_invokestatic : | 330 case Bytecodes::_invokestatic : |
299 case Bytecodes::_invokeinterface: | 331 case Bytecodes::_invokeinterface: |
332 case Bytecodes::_invokehandle : // if reverse=true | |
300 rewrite_member_reference(bcp, prefix_length+1, reverse); | 333 rewrite_member_reference(bcp, prefix_length+1, reverse); |
301 break; | 334 break; |
302 case Bytecodes::_invokedynamic: | 335 case Bytecodes::_invokedynamic: |
303 rewrite_invokedynamic(bcp, prefix_length+1, reverse); | 336 rewrite_invokedynamic(bcp, prefix_length+1, reverse); |
304 break; | 337 break; |
305 case Bytecodes::_ldc: | 338 case Bytecodes::_ldc: |
306 case Bytecodes::_fast_aldc: | 339 case Bytecodes::_fast_aldc: // if reverse=true |
307 maybe_rewrite_ldc(bcp, prefix_length+1, false, reverse); | 340 maybe_rewrite_ldc(bcp, prefix_length+1, false, reverse); |
308 break; | 341 break; |
309 case Bytecodes::_ldc_w: | 342 case Bytecodes::_ldc_w: |
310 case Bytecodes::_fast_aldc_w: | 343 case Bytecodes::_fast_aldc_w: // if reverse=true |
311 maybe_rewrite_ldc(bcp, prefix_length+1, true, reverse); | 344 maybe_rewrite_ldc(bcp, prefix_length+1, true, reverse); |
312 break; | 345 break; |
313 case Bytecodes::_jsr : // fall through | 346 case Bytecodes::_jsr : // fall through |
314 case Bytecodes::_jsr_w : nof_jsrs++; break; | 347 case Bytecodes::_jsr_w : nof_jsrs++; break; |
315 case Bytecodes::_monitorenter : // fall through | 348 case Bytecodes::_monitorenter : // fall through |