comparison src/share/vm/jvmci/jvmciCompilerToVM.cpp @ 21559:be896a1983c0

recast all Graal native code as JVMCI code (JBS:GRAAL-53)
author Doug Simon <doug.simon@oracle.com>
date Thu, 28 May 2015 15:36:48 +0200
parents src/share/vm/graal/graalCompilerToVM.cpp@48c1ebd24120
children ce2113326bc8
comparison
equal deleted inserted replaced
21558:d563baeca9df 21559:be896a1983c0
1 /*
2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 #include "precompiled.hpp"
25 #include "code/scopeDesc.hpp"
26 #include "memory/oopFactory.hpp"
27 #include "oops/generateOopMap.hpp"
28 #include "oops/fieldStreams.hpp"
29 #include "runtime/fieldDescriptor.hpp"
30 #include "runtime/javaCalls.hpp"
31 #include "jvmci/jvmciRuntime.hpp"
32 #include "compiler/compileBroker.hpp"
33 #include "compiler/compilerOracle.hpp"
34 #include "compiler/disassembler.hpp"
35 #include "jvmci/jvmciCompilerToVM.hpp"
36 #include "jvmci/jvmciCompiler.hpp"
37 #include "jvmci/jvmciEnv.hpp"
38 #include "jvmci/jvmciJavaAccess.hpp"
39 #include "jvmci/jvmciCodeInstaller.hpp"
40 #include "gc_implementation/g1/heapRegion.hpp"
41 #include "runtime/javaCalls.hpp"
42 #include "runtime/deoptimization.hpp"
43 #include "runtime/vframe.hpp"
44 #include "runtime/vframe_hp.hpp"
45 #include "runtime/vmStructs.hpp"
46
47
48 // Entry to native method implementation that transitions current thread to '_thread_in_vm'.
49 #define C2V_VMENTRY(result_type, name, signature) \
50 JNIEXPORT result_type JNICALL c2v_ ## name signature { \
51 TRACE_jvmci_3("CompilerToVM::" #name); \
52 JVMCI_VM_ENTRY_MARK; \
53
54 #define C2V_END }
55
56 extern "C" {
57 extern VMStructEntry* gHotSpotVMStructs;
58 extern uint64_t gHotSpotVMStructEntryTypeNameOffset;
59 extern uint64_t gHotSpotVMStructEntryFieldNameOffset;
60 extern uint64_t gHotSpotVMStructEntryTypeStringOffset;
61 extern uint64_t gHotSpotVMStructEntryIsStaticOffset;
62 extern uint64_t gHotSpotVMStructEntryOffsetOffset;
63 extern uint64_t gHotSpotVMStructEntryAddressOffset;
64 extern uint64_t gHotSpotVMStructEntryArrayStride;
65
66 extern VMTypeEntry* gHotSpotVMTypes;
67 extern uint64_t gHotSpotVMTypeEntryTypeNameOffset;
68 extern uint64_t gHotSpotVMTypeEntrySuperclassNameOffset;
69 extern uint64_t gHotSpotVMTypeEntryIsOopTypeOffset;
70 extern uint64_t gHotSpotVMTypeEntryIsIntegerTypeOffset;
71 extern uint64_t gHotSpotVMTypeEntryIsUnsignedOffset;
72 extern uint64_t gHotSpotVMTypeEntrySizeOffset;
73 extern uint64_t gHotSpotVMTypeEntryArrayStride;
74
75 extern VMIntConstantEntry* gHotSpotVMIntConstants;
76 extern uint64_t gHotSpotVMIntConstantEntryNameOffset;
77 extern uint64_t gHotSpotVMIntConstantEntryValueOffset;
78 extern uint64_t gHotSpotVMIntConstantEntryArrayStride;
79
80 extern VMLongConstantEntry* gHotSpotVMLongConstants;
81 extern uint64_t gHotSpotVMLongConstantEntryNameOffset;
82 extern uint64_t gHotSpotVMLongConstantEntryValueOffset;
83 extern uint64_t gHotSpotVMLongConstantEntryArrayStride;
84 }
85
86 C2V_VMENTRY(void, initializeConfiguration, (JNIEnv *, jobject, jobject config))
87 VMStructs::initHotSpotVMConfig(JNIHandles::resolve(config));
88 C2V_END
89
90 C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jlong metaspace_method))
91 methodHandle method = asMethod(metaspace_method);
92 ResourceMark rm;
93
94 int code_size = method->code_size();
95 typeArrayOop reconstituted_code = oopFactory::new_byteArray(code_size, CHECK_NULL);
96
97 guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten");
98 // iterate over all bytecodes and replace non-Java bytecodes
99
100 for (BytecodeStream s(method); s.next() != Bytecodes::_illegal; ) {
101 Bytecodes::Code code = s.code();
102 Bytecodes::Code raw_code = s.raw_code();
103 int bci = s.bci();
104 int len = s.instruction_size();
105
106 // Restore original byte code.
107 reconstituted_code->byte_at_put(bci, (jbyte) (s.is_wide()? Bytecodes::_wide : code));
108 if (len > 1) {
109 memcpy(reconstituted_code->byte_at_addr(bci + 1), s.bcp()+1, len-1);
110 }
111
112 if (len > 1) {
113 // Restore the big-endian constant pool indexes.
114 // Cf. Rewriter::scan_method
115 switch (code) {
116 case Bytecodes::_getstatic:
117 case Bytecodes::_putstatic:
118 case Bytecodes::_getfield:
119 case Bytecodes::_putfield:
120 case Bytecodes::_invokevirtual:
121 case Bytecodes::_invokespecial:
122 case Bytecodes::_invokestatic:
123 case Bytecodes::_invokeinterface:
124 case Bytecodes::_invokehandle: {
125 int cp_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
126 Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
127 break;
128 }
129
130 case Bytecodes::_invokedynamic:
131 int cp_index = Bytes::get_native_u4((address) reconstituted_code->byte_at_addr(bci + 1));
132 Bytes::put_Java_u4((address) reconstituted_code->byte_at_addr(bci + 1), (u4) cp_index);
133 break;
134 }
135
136 // Not all ldc byte code are rewritten.
137 switch (raw_code) {
138 case Bytecodes::_fast_aldc: {
139 int cpc_index = reconstituted_code->byte_at(bci + 1) & 0xff;
140 int cp_index = method->constants()->object_to_cp_index(cpc_index);
141 assert(cp_index < method->constants()->length(), "sanity check");
142 reconstituted_code->byte_at_put(bci + 1, (jbyte) cp_index);
143 break;
144 }
145
146 case Bytecodes::_fast_aldc_w: {
147 int cpc_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
148 int cp_index = method->constants()->object_to_cp_index(cpc_index);
149 assert(cp_index < method->constants()->length(), "sanity check");
150 Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
151 break;
152 }
153 }
154 }
155 }
156
157 return (jbyteArray) JNIHandles::make_local(THREAD, reconstituted_code);
158 C2V_END
159
160 C2V_VMENTRY(jint, exceptionTableLength, (JNIEnv *, jobject, jlong metaspace_method))
161 ResourceMark rm;
162 methodHandle method = asMethod(metaspace_method);
163 return method->exception_table_length();
164 C2V_END
165
166 C2V_VMENTRY(jlong, exceptionTableStart, (JNIEnv *, jobject, jlong metaspace_method))
167 ResourceMark rm;
168 methodHandle method = asMethod(metaspace_method);
169 assert(method->exception_table_length() != 0, "should be handled in Java code");
170 return (jlong) (address) method->exception_table_start();
171 C2V_END
172
173 C2V_VMENTRY(jint, hasBalancedMonitors, (JNIEnv *, jobject, jlong metaspace_method))
174 // Analyze the method to see if monitors are used properly.
175 methodHandle method(THREAD, asMethod(metaspace_method));
176 {
177 EXCEPTION_MARK;
178 ResourceMark rm(THREAD);
179 GeneratePairingInfo gpi(method);
180 gpi.compute_map(CATCH);
181 if (!gpi.monitor_safe()) {
182 return false;
183 }
184 method->set_guaranteed_monitor_matching();
185 }
186 return true;
187 C2V_END
188
189 C2V_VMENTRY(jlong, getMetaspaceMethod, (JNIEnv *, jobject, jclass holder_handle, jint slot))
190 oop java_class = JNIHandles::resolve(holder_handle);
191 Klass* holder = java_lang_Class::as_Klass(java_class);
192 methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot);
193 return (jlong) (address) method();
194 }
195
196 C2V_VMENTRY(jlong, findUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_klass, jlong metaspace_method))
197 methodHandle method = asMethod(metaspace_method);
198 KlassHandle holder = asKlass(metaspace_klass);
199 assert(!holder->is_interface(), "should be handled in Java code");
200 ResourceMark rm;
201 MutexLocker locker(Compile_lock);
202 Method* ucm = Dependencies::find_unique_concrete_method(holder(), method());
203 return (jlong) (address) ucm;
204 C2V_END
205
206 C2V_VMENTRY(jlong, getKlassImplementor, (JNIEnv *, jobject, jlong metaspace_klass))
207 InstanceKlass* klass = (InstanceKlass*) asKlass(metaspace_klass);
208 return (jlong) (address) klass->implementor();
209 C2V_END
210
211 C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv *, jobject, jlong metaspace_method))
212 methodHandle method = asMethod(metaspace_method);
213 return method->is_ignored_by_security_stack_walk();
214 C2V_END
215
216 C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jlong metaspace_method))
217 methodHandle method = asMethod(metaspace_method);
218 return !method->is_not_compilable() && !CompilerOracle::should_not_inline(method) && !method->dont_inline();
219 C2V_END
220
221 C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jlong metaspace_method))
222 methodHandle method = asMethod(metaspace_method);
223 return CompilerOracle::should_inline(method) || method->force_inline();
224 C2V_END
225
226 C2V_VMENTRY(jlong, lookupType, (JNIEnv*, jobject, jstring jname, jclass accessing_class, jboolean resolve))
227 ResourceMark rm;
228 Handle name = JNIHandles::resolve(jname);
229 Symbol* class_name = java_lang_String::as_symbol(name, THREAD);
230 assert(class_name != NULL, "name to symbol creation failed");
231 assert(class_name->size() > 1, "primitive types should be handled in Java code");
232
233 Klass* resolved_klass = NULL;
234 Handle class_loader;
235 Handle protection_domain;
236 if (JNIHandles::resolve(accessing_class) == NULL) {
237 THROW_(vmSymbols::java_lang_NullPointerException(), 0L);
238 }
239 Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class));
240 class_loader = accessing_klass->class_loader();
241 protection_domain = accessing_klass->protection_domain();
242
243 if (resolve) {
244 resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_0);
245 } else {
246 if (class_name->byte_at(0) == 'L' &&
247 class_name->byte_at(class_name->utf8_length()-1) == ';') {
248 // This is a name from a signature. Strip off the trimmings.
249 // Call recursive to keep scope of strippedsym.
250 TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1,
251 class_name->utf8_length()-2,
252 CHECK_0);
253 resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, CHECK_0);
254 } else if (FieldType::is_array(class_name)) {
255 FieldArrayInfo fd;
256 // dimension and object_key in FieldArrayInfo are assigned as a side-effect
257 // of this call
258 BasicType t = FieldType::get_array_info(class_name, fd, CHECK_0);
259 if (t == T_OBJECT) {
260 TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1+fd.dimension(),
261 class_name->utf8_length()-2-fd.dimension(),
262 CHECK_0);
263 // naked oop "k" is OK here -- we assign back into it
264 resolved_klass = SystemDictionary::find(strippedsym,
265 class_loader,
266 protection_domain,
267 CHECK_0);
268 if (resolved_klass != NULL) {
269 resolved_klass = resolved_klass->array_klass(fd.dimension(), CHECK_0);
270 }
271 } else {
272 resolved_klass = Universe::typeArrayKlassObj(t);
273 resolved_klass = TypeArrayKlass::cast(resolved_klass)->array_klass(fd.dimension(), CHECK_0);
274 }
275 }
276 }
277 return (jlong) (address) resolved_klass;
278 C2V_END
279
280 C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
281 ConstantPool* cp = (ConstantPool*) metaspace_constant_pool;
282 oop result = cp->resolve_constant_at(index, CHECK_NULL);
283 return JNIHandles::make_local(THREAD, result);
284 C2V_END
285
286 C2V_VMENTRY(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
287 ConstantPool* cp = (ConstantPool*) metaspace_constant_pool;
288 oop result = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL);
289 return JNIHandles::make_local(THREAD, result);
290 C2V_END
291
292 C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
293 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool;
294 return cp->name_and_type_ref_index_at(index);
295 C2V_END
296
297 C2V_VMENTRY(jobject, lookupNameRefInPool, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
298 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool;
299 Handle sym = java_lang_String::create_from_symbol(cp->name_ref_at(index), CHECK_NULL);
300 return JNIHandles::make_local(THREAD, sym());
301 C2V_END
302
303 C2V_VMENTRY(jobject, lookupSignatureRefInPool, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
304 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool;
305 Handle sym = java_lang_String::create_from_symbol(cp->signature_ref_at(index), CHECK_NULL);
306 return JNIHandles::make_local(THREAD, sym());
307 C2V_END
308
309 C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
310 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool;
311 return cp->klass_ref_index_at(index);
312 C2V_END
313
314 C2V_VMENTRY(jlong, constantPoolKlassAt, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
315 ConstantPool* cp = (ConstantPool*) metaspace_constant_pool;
316 return (jlong) (address) cp->klass_at(index, THREAD);
317 C2V_END
318
319 C2V_VMENTRY(jlong, lookupKlassInPool, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index, jbyte opcode))
320 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool;
321 KlassHandle loading_klass(cp->pool_holder());
322 bool is_accessible = false;
323 KlassHandle klass = JVMCIEnv::get_klass_by_index(cp, index, is_accessible, loading_klass);
324 if (klass.is_null()) {
325 // We have to lock the cpool to keep the oop from being resolved
326 // while we are accessing it.
327 MonitorLockerEx ml(cp->lock());
328 constantTag tag = cp->tag_at(index);
329 if (tag.is_klass()) {
330 // The klass has been inserted into the constant pool
331 // very recently.
332 return (jlong) CompilerToVM::tag_pointer(cp->resolved_klass_at(index));
333 } else if (tag.is_symbol()) {
334 return (jlong) CompilerToVM::tag_pointer(cp->symbol_at(index));
335 } else {
336 assert(cp->tag_at(index).is_unresolved_klass(), "wrong tag");
337 return (jlong) CompilerToVM::tag_pointer(cp->unresolved_klass_at(index));
338 }
339 }
340 return (jlong) CompilerToVM::tag_pointer(klass());
341 C2V_END
342
343 C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
344 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool;
345 oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index);
346 return JNIHandles::make_local(THREAD, appendix_oop);
347 C2V_END
348
349 C2V_VMENTRY(jlong, lookupMethodInPool, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index, jbyte opcode))
350 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool;
351 instanceKlassHandle pool_holder(cp->pool_holder());
352 Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
353 methodHandle method = JVMCIEnv::get_method_by_index(cp, index, bc, pool_holder);
354 return (jlong) (address) method();
355 C2V_END
356
357 C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
358 ConstantPool* cp = (ConstantPool*) metaspace_constant_pool;
359 return cp->remap_instruction_operand_from_cache(index);
360 C2V_END
361
362 C2V_VMENTRY(jlong, resolveField, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index, jbyte opcode, jlongArray info_handle))
363 ResourceMark rm;
364 constantPoolHandle cp = (ConstantPool*) metaspace_constant_pool;
365 Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
366 fieldDescriptor result;
367 LinkResolver::resolve_field_access(result, cp, index, Bytecodes::java_code(code), true, false, CHECK_0);
368 typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
369 assert(info != NULL && info->length() == 2, "must be");
370 info->long_at_put(0, (jlong) result.access_flags().as_int());
371 info->long_at_put(1, (jlong) result.offset());
372 return (jlong) (address) result.field_holder();
373 C2V_END
374
375 C2V_VMENTRY(jint, getVtableIndexForInterface, (JNIEnv *, jobject, jlong metaspace_klass, jlong metaspace_method))
376 Klass* klass = (Klass*) metaspace_klass;
377 Method* method = (Method*) metaspace_method;
378 assert(!klass->is_interface(), "");
379 return LinkResolver::vtable_index_of_interface_method(klass, method);
380 C2V_END
381
382 C2V_VMENTRY(jlong, resolveMethod, (JNIEnv *, jobject, jlong metaspace_klass_receiver, jlong metaspace_method, jlong metaspace_klass_caller))
383 Klass* recv_klass = (Klass*) metaspace_klass_receiver;
384 Klass* caller_klass = (Klass*) metaspace_klass_caller;
385 Method* method = (Method*) metaspace_method;
386
387 if (recv_klass->oop_is_array() || (InstanceKlass::cast(recv_klass)->is_linked())) {
388 Klass* holder_klass = method->method_holder();
389 Symbol* method_name = method->name();
390 Symbol* method_signature = method->signature();
391
392
393 if (holder_klass->is_interface()) {
394 // do link-time resolution to check all access rules.
395 methodHandle resolved_method;
396 LinkResolver::linktime_resolve_interface_method(resolved_method, holder_klass, method_name, method_signature, caller_klass, true, CHECK_AND_CLEAR_0);
397 if (resolved_method->is_private()) {
398 return (jlong) (address) NULL;
399 }
400 assert(recv_klass->is_subtype_of(holder_klass), "");
401 // do actual lookup
402 methodHandle sel_method;
403 LinkResolver::lookup_instance_method_in_klasses(sel_method, recv_klass,
404 resolved_method->name(),
405 resolved_method->signature(), CHECK_AND_CLEAR_0);
406 return (jlong) (address) sel_method();
407 } else {
408 // do link-time resolution to check all access rules.
409 methodHandle resolved_method;
410 LinkResolver::linktime_resolve_virtual_method(resolved_method, holder_klass, method_name, method_signature, caller_klass, true, CHECK_AND_CLEAR_0);
411 // do actual lookup (see LinkResolver::runtime_resolve_virtual_method)
412 int vtable_index = Method::invalid_vtable_index;
413 Method* selected_method;
414
415 if (resolved_method->method_holder()->is_interface()) { // miranda method
416 vtable_index = LinkResolver::vtable_index_of_interface_method(holder_klass, resolved_method);
417 assert(vtable_index >= 0 , "we should have valid vtable index at this point");
418
419 InstanceKlass* inst = InstanceKlass::cast(recv_klass);
420 selected_method = inst->method_at_vtable(vtable_index);
421 } else {
422 // at this point we are sure that resolved_method is virtual and not
423 // a miranda method; therefore, it must have a valid vtable index.
424 assert(!resolved_method->has_itable_index(), "");
425 vtable_index = resolved_method->vtable_index();
426 // We could get a negative vtable_index for final methods,
427 // because as an optimization they are they are never put in the vtable,
428 // unless they override an existing method.
429 // If we do get a negative, it means the resolved method is the the selected
430 // method, and it can never be changed by an override.
431 if (vtable_index == Method::nonvirtual_vtable_index) {
432 assert(resolved_method->can_be_statically_bound(), "cannot override this method");
433 selected_method = resolved_method();
434 } else {
435 // recv_klass might be an arrayKlassOop but all vtables start at
436 // the same place. The cast is to avoid virtual call and assertion.
437 InstanceKlass* inst = (InstanceKlass*)recv_klass;
438 selected_method = inst->method_at_vtable(vtable_index);
439 }
440 }
441 return (jlong) (address) selected_method;
442 }
443 }
444 return (jlong) (address) NULL;
445 C2V_END
446
447 C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jlong metaspace_klass))
448 Klass* klass = (Klass*) metaspace_klass;
449 assert(klass != NULL, "method must not be called for primitive types");
450 return Dependencies::find_finalizable_subclass(klass) != NULL;
451 C2V_END
452
453 C2V_VMENTRY(jlong, getClassInitializer, (JNIEnv *, jobject, jlong metaspace_klass))
454 InstanceKlass* klass = (InstanceKlass*) metaspace_klass;
455 return (jlong) (address) klass->class_initializer();
456 C2V_END
457
458 C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv*, jobject, jlong addr))
459 address target_addr = (address) addr;
460 if (target_addr != 0x0) {
461 int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int));
462 int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int));
463 return MAX2(ABS(off_low), ABS(off_high));
464 }
465 return -1;
466 C2V_END
467
468 C2V_VMENTRY(void, doNotInlineOrCompile,(JNIEnv *, jobject, jlong metaspace_method))
469 methodHandle method = asMethod(metaspace_method);
470 method->set_not_c1_compilable();
471 method->set_not_c2_compilable();
472 method->set_dont_inline(true);
473 C2V_END
474
475 C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject compiled_code, jobject installed_code, jobject speculation_log))
476 ResourceMark rm;
477 HandleMark hm;
478 Handle compiled_code_handle = JNIHandles::resolve(compiled_code);
479 CodeBlob* cb = NULL;
480 Handle installed_code_handle = JNIHandles::resolve(installed_code);
481 Handle speculation_log_handle = JNIHandles::resolve(speculation_log);
482
483 TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer());
484 CodeInstaller installer;
485 JVMCIEnv::CodeInstallResult result = installer.install(compiled_code_handle, cb, installed_code_handle, speculation_log_handle);
486
487 if (PrintCodeCacheOnCompilation) {
488 stringStream s;
489 // Dump code cache into a buffer before locking the tty,
490 {
491 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
492 CodeCache::print_summary(&s, false);
493 }
494 ttyLocker ttyl;
495 tty->print_raw_cr(s.as_string());
496 }
497
498 if (result != JVMCIEnv::ok) {
499 assert(cb == NULL, "should be");
500 } else {
501 if (!installed_code_handle.is_null()) {
502 assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
503 InstalledCode::set_address(installed_code_handle, (jlong) cb);
504 InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1);
505 oop comp_result = HotSpotCompiledCode::comp(compiled_code_handle);
506 if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
507 HotSpotInstalledCode::set_size(installed_code_handle, cb->size());
508 HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin());
509 HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
510 }
511 nmethod* nm = cb->as_nmethod_or_null();
512 if (nm != NULL && installed_code_handle->is_scavengable()) {
513 assert(nm->detect_scavenge_root_oops(), "nm should be scavengable if installed_code is scavengable");
514 if (!UseG1GC) {
515 assert(nm->on_scavenge_root_list(), "nm should be on scavengable list");
516 }
517 }
518 }
519 }
520 return result;
521 C2V_END
522
523 C2V_VMENTRY(void, notifyCompilationStatistics, (JNIEnv *jniEnv, jobject, jint id, jobject hotspot_method, jboolean osr, jint processedBytecodes, jlong time, jlong timeUnitsPerSecond, jobject installed_code))
524 CompilerStatistics* stats = JVMCICompiler::instance()->stats();
525
526 elapsedTimer timer = elapsedTimer(time, timeUnitsPerSecond);
527 if (osr) {
528 stats->_osr.update(timer, processedBytecodes);
529 } else {
530 stats->_standard.update(timer, processedBytecodes);
531 }
532 Handle installed_code_handle = JNIHandles::resolve(installed_code);
533 if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
534 stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle);
535 stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle);
536 }
537
538 if (CITimeEach) {
539 methodHandle method = asMethod(HotSpotResolvedJavaMethodImpl::metaspaceMethod(hotspot_method));
540 float bytes_per_sec = 1.0 * processedBytecodes / timer.seconds();
541 tty->print_cr("%3d seconds: %f bytes/sec: %f (bytes %d)",
542 id, timer.seconds(), bytes_per_sec, processedBytecodes);
543 }
544 C2V_END
545
546 C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject))
547 CompilerStatistics* stats = JVMCICompiler::instance()->stats();
548 stats->_standard.reset();
549 stats->_osr.reset();
550 C2V_END
551
552 C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jlong codeBlob))
553 ResourceMark rm;
554 HandleMark hm;
555
556 CodeBlob* cb = (CodeBlob*) (address) codeBlob;
557 if (cb == NULL) {
558 return NULL;
559 }
560
561 // We don't want the stringStream buffer to resize during disassembly as it
562 // uses scoped resource memory. If a nested function called during disassembly uses
563 // a ResourceMark and the buffer expands within the scope of the mark,
564 // the buffer becomes garbage when that scope is exited. Experience shows that
565 // the disassembled code is typically about 10x the code size so a fixed buffer
566 // sized to 20x code size plus a fixed amount for header info should be sufficient.
567 int bufferSize = cb->code_size() * 20 + 1024;
568 char* buffer = NEW_RESOURCE_ARRAY(char, bufferSize);
569 stringStream st(buffer, bufferSize);
570 if (cb->is_nmethod()) {
571 nmethod* nm = (nmethod*) cb;
572 if (!nm->is_alive()) {
573 return NULL;
574 }
575 Disassembler::decode(nm, &st);
576 } else {
577 Disassembler::decode(cb, &st);
578 }
579 if (st.size() <= 0) {
580 return NULL;
581 }
582
583 Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
584 return JNIHandles::make_local(THREAD, result());
585 C2V_END
586
587 C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv*, jobject, jlong metaspace_method, int bci))
588 ResourceMark rm;
589 HandleMark hm;
590
591 methodHandle method = asMethod(metaspace_method);
592 oop element = java_lang_StackTraceElement::create(method, bci, CHECK_NULL);
593 return JNIHandles::make_local(THREAD, element);
594 C2V_END
595
596 C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv*, jobject, jobject args, jobject hotspotInstalledCode))
597 ResourceMark rm;
598 HandleMark hm;
599
600 jlong nmethodValue = InstalledCode::address(hotspotInstalledCode);
601 if (nmethodValue == 0L) {
602 THROW_(vmSymbols::com_oracle_jvmci_code_InvalidInstalledCodeException(), NULL);
603 }
604 nmethod* nm = (nmethod*) (address) nmethodValue;
605 methodHandle mh = nm->method();
606 Symbol* signature = mh->signature();
607 JavaCallArguments jca(mh->size_of_parameters());
608
609 JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
610 JavaValue result(jap.get_ret_type());
611 jca.set_alternative_target(nm);
612 JavaCalls::call(&result, mh, &jca, CHECK_NULL);
613
614 if (jap.get_ret_type() == T_VOID) {
615 return NULL;
616 } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) {
617 return JNIHandles::make_local(THREAD, (oop) result.get_jobject());
618 } else {
619 jvalue *value = (jvalue *) result.get_value_addr();
620 // Narrow the value down if required (Important on big endian machines)
621 switch (jap.get_ret_type()) {
622 case T_BOOLEAN:
623 value->z = (jboolean) value->i;
624 break;
625 case T_BYTE:
626 value->b = (jbyte) value->i;
627 break;
628 case T_CHAR:
629 value->c = (jchar) value->i;
630 break;
631 case T_SHORT:
632 value->s = (jshort) value->i;
633 break;
634 }
635 oop o = java_lang_boxing_object::create(jap.get_ret_type(), value, CHECK_NULL);
636 return JNIHandles::make_local(THREAD, o);
637 }
638 C2V_END
639
640 C2V_VMENTRY(jlongArray, getLineNumberTable, (JNIEnv *, jobject, jlong metaspace_method))
641 Method* method = (Method*) metaspace_method;
642 if (!method->has_linenumber_table()) {
643 return NULL;
644 }
645 u2 num_entries = 0;
646 CompressedLineNumberReadStream streamForSize(method->compressed_linenumber_table());
647 while (streamForSize.read_pair()) {
648 num_entries++;
649 }
650
651 CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
652 typeArrayOop result = oopFactory::new_longArray(2 * num_entries, CHECK_NULL);
653
654 int i = 0;
655 jlong value;
656 while (stream.read_pair()) {
657 value = ((long) stream.bci());
658 result->long_at_put(i, value);
659 value = ((long) stream.line());
660 result->long_at_put(i + 1, value);
661 i += 2;
662 }
663
664 return (jlongArray) JNIHandles::make_local(THREAD, result);
665 C2V_END
666
667 C2V_VMENTRY(jlong, getLocalVariableTableStart, (JNIEnv *, jobject, jlong metaspace_method))
668 ResourceMark rm;
669 Method* method = (Method*) metaspace_method;
670 if (!method->has_localvariable_table()) {
671 return 0;
672 }
673 return (jlong) (address) method->localvariable_table_start();
674 C2V_END
675
676 C2V_VMENTRY(jint, getLocalVariableTableLength, (JNIEnv *, jobject, jlong metaspace_method))
677 ResourceMark rm;
678 Method* method = (Method*) metaspace_method;
679 return method->localvariable_table_length();
680 C2V_END
681
682 C2V_VMENTRY(void, reprofile, (JNIEnv*, jobject, jlong metaspace_method))
683 Method* method = asMethod(metaspace_method);
684 MethodCounters* mcs = method->method_counters();
685 if (mcs != NULL) {
686 mcs->clear_counters();
687 }
688 NOT_PRODUCT(method->set_compiled_invocation_count(0));
689
690 nmethod* code = method->code();
691 if (code != NULL) {
692 code->make_not_entrant();
693 }
694
695 MethodData* method_data = method->method_data();
696 if (method_data == NULL) {
697 ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
698 method_data = MethodData::allocate(loader_data, method, CHECK);
699 method->set_method_data(method_data);
700 } else {
701 method_data->initialize();
702 }
703 C2V_END
704
705
706 C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject hotspotInstalledCode))
707 jlong nativeMethod = InstalledCode::address(hotspotInstalledCode);
708 nmethod* m = (nmethod*)nativeMethod;
709 if (m != NULL && !m->is_not_entrant()) {
710 m->mark_for_deoptimization();
711 VM_Deoptimize op;
712 VMThread::execute(&op);
713 }
714 InstalledCode::set_address(hotspotInstalledCode, 0);
715 C2V_END
716
717 C2V_VMENTRY(jobject, getJavaMirror, (JNIEnv* env, jobject, jlong metaspace_klass))
718 Klass* klass = asKlass(metaspace_klass);
719 return JNIHandles::make_local(THREAD, klass->java_mirror());
720 C2V_END
721
722 C2V_VMENTRY(jlong, readUnsafeKlassPointer, (JNIEnv*, jobject, jobject o))
723 oop resolved_o = JNIHandles::resolve(o);
724 jlong klass = (jlong)(address)resolved_o->klass();
725 return klass;
726 C2V_END
727
728 C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv*, jobject, jlong addr))
729 oop ret = oopDesc::load_decode_heap_oop((oop*)(address)addr);
730 return JNIHandles::make_local(THREAD, ret);
731 C2V_END
732
733 C2V_VMENTRY(jlongArray, collectCounters, (JNIEnv*, jobject))
734 typeArrayOop arrayOop = oopFactory::new_longArray(JVMCICounterSize, CHECK_NULL);
735 JavaThread::collect_counters(arrayOop);
736 return (jlongArray) JNIHandles::make_local(THREAD, arrayOop);
737 C2V_END
738
739 C2V_VMENTRY(int, allocateCompileId, (JNIEnv*, jobject, jlong metaspace_method, int entry_bci))
740 HandleMark hm;
741 ResourceMark rm;
742 Method* method = (Method*) metaspace_method;
743 return CompileBroker::assign_compile_id_unlocked(THREAD, method, entry_bci);
744 C2V_END
745
746
747 C2V_VMENTRY(jboolean, isMature, (JNIEnv*, jobject, jlong metaspace_method_data))
748 MethodData* mdo = asMethodData(metaspace_method_data);
749 return mdo != NULL && mdo->is_mature();
750 C2V_END
751
752 C2V_VMENTRY(jboolean, hasCompiledCodeForOSR, (JNIEnv*, jobject, jlong metaspace_method, int entry_bci, int comp_level))
753 Method* method = asMethod(metaspace_method);
754 return method->lookup_osr_nmethod_for(entry_bci, comp_level, true) != NULL;
755 C2V_END
756
757 C2V_VMENTRY(jlong, getTimeStamp, (JNIEnv*, jobject))
758 // tty->time_stamp is the time since VM start which should be used
759 // for all HotSpot log output when a timestamp is required.
760 return tty->time_stamp().milliseconds();
761 C2V_END
762
763 C2V_VMENTRY(jobject, getSymbol, (JNIEnv*, jobject, jlong metaspaceSymbol))
764 Handle sym = java_lang_String::create_from_symbol((Symbol*)(address)metaspaceSymbol, CHECK_NULL);
765 return JNIHandles::make_local(THREAD, sym());
766 C2V_END
767
768 bool matches(jlongArray methods, Method* method) {
769 typeArrayOop methods_oop = (typeArrayOop) JNIHandles::resolve(methods);
770
771 for (int i = 0; i < methods_oop->length(); i++) {
772 if (methods_oop->long_at(i) == (jlong) method) {
773 return true;
774 }
775 }
776 return false;
777 }
778
779 C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv*, jobject compilerToVM, jobject hs_frame, jlongArray methods, jint initialSkip))
780 ResourceMark rm;
781
782 if (!thread->has_last_Java_frame()) return NULL;
783 Handle result = InstanceKlass::cast(HotSpotStackFrameReference::klass())->allocate_instance(thread);
784 HotSpotStackFrameReference::klass()->initialize(thread);
785
786 StackFrameStream fst(thread);
787 if (hs_frame != NULL) {
788 // look for the correct stack frame if one is given
789 intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
790 while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
791 fst.next();
792 }
793 if (fst.current()->sp() != stack_pointer) {
794 THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
795 }
796 }
797
798 int frame_number = 0;
799 vframe* vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
800 if (hs_frame != NULL) {
801 // look for the correct vframe within the stack frame if one is given
802 int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
803 while (frame_number < last_frame_number) {
804 if (vf->is_top()) {
805 THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
806 }
807 vf = vf->sender();
808 frame_number ++;
809 }
810 // move one frame forward
811 if (vf->is_top()) {
812 if (fst.is_done()) {
813 return NULL;
814 }
815 fst.next();
816 vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
817 frame_number = 0;
818 } else {
819 vf = vf->sender();
820 frame_number++;
821 }
822 }
823
824 while (true) {
825 // look for the given method
826 while (true) {
827 StackValueCollection* locals = NULL;
828 if (vf->is_compiled_frame()) {
829 // compiled method frame
830 compiledVFrame* cvf = compiledVFrame::cast(vf);
831 if (methods == NULL || matches(methods, cvf->method())) {
832 if (initialSkip > 0) {
833 initialSkip --;
834 } else {
835 GrowableArray<ScopeValue*>* objects = cvf->scope()->objects();
836 bool reallocated = false;
837 if (objects != NULL) {
838 reallocated = Deoptimization::realloc_objects(thread, fst.current(), objects, THREAD);
839 Deoptimization::reassign_fields(fst.current(), fst.register_map(), objects, reallocated);
840
841 GrowableArray<ScopeValue*>* local_values = cvf->scope()->locals();
842 typeArrayHandle array = oopFactory::new_boolArray(local_values->length(), thread);
843 for (int i = 0; i < local_values->length(); i++) {
844 ScopeValue* value = local_values->at(i);
845 if (value->is_object()) {
846 array->bool_at_put(i, true);
847 }
848 }
849 HotSpotStackFrameReference::set_localIsVirtual(result, array());
850 } else {
851 HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
852 }
853
854 locals = cvf->locals();
855 HotSpotStackFrameReference::set_bci(result, cvf->bci());
856 HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) cvf->method());
857 }
858 }
859 } else if (vf->is_interpreted_frame()) {
860 // interpreted method frame
861 interpretedVFrame* ivf = interpretedVFrame::cast(vf);
862 if (methods == NULL || matches(methods, ivf->method())) {
863 if (initialSkip > 0) {
864 initialSkip --;
865 } else {
866 locals = ivf->locals();
867 HotSpotStackFrameReference::set_bci(result, ivf->bci());
868 HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) ivf->method());
869 HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
870 }
871 }
872 }
873
874 // locals != NULL means that we found a matching frame and result is already partially initialized
875 if (locals != NULL) {
876 HotSpotStackFrameReference::set_compilerToVM(result, JNIHandles::resolve(compilerToVM));
877 HotSpotStackFrameReference::set_stackPointer(result, (jlong) fst.current()->sp());
878 HotSpotStackFrameReference::set_frameNumber(result, frame_number);
879
880 // initialize the locals array
881 objArrayHandle array = oopFactory::new_objectArray(locals->size(), thread);
882 for (int i = 0; i < locals->size(); i++) {
883 StackValue* var = locals->at(i);
884 if (var->type() == T_OBJECT) {
885 array->obj_at_put(i, locals->at(i)->get_obj()());
886 }
887 }
888 HotSpotStackFrameReference::set_locals(result, array());
889
890 return JNIHandles::make_local(thread, result());
891 }
892
893 if (vf->is_top()) {
894 break;
895 }
896 frame_number++;
897 vf = vf->sender();
898 } // end of vframe loop
899
900 if (fst.is_done()) {
901 break;
902 }
903 fst.next();
904 vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
905 frame_number = 0;
906 } // end of frame loop
907
908 // the end was reached without finding a matching method
909 return NULL;
910 C2V_END
911
912 C2V_VMENTRY(void, resolveInvokeDynamic, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
913 ConstantPool* cp = (ConstantPool*)metaspace_constant_pool;
914 CallInfo callInfo;
915 LinkResolver::resolve_invokedynamic(callInfo, cp, index, CHECK);
916 ConstantPoolCacheEntry* cp_cache_entry = cp->invokedynamic_cp_cache_entry_at(index);
917 cp_cache_entry->set_dynamic_call(cp, callInfo);
918 C2V_END
919
920 C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv*, jobject))
921 //see compute_recording_non_safepoints in debugInfroRec.cpp
922 if (JvmtiExport::should_post_compiled_method_load() && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
923 return true;
924 }
925 return DebugNonSafepoints;
926 C2V_END
927
928 // public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
929 C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame, bool invalidate))
930 ResourceMark rm;
931
932 if (hs_frame == NULL) {
933 THROW_MSG(vmSymbols::java_lang_NullPointerException(), "stack frame is null")
934 }
935
936 HotSpotStackFrameReference::klass()->initialize(thread);
937
938 // look for the given stack frame
939 StackFrameStream fst(thread);
940 intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
941 while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
942 fst.next();
943 }
944 if (fst.current()->sp() != stack_pointer) {
945 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
946 }
947
948 if (invalidate) {
949 assert(fst.current()->cb()->is_nmethod(), "nmethod expected");
950 ((nmethod*) fst.current()->cb())->make_not_entrant();
951 }
952 Deoptimization::deoptimize(thread, *fst.current(), fst.register_map(), Deoptimization::Reason_none);
953
954 vframe* vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
955 if (!vf->is_compiled_frame()) {
956 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
957 }
958
959 GrowableArray<compiledVFrame*>* virtualFrames = new GrowableArray<compiledVFrame*>(10);
960 while (true) {
961 assert(vf->is_compiled_frame(), "Wrong frame type");
962 virtualFrames->push(compiledVFrame::cast(vf));
963 if (vf->is_top()) {
964 break;
965 }
966 vf = vf->sender();
967 }
968
969 int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
970 if (last_frame_number >= virtualFrames->length()) {
971 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
972 }
973
974 // Reallocate the non-escaping objects and restore their fields.
975 assert (virtualFrames->at(last_frame_number)->scope() != NULL,"invalid scope");
976 GrowableArray<ScopeValue*>* objects = virtualFrames->at(last_frame_number)->scope()->objects();
977
978 if (objects == NULL) {
979 // no objects to materialize
980 return;
981 }
982
983 bool reallocated = Deoptimization::realloc_objects(thread, fst.current(), objects, THREAD);
984 Deoptimization::reassign_fields(fst.current(), fst.register_map(), objects, reallocated);
985
986 for (int frame_index = 0; frame_index < virtualFrames->length(); frame_index++) {
987 compiledVFrame* cvf = virtualFrames->at(frame_index);
988
989 GrowableArray<ScopeValue*>* scopeLocals = cvf->scope()->locals();
990 StackValueCollection* locals = cvf->locals();
991
992 if (locals != NULL) {
993 for (int i2 = 0; i2 < locals->size(); i2++) {
994 StackValue* var = locals->at(i2);
995 if (var->type() == T_OBJECT && scopeLocals->at(i2)->is_object()) {
996 jvalue val;
997 val.l = (jobject) locals->at(i2)->get_obj()();
998 cvf->update_local(T_OBJECT, i2, val);
999 }
1000 }
1001 }
1002 }
1003
1004 // all locals are materialized by now
1005 HotSpotStackFrameReference::set_localIsVirtual(hs_frame, NULL);
1006
1007 // update the locals array
1008 objArrayHandle array = HotSpotStackFrameReference::locals(hs_frame);
1009 StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals();
1010 for (int i = 0; i < locals->size(); i++) {
1011 StackValue* var = locals->at(i);
1012 if (var->type() == T_OBJECT) {
1013 array->obj_at_put(i, locals->at(i)->get_obj()());
1014 }
1015 }
1016 C2V_END
1017
1018 C2V_VMENTRY(void, writeDebugOutput, (JNIEnv*, jobject, jbyteArray bytes, jint offset, jint length))
1019 while (length > 0) {
1020 jbyte* start = ((typeArrayOop) JNIHandles::resolve(bytes))->byte_at_addr(offset);
1021 tty->write((char*) start, MIN2(length, O_BUFLEN));
1022 length -= O_BUFLEN;
1023 offset += O_BUFLEN;
1024 }
1025 C2V_END
1026
1027 C2V_VMENTRY(void, flushDebugOutput, (JNIEnv*, jobject))
1028 tty->flush();
1029 C2V_END
1030
1031
1032 #define CC (char*) /*cast a literal from (const char*)*/
1033 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
1034
1035 #define TYPE "Lcom/oracle/jvmci/meta/JavaType;"
1036 #define METHOD "Lcom/oracle/jvmci/meta/JavaMethod;"
1037 #define FIELD "Lcom/oracle/jvmci/meta/JavaField;"
1038 #define SPECULATION_LOG "Lcom/oracle/jvmci/code/SpeculationLog;"
1039 #define STRING "Ljava/lang/String;"
1040 #define OBJECT "Ljava/lang/Object;"
1041 #define CLASS "Ljava/lang/Class;"
1042 #define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;"
1043 #define INSTALLED_CODE "Lcom/oracle/jvmci/code/InstalledCode;"
1044 #define RESOLVED_METHOD "Lcom/oracle/jvmci/meta/ResolvedJavaMethod;"
1045 #define HS_RESOLVED_METHOD "Lcom/oracle/jvmci/hotspot/HotSpotResolvedJavaMethod;"
1046 #define HS_COMPILED_CODE "Lcom/oracle/jvmci/hotspot/HotSpotCompiledCode;"
1047 #define HS_CONFIG "Lcom/oracle/jvmci/hotspot/HotSpotVMConfig;"
1048 #define HS_STACK_FRAME_REF "Lcom/oracle/jvmci/hotspot/HotSpotStackFrameReference;"
1049 #define METASPACE_KLASS "J"
1050 #define METASPACE_METHOD "J"
1051 #define METASPACE_METHOD_DATA "J"
1052 #define METASPACE_CONSTANT_POOL "J"
1053
1054 JNINativeMethod CompilerToVM_methods[] = {
1055 {CC"getBytecode", CC"("METASPACE_METHOD")[B", FN_PTR(getBytecode)},
1056 {CC"exceptionTableStart", CC"("METASPACE_METHOD")J", FN_PTR(exceptionTableStart)},
1057 {CC"exceptionTableLength", CC"("METASPACE_METHOD")I", FN_PTR(exceptionTableLength)},
1058 {CC"hasBalancedMonitors", CC"("METASPACE_METHOD")Z", FN_PTR(hasBalancedMonitors)},
1059 {CC"findUniqueConcreteMethod", CC"("METASPACE_KLASS METASPACE_METHOD")"METASPACE_METHOD, FN_PTR(findUniqueConcreteMethod)},
1060 {CC"getKlassImplementor", CC"("METASPACE_KLASS")"METASPACE_KLASS, FN_PTR(getKlassImplementor)},
1061 {CC"getStackTraceElement", CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)},
1062 {CC"methodIsIgnoredBySecurityStackWalk", CC"("METASPACE_METHOD")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)},
1063 {CC"doNotInlineOrCompile", CC"("METASPACE_METHOD")V", FN_PTR(doNotInlineOrCompile)},
1064 {CC"canInlineMethod", CC"("METASPACE_METHOD")Z", FN_PTR(canInlineMethod)},
1065 {CC"shouldInlineMethod", CC"("METASPACE_METHOD")Z", FN_PTR(shouldInlineMethod)},
1066 {CC"lookupType", CC"("STRING CLASS"Z)"METASPACE_KLASS, FN_PTR(lookupType)},
1067 {CC"resolveConstantInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolveConstantInPool)},
1068 {CC"resolvePossiblyCachedConstantInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolvePossiblyCachedConstantInPool)},
1069 {CC"lookupNameRefInPool", CC"("METASPACE_CONSTANT_POOL"I)"STRING, FN_PTR(lookupNameRefInPool)},
1070 {CC"lookupNameAndTypeRefIndexInPool", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(lookupNameAndTypeRefIndexInPool)},
1071 {CC"lookupSignatureRefInPool", CC"("METASPACE_CONSTANT_POOL"I)"STRING, FN_PTR(lookupSignatureRefInPool)},
1072 {CC"lookupKlassRefIndexInPool", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(lookupKlassRefIndexInPool)},
1073 {CC"constantPoolKlassAt", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_KLASS, FN_PTR(constantPoolKlassAt)},
1074 {CC"lookupKlassInPool", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_KLASS, FN_PTR(lookupKlassInPool)},
1075 {CC"lookupAppendixInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(lookupAppendixInPool)},
1076 {CC"lookupMethodInPool", CC"("METASPACE_CONSTANT_POOL"IB)"METASPACE_METHOD, FN_PTR(lookupMethodInPool)},
1077 {CC"constantPoolRemapInstructionOperandFromCache", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(constantPoolRemapInstructionOperandFromCache)},
1078 {CC"resolveField", CC"("METASPACE_CONSTANT_POOL"IB[J)"METASPACE_KLASS, FN_PTR(resolveField)},
1079 {CC"resolveInvokeDynamic", CC"("METASPACE_CONSTANT_POOL"I)V", FN_PTR(resolveInvokeDynamic)},
1080 {CC"resolveMethod", CC"("METASPACE_KLASS METASPACE_METHOD METASPACE_KLASS")"METASPACE_METHOD, FN_PTR(resolveMethod)},
1081 {CC"getVtableIndexForInterface", CC"("METASPACE_KLASS METASPACE_METHOD")I", FN_PTR(getVtableIndexForInterface)},
1082 {CC"getClassInitializer", CC"("METASPACE_KLASS")"METASPACE_METHOD, FN_PTR(getClassInitializer)},
1083 {CC"hasFinalizableSubclass", CC"("METASPACE_KLASS")Z", FN_PTR(hasFinalizableSubclass)},
1084 {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)},
1085 {CC"getMetaspaceMethod", CC"("CLASS"I)"METASPACE_METHOD, FN_PTR(getMetaspaceMethod)},
1086 {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)},
1087 {CC"installCode", CC"("HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I", FN_PTR(installCode)},
1088 {CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)},
1089 {CC"resetCompilationStatistics", CC"()V", FN_PTR(resetCompilationStatistics)},
1090 {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)},
1091 {CC"executeCompiledMethodVarargs", CC"(["OBJECT INSTALLED_CODE")"OBJECT, FN_PTR(executeCompiledMethodVarargs)},
1092 {CC"getLineNumberTable", CC"("METASPACE_METHOD")[J", FN_PTR(getLineNumberTable)},
1093 {CC"getLocalVariableTableStart", CC"("METASPACE_METHOD")J", FN_PTR(getLocalVariableTableStart)},
1094 {CC"getLocalVariableTableLength", CC"("METASPACE_METHOD")I", FN_PTR(getLocalVariableTableLength)},
1095 {CC"reprofile", CC"("METASPACE_METHOD")V", FN_PTR(reprofile)},
1096 {CC"invalidateInstalledCode", CC"("INSTALLED_CODE")V", FN_PTR(invalidateInstalledCode)},
1097 {CC"getJavaMirror", CC"("METASPACE_KLASS")"CLASS, FN_PTR(getJavaMirror)},
1098 {CC"readUnsafeKlassPointer", CC"("OBJECT")J", FN_PTR(readUnsafeKlassPointer)},
1099 {CC"readUncompressedOop", CC"(J)"OBJECT, FN_PTR(readUncompressedOop)},
1100 {CC"collectCounters", CC"()[J", FN_PTR(collectCounters)},
1101 {CC"allocateCompileId", CC"("METASPACE_METHOD"I)I", FN_PTR(allocateCompileId)},
1102 {CC"isMature", CC"("METASPACE_METHOD_DATA")Z", FN_PTR(isMature)},
1103 {CC"hasCompiledCodeForOSR", CC"("METASPACE_METHOD"II)Z", FN_PTR(hasCompiledCodeForOSR)},
1104 {CC"getSymbol", CC"(J)"STRING, FN_PTR(getSymbol)},
1105 {CC"getTimeStamp", CC"()J", FN_PTR(getTimeStamp)},
1106 {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF "[JI)"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)},
1107 {CC"materializeVirtualObjects", CC"("HS_STACK_FRAME_REF"Z)V", FN_PTR(materializeVirtualObjects)},
1108 {CC"shouldDebugNonSafepoints", CC"()Z", FN_PTR(shouldDebugNonSafepoints)},
1109 {CC"writeDebugOutput", CC"([BII)V", FN_PTR(writeDebugOutput)},
1110 {CC"flushDebugOutput", CC"()V", FN_PTR(flushDebugOutput)},
1111 };
1112
1113 int CompilerToVM_methods_count() {
1114 return sizeof(CompilerToVM_methods) / sizeof(JNINativeMethod);
1115 }
1116