Mercurial > hg > graal-compiler
comparison src/share/vm/graal/graalCompilerToVM.cpp @ 14106:ca37cb080dad
reorganized graalCompilerToVM.cpp
author | twisti |
---|---|
date | Thu, 06 Mar 2014 22:45:25 -0800 |
parents | f62c770c22be |
children | 800057208a2c |
comparison
equal
deleted
inserted
replaced
14105:f62c770c22be | 14106:ca37cb080dad |
---|---|
55 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ | 55 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ |
56 TRACE_graal_3("CompilerToVM::" #name); \ | 56 TRACE_graal_3("CompilerToVM::" #name); \ |
57 | 57 |
58 #define C2V_END } | 58 #define C2V_END } |
59 | 59 |
60 C2V_ENTRY(jbyteArray, initializeBytecode, (JNIEnv *env, jobject, jlong metaspace_method, jbyteArray result)) | |
61 methodHandle method = asMethod(metaspace_method); | |
62 ResourceMark rm; | |
63 | |
64 int code_size = method->code_size(); | |
65 jbyte* reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size); | |
66 | |
67 guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten"); | |
68 // iterate over all bytecodes and replace non-Java bytecodes | |
69 | |
70 for (BytecodeStream s(method); s.next() != Bytecodes::_illegal; ) { | |
71 Bytecodes::Code code = s.code(); | |
72 Bytecodes::Code raw_code = s.raw_code(); | |
73 int bci = s.bci(); | |
74 int len = s.instruction_size(); | |
75 | |
76 // Restore original byte code. | |
77 reconstituted_code[bci] = (jbyte) (s.is_wide()? Bytecodes::_wide : code); | |
78 if (len > 1) { | |
79 memcpy(&reconstituted_code[bci+1], s.bcp()+1, len-1); | |
80 } | |
81 | |
82 if (len > 1) { | |
83 // Restore the big-endian constant pool indexes. | |
84 // Cf. Rewriter::scan_method | |
85 switch (code) { | |
86 case Bytecodes::_getstatic: | |
87 case Bytecodes::_putstatic: | |
88 case Bytecodes::_getfield: | |
89 case Bytecodes::_putfield: | |
90 case Bytecodes::_invokevirtual: | |
91 case Bytecodes::_invokespecial: | |
92 case Bytecodes::_invokestatic: | |
93 case Bytecodes::_invokeinterface: | |
94 case Bytecodes::_invokehandle: { | |
95 int cp_index = Bytes::get_native_u2((address) &reconstituted_code[bci + 1]); | |
96 Bytes::put_Java_u2((address) &reconstituted_code[bci + 1], (u2) cp_index); | |
97 break; | |
98 } | |
99 | |
100 case Bytecodes::_invokedynamic: | |
101 int cp_index = Bytes::get_native_u4((address) &reconstituted_code[bci + 1]); | |
102 Bytes::put_Java_u4((address) &reconstituted_code[bci + 1], (u4) cp_index); | |
103 break; | |
104 } | |
105 | |
106 // Not all ldc byte code are rewritten. | |
107 switch (raw_code) { | |
108 case Bytecodes::_fast_aldc: { | |
109 int cpc_index = reconstituted_code[bci + 1] & 0xff; | |
110 int cp_index = method->constants()->object_to_cp_index(cpc_index); | |
111 assert(cp_index < method->constants()->length(), "sanity check"); | |
112 reconstituted_code[bci + 1] = (jbyte) cp_index; | |
113 break; | |
114 } | |
115 | |
116 case Bytecodes::_fast_aldc_w: { | |
117 int cpc_index = Bytes::get_native_u2((address) &reconstituted_code[bci + 1]); | |
118 int cp_index = method->constants()->object_to_cp_index(cpc_index); | |
119 assert(cp_index < method->constants()->length(), "sanity check"); | |
120 Bytes::put_Java_u2((address) &reconstituted_code[bci + 1], (u2) cp_index); | |
121 break; | |
122 } | |
123 } | |
124 } | |
125 } | |
126 | |
127 env->SetByteArrayRegion(result, 0, code_size, reconstituted_code); | |
128 | |
129 return result; | |
130 C2V_END | |
131 | |
132 C2V_VMENTRY(jint, exceptionTableLength, (JNIEnv *, jobject, jlong metaspace_method)) | |
133 ResourceMark rm; | |
134 methodHandle method = asMethod(metaspace_method); | |
135 return method->exception_table_length(); | |
136 C2V_END | |
137 | |
138 C2V_VMENTRY(jlong, exceptionTableStart, (JNIEnv *, jobject, jlong metaspace_method)) | |
139 ResourceMark rm; | |
140 methodHandle method = asMethod(metaspace_method); | |
141 assert(method->exception_table_length() != 0, "should be handled in Java code"); | |
142 return (jlong) (address) method->exception_table_start(); | |
143 C2V_END | |
144 | |
145 C2V_VMENTRY(jint, hasBalancedMonitors, (JNIEnv *, jobject, jlong metaspace_method)) | |
146 // Analyze the method to see if monitors are used properly. | |
147 methodHandle method(THREAD, asMethod(metaspace_method)); | |
148 { | |
149 EXCEPTION_MARK; | |
150 ResourceMark rm(THREAD); | |
151 GeneratePairingInfo gpi(method); | |
152 gpi.compute_map(CATCH); | |
153 if (!gpi.monitor_safe()) { | |
154 return false; | |
155 } | |
156 method->set_guaranteed_monitor_matching(); | |
157 } | |
158 return true; | |
159 C2V_END | |
160 | |
161 C2V_VMENTRY(jlong, getMetaspaceMethod, (JNIEnv *, jobject, jclass holder_handle, jint slot)) | |
162 oop java_class = JNIHandles::resolve(holder_handle); | |
163 Klass* holder = java_lang_Class::as_Klass(java_class); | |
164 methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot); | |
165 return (jlong) (address) method(); | |
166 } | |
167 | |
168 C2V_VMENTRY(jlong, findUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_method)) | |
169 methodHandle method = asMethod(metaspace_method); | |
170 KlassHandle holder = method->method_holder(); | |
171 assert(!holder->is_interface(), "should be handled in Java code"); | |
172 ResourceMark rm; | |
173 MutexLocker locker(Compile_lock); | |
174 Method* ucm = Dependencies::find_unique_concrete_method(holder(), method()); | |
175 return (jlong) (address) ucm; | |
176 C2V_END | |
177 | |
178 C2V_VMENTRY(jlong, getKlassImplementor, (JNIEnv *, jobject, jlong metaspace_klass)) | |
179 InstanceKlass* klass = (InstanceKlass*) asKlass(metaspace_klass); | |
180 return (jlong) (address) klass->implementor(); | |
181 C2V_END | |
182 | |
183 C2V_VMENTRY(void, initializeMethod,(JNIEnv *, jobject, jlong metaspace_method, jobject hotspot_method)) | |
184 methodHandle method = asMethod(metaspace_method); | |
185 InstanceKlass::cast(HotSpotResolvedJavaMethod::klass())->initialize(CHECK); | |
186 HotSpotResolvedJavaMethod::set_callerSensitive(hotspot_method, method->caller_sensitive()); | |
187 HotSpotResolvedJavaMethod::set_forceInline(hotspot_method, method->force_inline()); | |
188 HotSpotResolvedJavaMethod::set_dontInline(hotspot_method, method->dont_inline()); | |
189 HotSpotResolvedJavaMethod::set_ignoredBySecurityStackWalk(hotspot_method, method->is_ignored_by_security_stack_walk()); | |
190 C2V_END | |
191 | |
192 C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jlong metaspace_method)) | |
193 methodHandle method = asMethod(metaspace_method); | |
194 return !method->is_not_compilable() && !CompilerOracle::should_not_inline(method) && !method->dont_inline(); | |
195 C2V_END | |
196 | |
197 C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jlong metaspace_method)) | |
198 methodHandle method = asMethod(metaspace_method); | |
199 return CompilerOracle::should_inline(method) || method->force_inline(); | |
200 C2V_END | |
201 | |
202 C2V_ENTRY(jint, getCompiledCodeSize, (JNIEnv *env, jobject, jlong metaspace_method)) | |
203 nmethod* code = (asMethod(metaspace_method))->code(); | |
204 return code == NULL ? 0 : code->insts_size(); | |
205 C2V_END | |
206 | |
207 C2V_VMENTRY(jlong, lookupType, (JNIEnv *env, jobject, jstring jname, jclass accessing_class, jboolean eagerResolve)) | |
208 ResourceMark rm; | |
209 Handle name = JNIHandles::resolve(jname); | |
210 Symbol* class_name = java_lang_String::as_symbol(name, THREAD); | |
211 assert(class_name != NULL, "name to symbol creation failed"); | |
212 assert(class_name->size() > 1, "primitive types should be handled in Java code"); | |
213 | |
214 Klass* resolved_klass = NULL; | |
215 Handle class_loader; | |
216 Handle protection_domain; | |
217 if (JNIHandles::resolve(accessing_class) != NULL) { | |
218 Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class)); | |
219 class_loader = accessing_klass->class_loader(); | |
220 protection_domain = accessing_klass->protection_domain(); | |
221 } | |
222 | |
223 if (eagerResolve) { | |
224 resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, protection_domain, true, THREAD); | |
225 } else { | |
226 resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, THREAD); | |
227 } | |
228 | |
229 return (jlong) (address) resolved_klass; | |
230 C2V_END | |
231 | |
232 C2V_VMENTRY(jlong, lookupKlassByName, (JNIEnv *env, jobject, jstring name, jclass loading_class)) | |
233 KlassHandle loading_klass = java_lang_Class::as_Klass(JNIHandles::resolve(loading_class)); | |
234 Symbol* name_symbol = java_lang_String::as_symbol(JNIHandles::resolve(name), THREAD); | |
235 KlassHandle klass = GraalEnv::get_klass_by_name(loading_klass, name_symbol, false); | |
236 return (jlong) (address) klass(); | |
237 C2V_END | |
238 | |
239 C2V_VMENTRY(jobject, lookupConstantInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
240 ConstantPool* cp = (ConstantPool*) metaspace_constant_pool; | |
241 oop result = NULL; | |
242 constantTag tag = cp->tag_at(index); | |
243 switch (tag.value()) { | |
244 case JVM_CONSTANT_String: | |
245 result = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL); | |
246 break; | |
247 case JVM_CONSTANT_MethodHandle: | |
248 case JVM_CONSTANT_MethodHandleInError: | |
249 case JVM_CONSTANT_MethodType: | |
250 case JVM_CONSTANT_MethodTypeInError: | |
251 result = cp->resolve_constant_at(index, CHECK_NULL); | |
252 break; | |
253 default: | |
254 fatal(err_msg_res("unknown constant pool tag %s at cpi %d in %s", tag.internal_name(), index, cp->pool_holder()->name()->as_C_string())); | |
255 } | |
256 return JNIHandles::make_local(THREAD, result); | |
257 C2V_END | |
258 | |
259 C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
260 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
261 return cp->name_and_type_ref_index_at(index); | |
262 C2V_END | |
263 | |
264 C2V_VMENTRY(jlong, lookupNameRefInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
265 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
266 return (jlong) (address) cp->name_ref_at(index); | |
267 C2V_END | |
268 | |
269 C2V_VMENTRY(jlong, lookupSignatureRefInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
270 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
271 return (jlong) (address) cp->signature_ref_at(index); | |
272 C2V_END | |
273 | |
274 C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
275 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
276 return cp->klass_ref_index_at(index); | |
277 C2V_END | |
278 | |
279 C2V_VMENTRY(jlong, lookupKlassInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index, jbyte opcode)) | |
280 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
281 KlassHandle loading_klass(cp->pool_holder()); | |
282 bool is_accessible = false; | |
283 KlassHandle klass = GraalEnv::get_klass_by_index(cp, index, is_accessible, loading_klass); | |
284 if (klass.is_null()) { | |
285 // We have to lock the cpool to keep the oop from being resolved | |
286 // while we are accessing it. | |
287 MonitorLockerEx ml(cp->lock()); | |
288 constantTag tag = cp->tag_at(index); | |
289 if (tag.is_klass()) { | |
290 // The klass has been inserted into the constant pool | |
291 // very recently. | |
292 return (jlong) CompilerToVM::tag_pointer(cp->resolved_klass_at(index)); | |
293 } else if (tag.is_symbol()) { | |
294 return (jlong) CompilerToVM::tag_pointer(cp->symbol_at(index)); | |
295 } else { | |
296 assert(cp->tag_at(index).is_unresolved_klass(), "wrong tag"); | |
297 return (jlong) CompilerToVM::tag_pointer(cp->unresolved_klass_at(index)); | |
298 } | |
299 } | |
300 return (jlong) CompilerToVM::tag_pointer(klass()); | |
301 C2V_END | |
302 | |
303 C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
304 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
305 oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index); | |
306 return JNIHandles::make_local(THREAD, appendix_oop); | |
307 C2V_END | |
308 | |
309 C2V_VMENTRY(jlong, lookupMethodInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index, jbyte opcode)) | |
310 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
311 instanceKlassHandle pool_holder(cp->pool_holder()); | |
312 Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); | |
313 methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); | |
314 return (jlong) (address) method(); | |
315 C2V_END | |
316 | |
317 C2V_VMENTRY(void, loadReferencedTypeInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index, jbyte op)) | |
318 ConstantPool* cp = (ConstantPool*) metaspace_constant_pool; | |
319 Bytecodes::Code bc = (Bytecodes::Code) (((int) op) & 0xFF); | |
320 if (bc != Bytecodes::_checkcast && bc != Bytecodes::_instanceof && bc != Bytecodes::_new && bc != Bytecodes::_anewarray | |
321 && bc != Bytecodes::_multianewarray && bc != Bytecodes::_ldc && bc != Bytecodes::_ldc_w && bc != Bytecodes::_ldc2_w) | |
322 { | |
323 index = cp->remap_instruction_operand_from_cache(index); | |
324 } | |
325 constantTag tag = cp->tag_at(index); | |
326 if (tag.is_field_or_method()) { | |
327 index = cp->uncached_klass_ref_index_at(index); | |
328 tag = cp->tag_at(index); | |
329 } | |
330 | |
331 if (tag.is_unresolved_klass() || tag.is_klass()) { | |
332 Klass* klass = cp->klass_at(index, CHECK); | |
333 if (klass->oop_is_instance()) { | |
334 InstanceKlass::cast(klass)->initialize(CHECK); | |
335 } | |
336 } | |
337 C2V_END | |
338 | |
339 C2V_VMENTRY(jlong, resolveField, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index, jbyte opcode, jlongArray info_handle)) | |
340 ResourceMark rm; | |
341 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
342 Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF); | |
343 fieldDescriptor result; | |
344 LinkResolver::resolve_field_access(result, cp, index, Bytecodes::java_code(code), true, false, CHECK_0); | |
345 typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle); | |
346 assert(info != NULL && info->length() == 2, "must be"); | |
347 info->long_at_put(0, (jlong) result.access_flags().as_int()); | |
348 info->long_at_put(1, (jlong) result.offset()); | |
349 return (jlong) (address) result.field_holder(); | |
350 C2V_END | |
351 | |
352 C2V_VMENTRY(jlong, resolveMethod, (JNIEnv *, jobject, jlong metaspace_klass, jstring name, jstring signature)) | |
353 Klass* klass = (Klass*) metaspace_klass; | |
354 Symbol* name_symbol = java_lang_String::as_symbol(JNIHandles::resolve(name), THREAD); | |
355 Symbol* signature_symbol = java_lang_String::as_symbol(JNIHandles::resolve(signature), THREAD); | |
356 return (jlong) (address) klass->lookup_method(name_symbol, signature_symbol); | |
357 C2V_END | |
358 | |
359 C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jlong metaspace_klass)) | |
360 Klass* klass = (Klass*) metaspace_klass; | |
361 assert(klass != NULL, "method must not be called for primitive types"); | |
362 return Dependencies::find_finalizable_subclass(klass) != NULL; | |
363 C2V_END | |
364 | |
365 C2V_VMENTRY(jlong, getClassInitializer, (JNIEnv *, jobject, jlong metaspace_klass)) | |
366 InstanceKlass* klass = (InstanceKlass*) metaspace_klass; | |
367 return (jlong) (address) klass->class_initializer(); | |
368 C2V_END | |
369 | |
370 C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv *env, jobject, jlong addr)) | |
371 address target_addr = (address) addr; | |
372 if (target_addr != 0x0) { | |
373 int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int)); | |
374 int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int)); | |
375 return MAX2(ABS(off_low), ABS(off_high)); | |
376 } | |
377 return -1; | |
378 C2V_END | |
379 | |
380 | |
381 // helpers used to set fields in the HotSpotVMConfig object | |
382 jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { | |
383 jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); | |
384 if (id == NULL) { | |
385 fatal(err_msg("field not found: %s (%s)", name, sig)); | |
386 } | |
387 return id; | |
388 } | |
389 | |
390 C2V_VMENTRY(void, doNotInlineOrCompile,(JNIEnv *, jobject, jlong metaspace_method)) | |
391 methodHandle method = asMethod(metaspace_method); | |
392 method->set_not_c1_compilable(); | |
393 method->set_not_c2_compilable(); | |
394 method->set_dont_inline(true); | |
395 C2V_END | |
396 | |
397 extern "C" { | 60 extern "C" { |
398 extern VMStructEntry* gHotSpotVMStructs; | 61 extern VMStructEntry* gHotSpotVMStructs; |
399 extern uint64_t gHotSpotVMStructEntryTypeNameOffset; | 62 extern uint64_t gHotSpotVMStructEntryTypeNameOffset; |
400 extern uint64_t gHotSpotVMStructEntryFieldNameOffset; | 63 extern uint64_t gHotSpotVMStructEntryFieldNameOffset; |
401 extern uint64_t gHotSpotVMStructEntryTypeStringOffset; | 64 extern uint64_t gHotSpotVMStructEntryTypeStringOffset; |
420 | 83 |
421 extern VMLongConstantEntry* gHotSpotVMLongConstants; | 84 extern VMLongConstantEntry* gHotSpotVMLongConstants; |
422 extern uint64_t gHotSpotVMLongConstantEntryNameOffset; | 85 extern uint64_t gHotSpotVMLongConstantEntryNameOffset; |
423 extern uint64_t gHotSpotVMLongConstantEntryValueOffset; | 86 extern uint64_t gHotSpotVMLongConstantEntryValueOffset; |
424 extern uint64_t gHotSpotVMLongConstantEntryArrayStride; | 87 extern uint64_t gHotSpotVMLongConstantEntryArrayStride; |
88 } | |
89 | |
90 // helpers used to set fields in the HotSpotVMConfig object | |
91 static jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { | |
92 jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); | |
93 if (id == NULL) { | |
94 fatal(err_msg("field not found: %s (%s)", name, sig)); | |
95 } | |
96 return id; | |
425 } | 97 } |
426 | 98 |
427 C2V_ENTRY(void, initializeConfiguration, (JNIEnv *env, jobject, jobject config)) | 99 C2V_ENTRY(void, initializeConfiguration, (JNIEnv *env, jobject, jobject config)) |
428 | 100 |
429 #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0) | 101 #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0) |
530 | 202 |
531 #undef set_boolean | 203 #undef set_boolean |
532 #undef set_int | 204 #undef set_int |
533 #undef set_long | 205 #undef set_long |
534 | 206 |
207 C2V_END | |
208 | |
209 C2V_ENTRY(jbyteArray, initializeBytecode, (JNIEnv *env, jobject, jlong metaspace_method, jbyteArray result)) | |
210 methodHandle method = asMethod(metaspace_method); | |
211 ResourceMark rm; | |
212 | |
213 int code_size = method->code_size(); | |
214 jbyte* reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size); | |
215 | |
216 guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten"); | |
217 // iterate over all bytecodes and replace non-Java bytecodes | |
218 | |
219 for (BytecodeStream s(method); s.next() != Bytecodes::_illegal; ) { | |
220 Bytecodes::Code code = s.code(); | |
221 Bytecodes::Code raw_code = s.raw_code(); | |
222 int bci = s.bci(); | |
223 int len = s.instruction_size(); | |
224 | |
225 // Restore original byte code. | |
226 reconstituted_code[bci] = (jbyte) (s.is_wide()? Bytecodes::_wide : code); | |
227 if (len > 1) { | |
228 memcpy(&reconstituted_code[bci+1], s.bcp()+1, len-1); | |
229 } | |
230 | |
231 if (len > 1) { | |
232 // Restore the big-endian constant pool indexes. | |
233 // Cf. Rewriter::scan_method | |
234 switch (code) { | |
235 case Bytecodes::_getstatic: | |
236 case Bytecodes::_putstatic: | |
237 case Bytecodes::_getfield: | |
238 case Bytecodes::_putfield: | |
239 case Bytecodes::_invokevirtual: | |
240 case Bytecodes::_invokespecial: | |
241 case Bytecodes::_invokestatic: | |
242 case Bytecodes::_invokeinterface: | |
243 case Bytecodes::_invokehandle: { | |
244 int cp_index = Bytes::get_native_u2((address) &reconstituted_code[bci + 1]); | |
245 Bytes::put_Java_u2((address) &reconstituted_code[bci + 1], (u2) cp_index); | |
246 break; | |
247 } | |
248 | |
249 case Bytecodes::_invokedynamic: | |
250 int cp_index = Bytes::get_native_u4((address) &reconstituted_code[bci + 1]); | |
251 Bytes::put_Java_u4((address) &reconstituted_code[bci + 1], (u4) cp_index); | |
252 break; | |
253 } | |
254 | |
255 // Not all ldc byte code are rewritten. | |
256 switch (raw_code) { | |
257 case Bytecodes::_fast_aldc: { | |
258 int cpc_index = reconstituted_code[bci + 1] & 0xff; | |
259 int cp_index = method->constants()->object_to_cp_index(cpc_index); | |
260 assert(cp_index < method->constants()->length(), "sanity check"); | |
261 reconstituted_code[bci + 1] = (jbyte) cp_index; | |
262 break; | |
263 } | |
264 | |
265 case Bytecodes::_fast_aldc_w: { | |
266 int cpc_index = Bytes::get_native_u2((address) &reconstituted_code[bci + 1]); | |
267 int cp_index = method->constants()->object_to_cp_index(cpc_index); | |
268 assert(cp_index < method->constants()->length(), "sanity check"); | |
269 Bytes::put_Java_u2((address) &reconstituted_code[bci + 1], (u2) cp_index); | |
270 break; | |
271 } | |
272 } | |
273 } | |
274 } | |
275 | |
276 env->SetByteArrayRegion(result, 0, code_size, reconstituted_code); | |
277 | |
278 return result; | |
279 C2V_END | |
280 | |
281 C2V_VMENTRY(jint, exceptionTableLength, (JNIEnv *, jobject, jlong metaspace_method)) | |
282 ResourceMark rm; | |
283 methodHandle method = asMethod(metaspace_method); | |
284 return method->exception_table_length(); | |
285 C2V_END | |
286 | |
287 C2V_VMENTRY(jlong, exceptionTableStart, (JNIEnv *, jobject, jlong metaspace_method)) | |
288 ResourceMark rm; | |
289 methodHandle method = asMethod(metaspace_method); | |
290 assert(method->exception_table_length() != 0, "should be handled in Java code"); | |
291 return (jlong) (address) method->exception_table_start(); | |
292 C2V_END | |
293 | |
294 C2V_VMENTRY(jint, hasBalancedMonitors, (JNIEnv *, jobject, jlong metaspace_method)) | |
295 // Analyze the method to see if monitors are used properly. | |
296 methodHandle method(THREAD, asMethod(metaspace_method)); | |
297 { | |
298 EXCEPTION_MARK; | |
299 ResourceMark rm(THREAD); | |
300 GeneratePairingInfo gpi(method); | |
301 gpi.compute_map(CATCH); | |
302 if (!gpi.monitor_safe()) { | |
303 return false; | |
304 } | |
305 method->set_guaranteed_monitor_matching(); | |
306 } | |
307 return true; | |
308 C2V_END | |
309 | |
310 C2V_VMENTRY(jlong, getMetaspaceMethod, (JNIEnv *, jobject, jclass holder_handle, jint slot)) | |
311 oop java_class = JNIHandles::resolve(holder_handle); | |
312 Klass* holder = java_lang_Class::as_Klass(java_class); | |
313 methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot); | |
314 return (jlong) (address) method(); | |
315 } | |
316 | |
317 C2V_VMENTRY(jlong, findUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_method)) | |
318 methodHandle method = asMethod(metaspace_method); | |
319 KlassHandle holder = method->method_holder(); | |
320 assert(!holder->is_interface(), "should be handled in Java code"); | |
321 ResourceMark rm; | |
322 MutexLocker locker(Compile_lock); | |
323 Method* ucm = Dependencies::find_unique_concrete_method(holder(), method()); | |
324 return (jlong) (address) ucm; | |
325 C2V_END | |
326 | |
327 C2V_VMENTRY(jlong, getKlassImplementor, (JNIEnv *, jobject, jlong metaspace_klass)) | |
328 InstanceKlass* klass = (InstanceKlass*) asKlass(metaspace_klass); | |
329 return (jlong) (address) klass->implementor(); | |
330 C2V_END | |
331 | |
332 C2V_VMENTRY(void, initializeMethod,(JNIEnv *, jobject, jlong metaspace_method, jobject hotspot_method)) | |
333 methodHandle method = asMethod(metaspace_method); | |
334 InstanceKlass::cast(HotSpotResolvedJavaMethod::klass())->initialize(CHECK); | |
335 HotSpotResolvedJavaMethod::set_callerSensitive(hotspot_method, method->caller_sensitive()); | |
336 HotSpotResolvedJavaMethod::set_forceInline(hotspot_method, method->force_inline()); | |
337 HotSpotResolvedJavaMethod::set_dontInline(hotspot_method, method->dont_inline()); | |
338 HotSpotResolvedJavaMethod::set_ignoredBySecurityStackWalk(hotspot_method, method->is_ignored_by_security_stack_walk()); | |
339 C2V_END | |
340 | |
341 C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jlong metaspace_method)) | |
342 methodHandle method = asMethod(metaspace_method); | |
343 return !method->is_not_compilable() && !CompilerOracle::should_not_inline(method) && !method->dont_inline(); | |
344 C2V_END | |
345 | |
346 C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jlong metaspace_method)) | |
347 methodHandle method = asMethod(metaspace_method); | |
348 return CompilerOracle::should_inline(method) || method->force_inline(); | |
349 C2V_END | |
350 | |
351 C2V_ENTRY(jint, getCompiledCodeSize, (JNIEnv *env, jobject, jlong metaspace_method)) | |
352 nmethod* code = (asMethod(metaspace_method))->code(); | |
353 return code == NULL ? 0 : code->insts_size(); | |
354 C2V_END | |
355 | |
356 C2V_VMENTRY(jlong, lookupType, (JNIEnv *env, jobject, jstring jname, jclass accessing_class, jboolean eagerResolve)) | |
357 ResourceMark rm; | |
358 Handle name = JNIHandles::resolve(jname); | |
359 Symbol* class_name = java_lang_String::as_symbol(name, THREAD); | |
360 assert(class_name != NULL, "name to symbol creation failed"); | |
361 assert(class_name->size() > 1, "primitive types should be handled in Java code"); | |
362 | |
363 Klass* resolved_klass = NULL; | |
364 Handle class_loader; | |
365 Handle protection_domain; | |
366 if (JNIHandles::resolve(accessing_class) != NULL) { | |
367 Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class)); | |
368 class_loader = accessing_klass->class_loader(); | |
369 protection_domain = accessing_klass->protection_domain(); | |
370 } | |
371 | |
372 if (eagerResolve) { | |
373 resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, protection_domain, true, THREAD); | |
374 } else { | |
375 resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, THREAD); | |
376 } | |
377 | |
378 return (jlong) (address) resolved_klass; | |
379 C2V_END | |
380 | |
381 C2V_VMENTRY(jlong, lookupKlassByName, (JNIEnv *env, jobject, jstring name, jclass loading_class)) | |
382 KlassHandle loading_klass = java_lang_Class::as_Klass(JNIHandles::resolve(loading_class)); | |
383 Symbol* name_symbol = java_lang_String::as_symbol(JNIHandles::resolve(name), THREAD); | |
384 KlassHandle klass = GraalEnv::get_klass_by_name(loading_klass, name_symbol, false); | |
385 return (jlong) (address) klass(); | |
386 C2V_END | |
387 | |
388 C2V_VMENTRY(jobject, lookupConstantInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
389 ConstantPool* cp = (ConstantPool*) metaspace_constant_pool; | |
390 oop result = NULL; | |
391 constantTag tag = cp->tag_at(index); | |
392 switch (tag.value()) { | |
393 case JVM_CONSTANT_String: | |
394 result = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL); | |
395 break; | |
396 case JVM_CONSTANT_MethodHandle: | |
397 case JVM_CONSTANT_MethodHandleInError: | |
398 case JVM_CONSTANT_MethodType: | |
399 case JVM_CONSTANT_MethodTypeInError: | |
400 result = cp->resolve_constant_at(index, CHECK_NULL); | |
401 break; | |
402 default: | |
403 fatal(err_msg_res("unknown constant pool tag %s at cpi %d in %s", tag.internal_name(), index, cp->pool_holder()->name()->as_C_string())); | |
404 } | |
405 return JNIHandles::make_local(THREAD, result); | |
406 C2V_END | |
407 | |
408 C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
409 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
410 return cp->name_and_type_ref_index_at(index); | |
411 C2V_END | |
412 | |
413 C2V_VMENTRY(jlong, lookupNameRefInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
414 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
415 return (jlong) (address) cp->name_ref_at(index); | |
416 C2V_END | |
417 | |
418 C2V_VMENTRY(jlong, lookupSignatureRefInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
419 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
420 return (jlong) (address) cp->signature_ref_at(index); | |
421 C2V_END | |
422 | |
423 C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
424 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
425 return cp->klass_ref_index_at(index); | |
426 C2V_END | |
427 | |
428 C2V_VMENTRY(jlong, lookupKlassInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index, jbyte opcode)) | |
429 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
430 KlassHandle loading_klass(cp->pool_holder()); | |
431 bool is_accessible = false; | |
432 KlassHandle klass = GraalEnv::get_klass_by_index(cp, index, is_accessible, loading_klass); | |
433 if (klass.is_null()) { | |
434 // We have to lock the cpool to keep the oop from being resolved | |
435 // while we are accessing it. | |
436 MonitorLockerEx ml(cp->lock()); | |
437 constantTag tag = cp->tag_at(index); | |
438 if (tag.is_klass()) { | |
439 // The klass has been inserted into the constant pool | |
440 // very recently. | |
441 return (jlong) CompilerToVM::tag_pointer(cp->resolved_klass_at(index)); | |
442 } else if (tag.is_symbol()) { | |
443 return (jlong) CompilerToVM::tag_pointer(cp->symbol_at(index)); | |
444 } else { | |
445 assert(cp->tag_at(index).is_unresolved_klass(), "wrong tag"); | |
446 return (jlong) CompilerToVM::tag_pointer(cp->unresolved_klass_at(index)); | |
447 } | |
448 } | |
449 return (jlong) CompilerToVM::tag_pointer(klass()); | |
450 C2V_END | |
451 | |
452 C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) | |
453 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
454 oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index); | |
455 return JNIHandles::make_local(THREAD, appendix_oop); | |
456 C2V_END | |
457 | |
458 C2V_VMENTRY(jlong, lookupMethodInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index, jbyte opcode)) | |
459 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
460 instanceKlassHandle pool_holder(cp->pool_holder()); | |
461 Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); | |
462 methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); | |
463 return (jlong) (address) method(); | |
464 C2V_END | |
465 | |
466 C2V_VMENTRY(void, loadReferencedTypeInPool, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index, jbyte op)) | |
467 ConstantPool* cp = (ConstantPool*) metaspace_constant_pool; | |
468 Bytecodes::Code bc = (Bytecodes::Code) (((int) op) & 0xFF); | |
469 if (bc != Bytecodes::_checkcast && bc != Bytecodes::_instanceof && bc != Bytecodes::_new && bc != Bytecodes::_anewarray | |
470 && bc != Bytecodes::_multianewarray && bc != Bytecodes::_ldc && bc != Bytecodes::_ldc_w && bc != Bytecodes::_ldc2_w) | |
471 { | |
472 index = cp->remap_instruction_operand_from_cache(index); | |
473 } | |
474 constantTag tag = cp->tag_at(index); | |
475 if (tag.is_field_or_method()) { | |
476 index = cp->uncached_klass_ref_index_at(index); | |
477 tag = cp->tag_at(index); | |
478 } | |
479 | |
480 if (tag.is_unresolved_klass() || tag.is_klass()) { | |
481 Klass* klass = cp->klass_at(index, CHECK); | |
482 if (klass->oop_is_instance()) { | |
483 InstanceKlass::cast(klass)->initialize(CHECK); | |
484 } | |
485 } | |
486 C2V_END | |
487 | |
488 C2V_VMENTRY(jlong, resolveField, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index, jbyte opcode, jlongArray info_handle)) | |
489 ResourceMark rm; | |
490 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool; | |
491 Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF); | |
492 fieldDescriptor result; | |
493 LinkResolver::resolve_field_access(result, cp, index, Bytecodes::java_code(code), true, false, CHECK_0); | |
494 typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle); | |
495 assert(info != NULL && info->length() == 2, "must be"); | |
496 info->long_at_put(0, (jlong) result.access_flags().as_int()); | |
497 info->long_at_put(1, (jlong) result.offset()); | |
498 return (jlong) (address) result.field_holder(); | |
499 C2V_END | |
500 | |
501 C2V_VMENTRY(jlong, resolveMethod, (JNIEnv *, jobject, jlong metaspace_klass, jstring name, jstring signature)) | |
502 Klass* klass = (Klass*) metaspace_klass; | |
503 Symbol* name_symbol = java_lang_String::as_symbol(JNIHandles::resolve(name), THREAD); | |
504 Symbol* signature_symbol = java_lang_String::as_symbol(JNIHandles::resolve(signature), THREAD); | |
505 return (jlong) (address) klass->lookup_method(name_symbol, signature_symbol); | |
506 C2V_END | |
507 | |
508 C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jlong metaspace_klass)) | |
509 Klass* klass = (Klass*) metaspace_klass; | |
510 assert(klass != NULL, "method must not be called for primitive types"); | |
511 return Dependencies::find_finalizable_subclass(klass) != NULL; | |
512 C2V_END | |
513 | |
514 C2V_VMENTRY(jlong, getClassInitializer, (JNIEnv *, jobject, jlong metaspace_klass)) | |
515 InstanceKlass* klass = (InstanceKlass*) metaspace_klass; | |
516 return (jlong) (address) klass->class_initializer(); | |
517 C2V_END | |
518 | |
519 C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv *env, jobject, jlong addr)) | |
520 address target_addr = (address) addr; | |
521 if (target_addr != 0x0) { | |
522 int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int)); | |
523 int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int)); | |
524 return MAX2(ABS(off_low), ABS(off_high)); | |
525 } | |
526 return -1; | |
527 C2V_END | |
528 | |
529 C2V_VMENTRY(void, doNotInlineOrCompile,(JNIEnv *, jobject, jlong metaspace_method)) | |
530 methodHandle method = asMethod(metaspace_method); | |
531 method->set_not_c1_compilable(); | |
532 method->set_not_c2_compilable(); | |
533 method->set_dont_inline(true); | |
535 C2V_END | 534 C2V_END |
536 | 535 |
537 C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compiled_code, jobject installed_code, jobject speculation_log)) | 536 C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compiled_code, jobject installed_code, jobject speculation_log)) |
538 ResourceMark rm; | 537 ResourceMark rm; |
539 HandleMark hm; | 538 HandleMark hm; |