Mercurial > hg > truffle
annotate src/share/vm/graal/graalCompilerToVM.cpp @ 7225:31c4d9f9e922
adder better CHA support
added more test cases for inlining and intrinsification
author | Christian Haeubl <haeubl@ssw.jku.at> |
---|---|
date | Fri, 14 Dec 2012 12:05:35 +0100 |
parents | 720925633b3a |
children | 8a3efb8c831d |
rev | line source |
---|---|
7221 | 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 "runtime/fieldDescriptor.hpp" | |
26 #include "memory/oopFactory.hpp" | |
27 #include "oops/generateOopMap.hpp" | |
28 #include "oops/fieldStreams.hpp" | |
29 #include "runtime/javaCalls.hpp" | |
30 #include "graal/graalRuntime.hpp" | |
31 #include "compiler/compileBroker.hpp" | |
32 #include "compiler/compilerOracle.hpp" | |
33 #include "graal/graalCompilerToVM.hpp" | |
34 #include "graal/graalCompiler.hpp" | |
35 #include "graal/graalEnv.hpp" | |
36 #include "graal/graalJavaAccess.hpp" | |
37 #include "graal/graalCodeInstaller.hpp" | |
38 #include "graal/graalVMToCompiler.hpp" | |
39 #include "graal/graalVmIds.hpp" | |
40 | |
41 | |
42 Method* getMethodFromHotSpotMethod(oop hotspot_method) { | |
43 assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotResolvedJavaMethod::klass()), "sanity"); | |
44 return asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hotspot_method)); | |
45 } | |
46 | |
47 // Entry to native method implementation that transitions current thread to '_thread_in_vm'. | |
48 #define C2V_VMENTRY(result_type, name, signature) \ | |
49 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ | |
50 TRACE_graal_3("CompilerToVM::" #name); \ | |
51 GRAAL_VM_ENTRY_MARK; \ | |
52 | |
53 // Entry to native method implementation that calls a JNI function | |
54 // and hence cannot transition current thread to '_thread_in_vm'. | |
55 #define C2V_ENTRY(result_type, name, signature) \ | |
56 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ | |
57 TRACE_graal_3("CompilerToVM::" #name); \ | |
58 | |
59 #define C2V_END } | |
60 | |
61 C2V_ENTRY(jbyteArray, initializeBytecode, (JNIEnv *env, jobject, jlong metaspace_method, jbyteArray result)) | |
62 methodHandle method = asMethod(metaspace_method); | |
63 ResourceMark rm; | |
64 | |
65 int code_size = method->code_size(); | |
66 jbyte* reconstituted_code = NULL; | |
67 | |
68 // replace all breakpoints - must be done before undoing any rewriting | |
69 if (method->number_of_breakpoints() > 0) { | |
70 reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size); | |
71 memcpy(reconstituted_code, (jbyte *) method->code_base(), code_size); | |
72 BreakpointInfo* bp = InstanceKlass::cast(method->method_holder())->breakpoints(); | |
73 for (; bp != NULL; bp = bp->next()) { | |
74 if (bp->match(method())) { | |
75 jbyte code = bp->orig_bytecode(); | |
76 reconstituted_code[bp->bci()] = code; | |
77 } | |
78 } | |
79 } | |
80 | |
81 // iterate over all bytecodes and replace non-Java bytecodes | |
82 if (RewriteBytecodes || RewriteFrequentPairs || InstanceKlass::cast(method->method_holder())->is_rewritten()) { | |
83 if (reconstituted_code == NULL) { | |
84 reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size); | |
85 memcpy(reconstituted_code, (jbyte *) method->code_base(), code_size); | |
86 } | |
87 BytecodeStream s(method); | |
88 while(!s.is_last_bytecode()) { | |
89 s.next(); | |
90 Bytecodes::Code opcode = s.raw_code(); | |
91 if (!Bytecodes::is_java_code(opcode)) { | |
92 jbyte original_opcode = Bytecodes::java_code(opcode); | |
93 int bci = s.bci(); | |
94 reconstituted_code[bci] = original_opcode; | |
95 if (opcode == Bytecodes::_fast_aldc_w) { | |
96 int cpci = Bytes::get_native_u2((address) reconstituted_code + bci + 1); | |
97 int i = method->constants()->object_to_cp_index(cpci); | |
98 assert(i < method->constants()->length(), "sanity check"); | |
99 Bytes::put_Java_u2((address) reconstituted_code + bci + 1, (u2)i); | |
100 } else if (opcode == Bytecodes::_fast_aldc) { | |
101 int cpci = reconstituted_code[bci + 1] & 0xff; | |
102 int i = method->constants()->object_to_cp_index(cpci); | |
103 assert(i < method->constants()->length(), "sanity check"); | |
104 reconstituted_code[bci + 1] = (jbyte)i; | |
105 } | |
106 } | |
107 } | |
108 } | |
109 | |
110 if (reconstituted_code == NULL) { | |
111 env->SetByteArrayRegion(result, 0, code_size, (jbyte *) method->code_base()); | |
112 } else { | |
113 env->SetByteArrayRegion(result, 0, code_size, reconstituted_code); | |
114 } | |
115 | |
116 return result; | |
117 C2V_END | |
118 | |
119 C2V_VMENTRY(jstring, getSignature, (JNIEnv *env, jobject, jlong metaspace_method)) | |
120 Method* method = asMethod(metaspace_method); | |
121 assert(method != NULL && method->signature() != NULL, "signature required"); | |
122 return VmIds::toString<jstring>(method->signature(), THREAD); | |
123 C2V_END | |
124 | |
125 C2V_VMENTRY(jobjectArray, initializeExceptionHandlers, (JNIEnv *, jobject, jlong metaspace_method, jobjectArray java_handlers)) | |
126 ResourceMark rm; | |
127 methodHandle method = asMethod(metaspace_method); | |
128 int handler_count = method->exception_table_length(); | |
129 objArrayHandle array = (objArrayOop) JNIHandles::resolve(java_handlers); | |
130 assert(array->length() == handler_count, "wrong length"); | |
131 ExceptionTableElement* handlers = handler_count == 0 ? NULL : method->exception_table_start(); | |
132 | |
133 for (int i = 0; i < handler_count; i++) { | |
134 ExceptionTableElement* handler = handlers + i; | |
135 Handle entry = array->obj_at(i); | |
136 assert(!entry.is_null(), "entry should not be null"); | |
137 ExceptionHandler::set_startBCI(entry, handler->start_pc); | |
138 ExceptionHandler::set_endBCI(entry, handler->end_pc); | |
139 ExceptionHandler::set_handlerBCI(entry, handler->handler_pc); | |
140 int catch_class_index = handler->catch_type_index; | |
141 ExceptionHandler::set_catchTypeCPI(entry, catch_class_index); | |
142 | |
143 if (catch_class_index == 0) { | |
144 ExceptionHandler::set_catchType(entry, NULL); | |
145 } else { | |
146 ConstantPool* cp = InstanceKlass::cast(method->method_holder())->constants(); | |
147 KlassHandle loading_klass = method->method_holder(); | |
148 Handle catch_class = GraalCompiler::get_JavaType(cp, catch_class_index, loading_klass, CHECK_NULL); | |
149 if (catch_class->klass() == HotSpotResolvedObjectType::klass() && java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(catch_class)) == SystemDictionary::Throwable_klass()) { | |
150 ExceptionHandler::set_catchType(entry, NULL); | |
151 ExceptionHandler::set_catchTypeCPI(entry, 0); | |
152 } else { | |
153 ExceptionHandler::set_catchType(entry, catch_class()); | |
154 } | |
155 } | |
156 array->obj_at_put(i, entry()); | |
157 } | |
158 | |
159 return (jobjectArray) JNIHandles::make_local(array()); | |
160 C2V_END | |
161 | |
162 C2V_VMENTRY(jint, hasBalancedMonitors, (JNIEnv *, jobject, jlong metaspace_method)) | |
163 | |
164 // Analyze the method to see if monitors are used properly. | |
165 methodHandle method(THREAD, asMethod(metaspace_method)); | |
166 assert(method->has_monitor_bytecodes(), "should have checked this"); | |
167 | |
168 // Check to see if a previous compilation computed the monitor-matching analysis. | |
169 if (method->guaranteed_monitor_matching()) { | |
170 return true; | |
171 } | |
172 | |
173 { | |
174 EXCEPTION_MARK; | |
175 ResourceMark rm(THREAD); | |
176 GeneratePairingInfo gpi(method); | |
177 gpi.compute_map(CATCH); | |
178 if (!gpi.monitor_safe()) { | |
179 return false; | |
180 } | |
181 method->set_guaranteed_monitor_matching(); | |
182 } | |
183 return true; | |
184 C2V_END | |
185 | |
186 C2V_VMENTRY(jlong, getMetaspaceMethod, (JNIEnv *, jobject, jobject reflection_method_handle, jobject resultHolder)) | |
187 oop reflection_method = JNIHandles::resolve(reflection_method_handle); | |
188 oop reflection_holder = java_lang_reflect_Method::clazz(reflection_method); | |
189 int slot = java_lang_reflect_Method::slot(reflection_method); | |
190 Klass* holder = java_lang_Class::as_Klass(reflection_holder); | |
191 methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot); | |
192 Handle type = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0); | |
193 objArrayOop(JNIHandles::resolve(resultHolder))->obj_at_put(0, type()); | |
194 return (jlong) (address) method(); | |
195 } | |
196 | |
197 C2V_VMENTRY(jlong, getMetaspaceConstructor, (JNIEnv *, jobject, jobject reflection_ctor_handle, jobject resultHolder)) | |
198 oop reflection_ctor = JNIHandles::resolve(reflection_ctor_handle); | |
199 oop reflection_holder = java_lang_reflect_Constructor::clazz(reflection_ctor); | |
200 int slot = java_lang_reflect_Constructor::slot(reflection_ctor); | |
201 Klass* holder = java_lang_Class::as_Klass(reflection_holder); | |
202 methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot); | |
203 Handle type = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0); | |
204 objArrayOop(JNIHandles::resolve(resultHolder))->obj_at_put(0, type()); | |
205 return (jlong) (address) method(); | |
206 } | |
207 | |
208 C2V_VMENTRY(jobject, getJavaField, (JNIEnv *, jobject, jobject reflection_field_handle)) | |
209 oop reflection_field = JNIHandles::resolve(reflection_field_handle); | |
210 oop reflection_holder = java_lang_reflect_Field::clazz(reflection_field); | |
211 int slot = java_lang_reflect_Field::slot(reflection_field); | |
212 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(reflection_holder)); | |
213 | |
214 int offset = holder->field_offset(slot); | |
215 int flags = holder->field_access_flags(slot); | |
216 Symbol* field_name = holder->field_name(slot); | |
217 Handle field_holder = GraalCompiler::get_JavaTypeFromClass(reflection_holder, CHECK_NULL); | |
218 Handle field_type = GraalCompiler::get_JavaTypeFromClass(java_lang_reflect_Field::type(reflection_field), CHECK_NULL); | |
219 | |
220 Handle ret = GraalCompiler::get_JavaField(offset, flags, field_name, field_holder, field_type, CHECK_NULL); | |
221 return JNIHandles::make_local(THREAD, ret()); | |
222 } | |
223 | |
224 C2V_VMENTRY(jlong, getUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_method, jobject resultHolder)) | |
225 methodHandle method = asMethod(metaspace_method); | |
226 KlassHandle holder = method->method_holder(); | |
7225
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
227 // TODO (chaeubl): check if the following is necessary |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
228 //if (holder->is_interface()) { |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
229 // // Cannot trust interfaces. Because of: |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
230 // // interface I { void foo(); } |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
231 // // class A { public void foo() {} } |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
232 // // class B extends A implements I { } |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
233 // // class C extends B { public void foo() { } } |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
234 // // class D extends B { } |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
235 // // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo(). |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
236 // return 0L; |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
237 //} |
7221 | 238 methodHandle ucm; |
239 { | |
240 ResourceMark rm; | |
241 MutexLocker locker(Compile_lock); | |
242 ucm = Dependencies::find_unique_concrete_method(holder(), method()); | |
243 } | |
244 | |
245 if (ucm.is_null()) { | |
246 return 0L; | |
247 } | |
248 | |
249 Handle type = GraalCompiler::createHotSpotResolvedObjectType(ucm(), CHECK_0); | |
250 objArrayOop(JNIHandles::resolve(resultHolder))->obj_at_put(0, type()); | |
251 return (jlong) (address) ucm(); | |
252 C2V_END | |
253 | |
7225
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
254 C2V_VMENTRY(jobject, getUniqueImplementor, (JNIEnv *, jobject, jobject interface_type)) |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
255 InstanceKlass* klass = (InstanceKlass*) asKlass(HotSpotResolvedObjectType::metaspaceKlass(interface_type)); |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
256 assert(klass->is_interface(), "must be"); |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
257 if (klass->nof_implementors() == 1) { |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
258 InstanceKlass* implementor = (InstanceKlass*) klass->implementor(); |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
259 if (!implementor->is_abstract() && !implementor->is_interface() && implementor->is_leaf_class()) { |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
260 Handle type = GraalCompiler::get_JavaType(implementor, CHECK_NULL); |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
261 return JNIHandles::make_local(THREAD, type()); |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
262 } |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
263 } |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
264 return NULL; |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
265 C2V_END |
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
266 |
7221 | 267 C2V_ENTRY(jint, getInvocationCount, (JNIEnv *, jobject, jlong metaspace_method)) |
268 Method* method = asMethod(metaspace_method); | |
269 return method->invocation_count(); | |
270 C2V_END | |
271 | |
272 C2V_VMENTRY(void, initializeMethod,(JNIEnv *, jobject, jlong metaspace_method, jobject hotspot_method)) | |
273 methodHandle method = asMethod(metaspace_method); | |
274 Handle name = VmIds::toString<Handle>(method->name(), CHECK); | |
275 InstanceKlass::cast(HotSpotResolvedJavaMethod::klass())->initialize(CHECK); | |
276 HotSpotResolvedJavaMethod::set_name(hotspot_method, name()); | |
277 HotSpotResolvedJavaMethod::set_codeSize(hotspot_method, method->code_size()); | |
278 HotSpotResolvedJavaMethod::set_exceptionHandlerCount(hotspot_method, method->exception_table_length()); | |
279 C2V_END | |
280 | |
281 C2V_VMENTRY(jboolean, isMethodCompilable,(JNIEnv *, jobject, jlong metaspace_method)) | |
282 methodHandle method = asMethod(metaspace_method); | |
283 return !method->is_not_compilable() && !CompilerOracle::should_not_inline(method); | |
284 C2V_END | |
285 | |
286 C2V_VMENTRY(void, initializeMethodData,(JNIEnv *, jobject, jlong metaspace_method_data, jobject hotspot_method_data)) | |
287 MethodData* method_data = asMethodData(metaspace_method_data); | |
288 HotSpotMethodData::set_normalDataSize(hotspot_method_data, method_data->data_size()); | |
289 HotSpotMethodData::set_extraDataSize(hotspot_method_data, method_data->extra_data_size()); | |
290 C2V_END | |
291 | |
292 // ------------------------------------------------------------------ | |
293 // Adjust a CounterData count to be commensurate with | |
294 // interpreter_invocation_count. If the MDO exists for | |
295 // only 25% of the time the method exists, then the | |
296 // counts in the MDO should be scaled by 4X, so that | |
297 // they can be usefully and stably compared against the | |
298 // invocation counts in methods. | |
299 int scale_count(MethodData* method_data, int count) { | |
300 if (count > 0) { | |
301 int counter_life; | |
302 int method_life = method_data->method()->interpreter_invocation_count(); | |
303 int current_mileage = MethodData::mileage_of(method_data->method()); | |
304 int creation_mileage = method_data->creation_mileage(); | |
305 counter_life = current_mileage - creation_mileage; | |
306 | |
307 // counter_life due to backedge_counter could be > method_life | |
308 if (counter_life > method_life) | |
309 counter_life = method_life; | |
310 if (0 < counter_life && counter_life <= method_life) { | |
311 count = (int)((double)count * method_life / counter_life + 0.5); | |
312 count = (count > 0) ? count : 1; | |
313 } | |
314 } | |
315 return count; | |
316 } | |
317 | |
318 C2V_ENTRY(jint, getCompiledCodeSize, (JNIEnv *env, jobject, jlong metaspace_method)) | |
319 nmethod* code = (asMethod(metaspace_method))->code(); | |
320 return code == NULL ? 0 : code->insts_size(); | |
321 C2V_END | |
322 | |
323 C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve)) | |
324 ResourceMark rm; | |
325 | |
326 Symbol* nameSymbol = VmIds::toSymbol(jname); | |
327 Handle name = JNIHandles::resolve(jname); | |
328 assert(nameSymbol != NULL, "name to symbol creation failed"); | |
329 | |
330 oop result = NULL; | |
331 if (nameSymbol == vmSymbols::int_signature()) { | |
332 result = VMToCompiler::createPrimitiveJavaType((int) T_INT, THREAD); | |
333 } else if (nameSymbol == vmSymbols::long_signature()) { | |
334 result = VMToCompiler::createPrimitiveJavaType((int) T_LONG, THREAD); | |
335 } else if (nameSymbol == vmSymbols::bool_signature()) { | |
336 result = VMToCompiler::createPrimitiveJavaType((int) T_BOOLEAN, THREAD); | |
337 } else if (nameSymbol == vmSymbols::char_signature()) { | |
338 result = VMToCompiler::createPrimitiveJavaType((int) T_CHAR, THREAD); | |
339 } else if (nameSymbol == vmSymbols::short_signature()) { | |
340 result = VMToCompiler::createPrimitiveJavaType((int) T_SHORT, THREAD); | |
341 } else if (nameSymbol == vmSymbols::byte_signature()) { | |
342 result = VMToCompiler::createPrimitiveJavaType((int) T_BYTE, THREAD); | |
343 } else if (nameSymbol == vmSymbols::double_signature()) { | |
344 result = VMToCompiler::createPrimitiveJavaType((int) T_DOUBLE, THREAD); | |
345 } else if (nameSymbol == vmSymbols::float_signature()) { | |
346 result = VMToCompiler::createPrimitiveJavaType((int) T_FLOAT, THREAD); | |
347 } else if (nameSymbol == vmSymbols::void_signature()) { | |
348 result = VMToCompiler::createPrimitiveJavaType((int) T_VOID, THREAD); | |
349 } else { | |
350 Klass* resolved_type = NULL; | |
351 Handle classloader; | |
352 Handle protectionDomain; | |
353 if (JNIHandles::resolve(accessingClass) != NULL) { | |
354 classloader = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(accessingClass))->class_loader(); | |
355 protectionDomain = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(accessingClass))->protection_domain(); | |
356 } | |
357 | |
358 if (eagerResolve) { | |
359 resolved_type = SystemDictionary::resolve_or_fail(nameSymbol, classloader, protectionDomain, true, THREAD); | |
360 } else { | |
361 resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); | |
362 } | |
363 | |
364 if (!HAS_PENDING_EXCEPTION) { | |
365 if (resolved_type == NULL) { | |
366 assert(!eagerResolve, "failed eager resolution should have caused an exception"); | |
367 Handle type = VMToCompiler::createUnresolvedJavaType(name, THREAD); | |
368 result = type(); | |
369 } else { | |
370 Handle type = GraalCompiler::createHotSpotResolvedObjectType(resolved_type, name, CHECK_NULL); | |
371 result = type(); | |
372 } | |
373 } | |
374 } | |
375 | |
376 return JNIHandles::make_local(THREAD, result); | |
377 C2V_END | |
378 | |
379 C2V_VMENTRY(jobject, lookupConstantInPool, (JNIEnv *env, jobject, jobject type, jint index)) | |
380 | |
381 ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); | |
382 | |
383 oop result = NULL; | |
384 constantTag tag = cp->tag_at(index); | |
385 if (tag.is_int()) { | |
386 result = VMToCompiler::createConstant(Kind::Int(), cp->int_at(index), CHECK_0); | |
387 } else if (tag.is_long()) { | |
388 result = VMToCompiler::createConstant(Kind::Long(), cp->long_at(index), CHECK_0); | |
389 } else if (tag.is_float()) { | |
390 result = VMToCompiler::createConstantFloat(cp->float_at(index), CHECK_0); | |
391 } else if (tag.is_double()) { | |
392 result = VMToCompiler::createConstantDouble(cp->double_at(index), CHECK_0); | |
393 } else if (tag.is_string()) { | |
394 oop string = NULL; | |
395 if (cp->is_pseudo_string_at(index)) { | |
396 int obj_index = cp->cp_to_object_index(index); | |
397 string = cp->pseudo_string_at(index, obj_index); | |
398 } else { | |
399 string = cp->string_at(index, THREAD); | |
400 if (HAS_PENDING_EXCEPTION) { | |
401 CLEAR_PENDING_EXCEPTION; | |
402 // TODO: Gracefully exit compilation. | |
403 fatal("out of memory during compilation!"); | |
404 return NULL; | |
405 } | |
406 } | |
407 result = VMToCompiler::createConstantObject(string, CHECK_0); | |
408 } else if (tag.is_klass() || tag.is_unresolved_klass()) { | |
409 Handle type = GraalCompiler::get_JavaType(cp, index, cp->pool_holder(), CHECK_NULL); | |
410 result = type(); | |
411 } else if (tag.is_object()) { | |
412 oop obj = cp->object_at(index); | |
413 assert(obj->is_instance(), "must be an instance"); | |
414 result = VMToCompiler::createConstantObject(obj, CHECK_NULL); | |
415 } else { | |
416 tty->print("unknown constant pool tag (%s) at cpi %d in %s: ", tag.internal_name(), index, cp->pool_holder()->name()->as_C_string()); | |
417 ShouldNotReachHere(); | |
418 } | |
419 | |
420 return JNIHandles::make_local(THREAD, result); | |
421 C2V_END | |
422 | |
423 C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode)) | |
424 index = GraalCompiler::to_cp_index_u2(index); | |
425 constantPoolHandle cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); | |
426 instanceKlassHandle pool_holder(cp->pool_holder()); | |
427 | |
428 Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); | |
429 methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); | |
430 if (!method.is_null()) { | |
431 Handle holder = GraalCompiler::get_JavaType(method->method_holder(), CHECK_NULL); | |
432 return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); | |
433 } else { | |
434 // Get the method's name and signature. | |
435 Handle name = VmIds::toString<Handle>(cp->name_ref_at(index), CHECK_NULL); | |
436 Handle signature = VmIds::toString<Handle>(cp->signature_ref_at(index), CHECK_NULL); | |
437 int holder_index = cp->klass_ref_index_at(index); | |
438 Handle type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); | |
439 return JNIHandles::make_local(THREAD, VMToCompiler::createUnresolvedJavaMethod(name, signature, type, THREAD)); | |
440 } | |
441 C2V_END | |
442 | |
443 C2V_VMENTRY(jobject, lookupTypeInPool, (JNIEnv *env, jobject, jobject type, jint index)) | |
444 | |
445 ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); | |
446 Handle result = GraalCompiler::get_JavaType(cp, index, cp->pool_holder(), CHECK_NULL); | |
447 return JNIHandles::make_local(THREAD, result()); | |
448 C2V_END | |
449 | |
450 C2V_VMENTRY(void, lookupReferencedTypeInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte op)) | |
451 ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); | |
452 int opcode = (op & 0xFF); | |
453 if (opcode != Bytecodes::_checkcast && opcode != Bytecodes::_instanceof && opcode != Bytecodes::_new && opcode != Bytecodes::_anewarray | |
454 && opcode != Bytecodes::_multianewarray && opcode != Bytecodes::_ldc && opcode != Bytecodes::_ldc_w && opcode != Bytecodes::_ldc2_w) | |
455 { | |
456 index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index_u2(index)); | |
457 } | |
458 constantTag tag = cp->tag_at(index); | |
459 if (tag.is_field_or_method()) { | |
460 index = cp->uncached_klass_ref_index_at(index); | |
461 tag = cp->tag_at(index); | |
462 } | |
463 | |
464 if (tag.is_unresolved_klass() || tag.is_klass()) { | |
465 Klass* klass = cp->klass_at(index, CHECK); | |
466 if (klass->oop_is_instance()) { | |
467 InstanceKlass::cast(klass)->initialize(CHECK); | |
468 } | |
469 } | |
470 C2V_END | |
471 | |
472 C2V_VMENTRY(jobject, lookupFieldInPool, (JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte opcode)) | |
473 ResourceMark rm; | |
474 | |
475 index = GraalCompiler::to_cp_index_u2(index); | |
476 constantPoolHandle cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(constantPoolHolder)))->constants(); | |
477 | |
478 int nt_index = cp->name_and_type_ref_index_at(index); | |
479 int sig_index = cp->signature_ref_index_at(nt_index); | |
480 Symbol* signature = cp->symbol_at(sig_index); | |
481 int name_index = cp->name_ref_index_at(nt_index); | |
482 Symbol* name = cp->symbol_at(name_index); | |
483 int holder_index = cp->klass_ref_index_at(index); | |
484 Handle holder = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); | |
485 instanceKlassHandle holder_klass; | |
486 | |
487 Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF); | |
488 int offset = -1; | |
489 AccessFlags flags; | |
490 BasicType basic_type; | |
491 if (holder->klass() == SystemDictionary::HotSpotResolvedObjectType_klass()) { | |
492 FieldAccessInfo result; | |
493 LinkResolver::resolve_field(result, cp, index, | |
494 Bytecodes::java_code(code), | |
495 true, false, Thread::current()); | |
496 if (HAS_PENDING_EXCEPTION) { | |
497 CLEAR_PENDING_EXCEPTION; | |
498 } else { | |
499 offset = result.field_offset(); | |
500 flags = result.access_flags(); | |
501 holder_klass = result.klass()(); | |
502 basic_type = result.field_type(); | |
503 holder = GraalCompiler::get_JavaType(holder_klass, CHECK_NULL); | |
504 } | |
505 } | |
506 | |
507 Handle type = GraalCompiler::get_JavaTypeFromSignature(signature, cp->pool_holder(), CHECK_NULL); | |
508 Handle field_handle = GraalCompiler::get_JavaField(offset, flags.as_int(), name, holder, type, THREAD); | |
509 | |
510 return JNIHandles::make_local(THREAD, field_handle()); | |
511 C2V_END | |
512 | |
513 C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature)) | |
514 | |
515 assert(JNIHandles::resolve(resolved_type) != NULL, ""); | |
516 Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(resolved_type)); | |
517 Symbol* name_symbol = VmIds::toSymbol(name); | |
518 Symbol* signature_symbol = VmIds::toSymbol(signature); | |
519 methodHandle method = klass->lookup_method(name_symbol, signature_symbol); | |
520 if (method.is_null()) { | |
521 if (TraceGraal >= 3) { | |
522 ResourceMark rm; | |
523 tty->print_cr("Could not resolve method %s %s on klass %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), klass->name()->as_C_string()); | |
524 } | |
525 return NULL; | |
526 } | |
527 Handle holder = GraalCompiler::get_JavaType(method->method_holder(), CHECK_NULL); | |
528 return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); | |
529 C2V_END | |
530 | |
531 C2V_VMENTRY(jboolean, isTypeInitialized,(JNIEnv *, jobject, jobject hotspot_klass)) | |
532 Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); | |
533 assert(klass != NULL, "method must not be called for primitive types"); | |
534 return InstanceKlass::cast(klass)->is_initialized(); | |
535 C2V_END | |
536 | |
537 C2V_VMENTRY(void, initializeType, (JNIEnv *, jobject, jobject hotspot_klass)) | |
538 Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); | |
539 assert(klass != NULL, "method must not be called for primitive types"); | |
540 InstanceKlass::cast(klass)->initialize(JavaThread::current()); | |
541 C2V_END | |
542 | |
543 C2V_VMENTRY(jobject, getInstanceFields, (JNIEnv *, jobject, jobject klass)) | |
544 ResourceMark rm; | |
545 | |
546 instanceKlassHandle k = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(klass)); | |
547 GrowableArray<Handle> fields(k->java_fields_count()); | |
548 | |
549 for (AllFieldStream fs(k()); !fs.done(); fs.next()) { | |
550 if (!fs.access_flags().is_static()) { | |
551 Handle type = GraalCompiler::get_JavaTypeFromSignature(fs.signature(), k, Thread::current()); | |
552 int flags = fs.access_flags().as_int(); | |
553 bool internal = fs.access_flags().is_internal(); | |
554 Handle name = VmIds::toString<Handle>(fs.name(), Thread::current()); | |
555 Handle field = VMToCompiler::createJavaField(JNIHandles::resolve(klass), name, type, fs.offset(), flags, internal, Thread::current()); | |
556 fields.append(field()); | |
557 } | |
558 } | |
559 objArrayHandle field_array = oopFactory::new_objArray(SystemDictionary::HotSpotResolvedJavaField_klass(), fields.length(), CHECK_NULL); | |
560 for (int i = 0; i < fields.length(); ++i) { | |
561 field_array->obj_at_put(i, fields.at(i)()); | |
562 } | |
563 return JNIHandles::make_local(field_array()); | |
564 C2V_END | |
565 | |
566 C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv *env, jobject, jlong stub)) | |
567 address target_addr = (address) stub; | |
568 if (target_addr != 0x0) { | |
569 int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int)); | |
570 int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int)); | |
571 return MAX2(ABS(off_low), ABS(off_high)); | |
572 } | |
573 return -1; | |
574 C2V_END | |
575 | |
576 C2V_VMENTRY(jobject, getResolvedType, (JNIEnv *env, jobject, jobject javaClass)) | |
577 oop java_mirror = JNIHandles::resolve(javaClass); | |
578 assert(java_mirror != NULL, "argument to CompilerToVM.getResolvedType must not be NULL"); | |
579 Handle type = GraalCompiler::get_JavaTypeFromClass(java_mirror, CHECK_NULL); | |
580 return JNIHandles::make_local(THREAD, type()); | |
581 C2V_END | |
582 | |
583 | |
584 // helpers used to set fields in the HotSpotVMConfig object | |
585 jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { | |
586 jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); | |
587 if (id == NULL) { | |
588 fatal(err_msg("field not found: %s (%s)", name, sig)); | |
589 } | |
590 return id; | |
591 } | |
592 | |
593 BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; | |
594 int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); | |
595 | |
596 C2V_ENTRY(void, initializeConfiguration, (JNIEnv *env, jobject, jobject config)) | |
597 | |
598 #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0) | |
599 #define set_int(name, value) do { env->SetIntField(config, getFieldID(env, config, name, "I"), value); } while (0) | |
600 #define set_long(name, value) do { env->SetLongField(config, getFieldID(env, config, name, "J"), value); } while (0) | |
601 #define set_object(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "Ljava/lang/Object;"), value); } while (0) | |
602 #define set_int_array(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "[I"), value); } while (0) | |
603 | |
604 guarantee(HeapWordSize == sizeof(char*), "Graal assumption that HeadWordSize == machine word size is wrong"); | |
605 #ifdef _WIN64 | |
7222 | 606 set_boolean("windowsOs", true); |
7221 | 607 #else |
608 set_boolean("windowsOs", false); | |
609 #endif | |
610 set_boolean("verifyOops", VerifyOops); | |
611 set_boolean("useFastLocking", UseFastLocking); | |
612 set_boolean("useFastNewObjectArray", UseFastNewObjectArray); | |
613 set_boolean("useBiasedLocking", UseBiasedLocking); | |
614 set_boolean("useFastNewTypeArray", UseFastNewTypeArray); | |
615 set_boolean("useTLAB", UseTLAB); | |
616 set_int("codeEntryAlignment", CodeEntryAlignment); | |
617 set_int("vmPageSize", os::vm_page_size()); | |
618 set_int("stackShadowPages", StackShadowPages); | |
619 set_int("hubOffset", oopDesc::klass_offset_in_bytes()); | |
620 set_int("markOffset", oopDesc::mark_offset_in_bytes()); | |
621 set_int("prototypeMarkWordOffset", in_bytes(Klass::prototype_header_offset())); | |
622 set_int("superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset())); | |
623 set_int("secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset())); | |
624 set_int("secondarySupersOffset", in_bytes(Klass::secondary_supers_offset())); | |
625 set_int("subklassOffset", in_bytes(Klass::subklass_offset())); | |
626 set_int("nextSiblingOffset", in_bytes(Klass::next_sibling_offset())); | |
627 set_int("arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); | |
628 set_int("klassStateOffset", in_bytes(InstanceKlass::init_state_offset())); | |
629 set_int("klassStateFullyInitialized", (int)InstanceKlass::fully_initialized); | |
630 set_int("threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); | |
631 set_int("threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); | |
632 set_int("threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); | |
633 set_int("osThreadOffset", in_bytes(JavaThread::osthread_offset())); | |
634 set_int("osThreadInterruptedOffset", in_bytes(OSThread::interrupted_offset())); | |
635 set_int("unlockedMask", (int) markOopDesc::unlocked_value); | |
636 set_int("biasedLockMaskInPlace", (int) markOopDesc::biased_lock_mask_in_place); | |
637 set_int("ageMaskInPlace", (int) markOopDesc::age_mask_in_place); | |
638 set_int("epochMaskInPlace", (int) markOopDesc::epoch_mask_in_place); | |
639 set_int("biasedLockPattern", (int) markOopDesc::biased_lock_pattern); | |
640 set_int("methodMaxLocalsOffset", in_bytes(Method::size_of_locals_offset())); | |
641 set_int("methodMaxStackOffset", in_bytes(Method::max_stack_offset())); | |
642 set_int("extraStackEntries", Method::extra_stack_entries()); | |
643 set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset())); | |
644 set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER); | |
645 set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); | |
646 set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); | |
647 set_long("safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); | |
648 set_boolean("isPollingPageFar", Assembler::is_polling_page_far()); | |
649 set_int("classMirrorOffset", in_bytes(Klass::java_mirror_offset())); | |
650 set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); | |
651 set_int("klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); | |
652 set_int("klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset())); | |
653 set_int("klassOffset", java_lang_Class::klass_offset_in_bytes()); | |
654 set_int("graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes()); | |
655 set_int("klassLayoutHelperOffset", in_bytes(Klass::layout_helper_offset())); | |
656 set_int("klassSuperKlassOffset", in_bytes(Klass::super_offset())); | |
657 set_int("methodDataOffset", in_bytes(Method::method_data_offset())); | |
658 set_int("nmethodEntryOffset", nmethod::verified_entry_point_offset()); | |
659 set_int("methodCompiledEntryOffset", in_bytes(Method::from_compiled_offset())); | |
660 set_int("basicLockSize", sizeof(BasicLock)); | |
661 set_int("basicLockDisplacedHeaderOffset", BasicLock::displaced_header_offset_in_bytes()); | |
662 set_int("uninitializedIdentityHashCodeValue", markOopDesc::no_hash); | |
663 set_int("identityHashCodeShift", markOopDesc::hash_shift); | |
664 | |
665 set_int("arrayKlassLayoutHelperIdentifier", 0x80000000); | |
666 assert((Klass::_lh_array_tag_obj_value & Klass::_lh_array_tag_type_value & 0x80000000) != 0, "obj_array and type_array must have first bit set"); | |
667 set_int("arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset())); | |
668 | |
669 set_int("metaspaceArrayLengthOffset", Array<Klass*>::length_offset_in_bytes()); | |
670 set_int("metaspaceArrayBaseOffset", Array<Klass*>::base_offset_in_bytes()); | |
671 set_int("methodDataOopDataOffset", in_bytes(MethodData::data_offset())); | |
672 set_int("methodDataOopTrapHistoryOffset", in_bytes(MethodData::trap_history_offset())); | |
673 set_int("dataLayoutHeaderSize", DataLayout::header_size_in_bytes()); | |
674 set_int("dataLayoutTagOffset", in_bytes(DataLayout::tag_offset())); | |
675 set_int("dataLayoutFlagsOffset", in_bytes(DataLayout::flags_offset())); | |
676 set_int("dataLayoutBCIOffset", in_bytes(DataLayout::bci_offset())); | |
677 set_int("dataLayoutCellsOffset", in_bytes(DataLayout::cell_offset(0))); | |
678 set_int("dataLayoutCellSize", DataLayout::cell_size); | |
679 set_int("bciProfileWidth", BciProfileWidth); | |
680 set_int("typeProfileWidth", TypeProfileWidth); | |
681 | |
682 set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); | |
683 set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); | |
684 set_long("heapTopAddress", (jlong)(address) Universe::heap()->top_addr()); | |
685 set_long("heapEndAddress", (jlong)(address) Universe::heap()->end_addr()); | |
686 set_int("threadTlabStartOffset", in_bytes(JavaThread::tlab_start_offset())); | |
687 set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset())); | |
688 set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset())); | |
689 set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset())); | |
690 set_int("tlabFastRefillWasteOffset", in_bytes(JavaThread::tlab_fast_refill_waste_offset())); | |
691 set_int("tlabNumberOfRefillsOffset", in_bytes(JavaThread::tlab_number_of_refills_offset())); | |
692 set_int("tlabRefillWasteLimitOffset", in_bytes(JavaThread::tlab_refill_waste_limit_offset())); | |
693 set_int("tlabRefillWasteIncrement", (int32_t) ThreadLocalAllocBuffer::refill_waste_limit_increment()); | |
694 set_int("klassInstanceSizeOffset", in_bytes(Klass::layout_helper_offset())); | |
695 set_boolean("tlabStats", TLABStats); | |
696 set_boolean("inlineContiguousAllocationSupported", !CMSIncrementalMode && Universe::heap()->supports_inline_contig_alloc()); | |
697 | |
698 set_long("arrayPrototypeMarkWord", (intptr_t)markOopDesc::prototype()); | |
699 set_int("layoutHelperLog2ElementSizeShift", Klass::_lh_log2_element_size_shift); | |
700 set_int("layoutHelperLog2ElementSizeMask", Klass::_lh_log2_element_size_mask); | |
701 set_int("layoutHelperElementTypeShift", Klass::_lh_element_type_shift); | |
702 set_int("layoutHelperElementTypeMask", Klass::_lh_element_type_mask); | |
703 set_int("layoutHelperHeaderSizeShift", Klass::_lh_header_size_shift); | |
704 set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask); | |
705 set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset())); | |
706 | |
707 set_long("debugStub", VmIds::addStub((address)warning)); | |
708 set_long("instanceofStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_slow_subtype_check_id))); | |
709 set_long("newInstanceStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_instance_id))); | |
710 set_long("newArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_array_id))); | |
711 set_long("newMultiArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_multi_array_id))); | |
712 set_long("identityHashCodeStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_identity_hash_code_id))); | |
713 set_long("threadIsInterruptedStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_thread_is_interrupted_id))); | |
714 set_long("inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); | |
715 set_long("handleExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_handle_exception_nofpu_id))); | |
716 set_long("handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); | |
717 set_long("monitorEnterStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorenter_id))); | |
718 set_long("monitorExitStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorexit_id))); | |
719 set_long("verifyOopStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_verify_oop_id))); | |
720 set_long("vmErrorStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_vm_error_id))); | |
721 set_long("deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap())); | |
722 set_long("unwindExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_unwind_exception_call_id))); | |
723 set_long("osrMigrationEndStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_OSR_migration_end_id))); | |
724 set_long("registerFinalizerStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_register_finalizer_id))); | |
725 set_long("setDeoptInfoStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_set_deopt_info_id))); | |
726 set_long("createNullPointerExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_null_pointer_exception_id))); | |
727 set_long("createOutOfBoundsExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_out_of_bounds_exception_id))); | |
728 set_long("javaTimeMillisStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeMillis))); | |
729 set_long("javaTimeNanosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeNanos))); | |
730 set_long("arithmeticFremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_frem_id))); | |
731 set_long("arithmeticDremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_drem_id))); | |
732 set_long("arithmeticSinStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dsin))); | |
733 set_long("arithmeticCosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dcos))); | |
734 set_long("arithmeticTanStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dtan))); | |
735 set_long("logPrimitiveStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id))); | |
736 set_long("logObjectStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_object_id))); | |
737 set_long("logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id))); | |
738 | |
739 | |
740 BarrierSet* bs = Universe::heap()->barrier_set(); | |
741 switch (bs->kind()) { | |
742 case BarrierSet::CardTableModRef: | |
743 case BarrierSet::CardTableExtension: { | |
744 jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; | |
745 assert(base != 0, "unexpected byte_map_base"); | |
746 set_long("cardtableStartAddress", base); | |
747 set_int("cardtableShift", CardTableModRefBS::card_shift); | |
748 break; | |
749 } | |
750 case BarrierSet::ModRef: | |
751 case BarrierSet::Other: | |
752 set_long("cardtableStartAddress", 0); | |
753 set_int("cardtableShift", 0); | |
754 // No post barriers | |
755 break; | |
756 #ifndef SERIALGC | |
757 case BarrierSet::G1SATBCT: | |
758 case BarrierSet::G1SATBCTLogging: | |
759 #endif // SERIALGC | |
760 default: | |
761 ShouldNotReachHere(); | |
762 break; | |
763 } | |
764 | |
765 set_int("arrayClassElementOffset", in_bytes(ObjArrayKlass::element_klass_offset())); | |
766 | |
767 #undef set_boolean | |
768 #undef set_int | |
769 #undef set_long | |
770 #undef set_object | |
771 #undef set_int_array | |
772 | |
773 C2V_END | |
774 | |
775 C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject info)) | |
776 ResourceMark rm; | |
777 HandleMark hm; | |
778 Handle compResultHandle = JNIHandles::resolve(compResult); | |
779 nmethod* nm = NULL; | |
780 methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(compResult)); | |
781 Handle installed_code_handle = JNIHandles::resolve(installed_code); | |
782 GraalEnv::CodeInstallResult result; | |
783 CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle); | |
784 | |
785 if (result != GraalEnv::ok) { | |
786 assert(nm == NULL, "should be"); | |
787 } else { | |
788 if (info != NULL) { | |
789 arrayOop codeCopy = oopFactory::new_byteArray(nm->code_size(), CHECK_0); | |
790 memcpy(codeCopy->base(T_BYTE), nm->code_begin(), nm->code_size()); | |
791 HotSpotCodeInfo::set_code(info, codeCopy); | |
792 HotSpotCodeInfo::set_start(info, (jlong) nm->code_begin()); | |
793 } | |
794 | |
795 if (!installed_code_handle.is_null()) { | |
796 assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type"); | |
797 HotSpotInstalledCode::set_nmethod(installed_code_handle, (jlong) nm); | |
798 HotSpotInstalledCode::set_method(installed_code_handle, HotSpotCompilationResult::method(compResult)); | |
799 assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable"); | |
800 } | |
801 } | |
802 return result; | |
803 C2V_END | |
804 | |
805 C2V_VMENTRY(jobject, disassembleNative, (JNIEnv *jniEnv, jobject, jbyteArray code, jlong start_address)) | |
806 ResourceMark rm; | |
807 HandleMark hm; | |
808 | |
809 stringStream(st); | |
810 arrayOop code_oop = (arrayOop) JNIHandles::resolve(code); | |
811 int len = code_oop->length(); | |
812 address begin = (address) code_oop->base(T_BYTE); | |
813 address end = begin + len; | |
814 Disassembler::decode(begin, end, &st); | |
815 | |
816 Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); | |
817 return JNIHandles::make_local(result()); | |
818 C2V_END | |
819 | |
820 C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv *env, jobject, jlong metaspace_method, int bci)) | |
821 ResourceMark rm; | |
822 HandleMark hm; | |
823 | |
824 methodHandle method = asMethod(metaspace_method); | |
825 oop element = java_lang_StackTraceElement::create(method, bci, CHECK_NULL); | |
826 return JNIHandles::make_local(element); | |
827 C2V_END | |
828 | |
829 C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject args)) | |
830 ResourceMark rm; | |
831 HandleMark hm; | |
832 | |
833 assert(metaspace_method != 0, "just checking"); | |
834 methodHandle mh = asMethod(metaspace_method); | |
835 Symbol* signature = mh->signature(); | |
836 JavaCallArguments jca; | |
837 | |
838 JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); | |
839 JavaValue result(jap.get_ret_type()); | |
840 | |
841 nmethod* nm = (nmethod*) (address) metaspace_nmethod; | |
842 if (nm == NULL || !nm->is_alive()) { | |
843 THROW_0(vmSymbols::MethodInvalidatedException()); | |
844 } | |
845 | |
846 JavaCalls::call(&result, mh, nm, &jca, CHECK_NULL); | |
847 | |
848 if (jap.get_ret_type() == T_VOID) { | |
849 return NULL; | |
850 } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) { | |
851 return JNIHandles::make_local((oop) result.get_jobject()); | |
852 } else { | |
853 oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL); | |
854 return JNIHandles::make_local(o); | |
855 } | |
856 C2V_END | |
857 | |
858 C2V_VMENTRY(jobject, executeCompiledMethod, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject arg1, jobject arg2, jobject arg3)) | |
859 ResourceMark rm; | |
860 HandleMark hm; | |
861 | |
862 methodHandle method = asMethod(metaspace_method); | |
863 assert(!method.is_null(), "just checking"); | |
864 JavaValue result(T_OBJECT); | |
865 JavaCallArguments args; | |
866 args.push_oop(JNIHandles::resolve(arg1)); | |
867 args.push_oop(JNIHandles::resolve(arg2)); | |
868 args.push_oop(JNIHandles::resolve(arg3)); | |
869 | |
870 nmethod* nm = (nmethod*) (address) metaspace_nmethod; | |
871 if (nm == NULL || !nm->is_alive()) { | |
872 THROW_0(vmSymbols::MethodInvalidatedException()); | |
873 } | |
874 | |
875 JavaCalls::call(&result, method, nm, &args, CHECK_NULL); | |
876 | |
877 return JNIHandles::make_local((oop) result.get_jobject()); | |
878 C2V_END | |
879 | |
880 C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method)) | |
881 | |
882 Method* method = asMethod(metaspace_method); | |
883 assert(!InstanceKlass::cast(method->method_holder())->is_interface(), "vtableEntryOffset cannot be called for interface methods"); | |
884 assert(InstanceKlass::cast(method->method_holder())->is_linked(), "vtableEntryOffset cannot be called is holder is not linked"); | |
885 | |
886 // get entry offset in words | |
887 int vtable_entry_offset = InstanceKlass::vtable_start_offset() + method->vtable_index() * vtableEntry::size(); | |
888 // convert to bytes | |
889 vtable_entry_offset = vtable_entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); | |
890 | |
891 return vtable_entry_offset; | |
892 C2V_END | |
893 | |
894 C2V_VMENTRY(jobject, getDeoptedLeafGraphIds, (JNIEnv *, jobject)) | |
895 | |
896 // the contract for this method is as follows: | |
897 // returning null: no deopted leaf graphs | |
898 // returning array (size > 0): the ids of the deopted leaf graphs | |
899 // returning array (size == 0): there was an overflow, the compiler needs to clear its cache completely | |
900 | |
901 oop array = GraalCompiler::instance()->dump_deopted_leaf_graphs(CHECK_NULL); | |
902 return JNIHandles::make_local(array); | |
903 C2V_END | |
904 | |
905 C2V_VMENTRY(jobject, decodePC, (JNIEnv *, jobject, jlong pc)) | |
906 stringStream(st); | |
907 CodeBlob* blob = CodeCache::find_blob_unsafe((void*) pc); | |
908 if (blob == NULL) { | |
909 st.print("[unidentified pc]"); | |
910 } else { | |
911 st.print(blob->name()); | |
912 | |
913 nmethod* nm = blob->as_nmethod_or_null(); | |
914 if (nm != NULL && nm->method() != NULL) { | |
915 st.print(" %s.", nm->method()->method_holder()->external_name()); | |
916 nm->method()->name()->print_symbol_on(&st); | |
917 st.print(" @ %d", pc - (jlong) nm->entry_point()); | |
918 } | |
919 } | |
920 Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); | |
921 return JNIHandles::make_local(result()); | |
922 C2V_END | |
923 | |
924 | |
925 #define CC (char*) /*cast a literal from (const char*)*/ | |
926 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) | |
927 | |
928 #define RESOLVED_TYPE "Lcom/oracle/graal/api/meta/ResolvedJavaType;" | |
929 #define TYPE "Lcom/oracle/graal/api/meta/JavaType;" | |
930 #define METHOD "Lcom/oracle/graal/api/meta/JavaMethod;" | |
931 #define FIELD "Lcom/oracle/graal/api/meta/JavaField;" | |
932 #define SIGNATURE "Lcom/oracle/graal/api/meta/Signature;" | |
933 #define CONSTANT_POOL "Lcom/oracle/graal/api/meta/ConstantPool;" | |
934 #define CONSTANT "Lcom/oracle/graal/api/meta/Constant;" | |
935 #define KIND "Lcom/oracle/graal/api/meta/Kind;" | |
936 #define RUNTIME_CALL "Lcom/oracle/graal/api/code/RuntimeCall;" | |
937 #define EXCEPTION_HANDLERS "[Lcom/oracle/graal/api/meta/ExceptionHandler;" | |
938 #define REFLECT_METHOD "Ljava/lang/reflect/Method;" | |
939 #define REFLECT_CONSTRUCTOR "Ljava/lang/reflect/Constructor;" | |
940 #define REFLECT_FIELD "Ljava/lang/reflect/Field;" | |
941 #define STRING "Ljava/lang/String;" | |
942 #define OBJECT "Ljava/lang/Object;" | |
943 #define CLASS "Ljava/lang/Class;" | |
944 #define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;" | |
945 #define HS_RESOLVED_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;" | |
946 #define HS_RESOLVED_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;" | |
947 #define HS_RESOLVED_FIELD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaField;" | |
948 #define HS_COMP_RESULT "Lcom/oracle/graal/hotspot/HotSpotCompilationResult;" | |
949 #define HS_CONFIG "Lcom/oracle/graal/hotspot/HotSpotVMConfig;" | |
950 #define HS_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotMethod;" | |
951 #define HS_INSTALLED_CODE "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;" | |
952 #define HS_CODE_INFO "Lcom/oracle/graal/hotspot/meta/HotSpotCodeInfo;" | |
953 #define METHOD_DATA "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;" | |
954 #define METASPACE_METHOD "J" | |
955 #define METASPACE_METHOD_DATA "J" | |
956 #define NMETHOD "J" | |
957 | |
958 JNINativeMethod CompilerToVM_methods[] = { | |
959 {CC"initializeBytecode", CC"("METASPACE_METHOD"[B)[B", FN_PTR(initializeBytecode)}, | |
960 {CC"getSignature", CC"("METASPACE_METHOD")"STRING, FN_PTR(getSignature)}, | |
961 {CC"initializeExceptionHandlers", CC"("METASPACE_METHOD EXCEPTION_HANDLERS")"EXCEPTION_HANDLERS, FN_PTR(initializeExceptionHandlers)}, | |
962 {CC"hasBalancedMonitors", CC"("METASPACE_METHOD")Z", FN_PTR(hasBalancedMonitors)}, | |
963 {CC"getUniqueConcreteMethod", CC"("METASPACE_METHOD"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getUniqueConcreteMethod)}, | |
7225
31c4d9f9e922
adder better CHA support
Christian Haeubl <haeubl@ssw.jku.at>
parents:
7222
diff
changeset
|
964 {CC"getUniqueImplementor", CC"("HS_RESOLVED_TYPE")"RESOLVED_TYPE, FN_PTR(getUniqueImplementor)}, |
7221 | 965 {CC"getStackTraceElement", CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, |
966 {CC"initializeMethod", CC"("METASPACE_METHOD HS_RESOLVED_METHOD")V", FN_PTR(initializeMethod)}, | |
967 {CC"initializeMethodData", CC"("METASPACE_METHOD_DATA METHOD_DATA")V", FN_PTR(initializeMethodData)}, | |
968 {CC"isMethodCompilable", CC"("METASPACE_METHOD")Z", FN_PTR(isMethodCompilable)}, | |
969 {CC"getInvocationCount", CC"("METASPACE_METHOD")I", FN_PTR(getInvocationCount)}, | |
970 {CC"getCompiledCodeSize", CC"("METASPACE_METHOD")I", FN_PTR(getCompiledCodeSize)}, | |
971 {CC"getVtableEntryOffset", CC"("METASPACE_METHOD")I", FN_PTR(getVtableEntryOffset)}, | |
972 {CC"lookupType", CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE, FN_PTR(lookupType)}, | |
973 {CC"lookupConstantInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupConstantInPool)}, | |
974 {CC"lookupMethodInPool", CC"("HS_RESOLVED_TYPE"IB)"METHOD, FN_PTR(lookupMethodInPool)}, | |
975 {CC"lookupTypeInPool", CC"("HS_RESOLVED_TYPE"I)"TYPE, FN_PTR(lookupTypeInPool)}, | |
976 {CC"lookupReferencedTypeInPool", CC"("HS_RESOLVED_TYPE"IB)V", FN_PTR(lookupReferencedTypeInPool)}, | |
977 {CC"lookupFieldInPool", CC"("HS_RESOLVED_TYPE"IB)"FIELD, FN_PTR(lookupFieldInPool)}, | |
978 {CC"resolveMethod", CC"("HS_RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(resolveMethod)}, | |
979 {CC"getInstanceFields", CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD, FN_PTR(getInstanceFields)}, | |
980 {CC"isTypeInitialized", CC"("HS_RESOLVED_TYPE")Z", FN_PTR(isTypeInitialized)}, | |
981 {CC"initializeType", CC"("HS_RESOLVED_TYPE")V", FN_PTR(initializeType)}, | |
982 {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)}, | |
983 {CC"getResolvedType", CC"("CLASS")"RESOLVED_TYPE, FN_PTR(getResolvedType)}, | |
984 {CC"getMetaspaceMethod", CC"("REFLECT_METHOD"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getMetaspaceMethod)}, | |
985 {CC"getMetaspaceConstructor", CC"("REFLECT_CONSTRUCTOR"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getMetaspaceConstructor)}, | |
986 {CC"getJavaField", CC"("REFLECT_FIELD")"HS_RESOLVED_FIELD, FN_PTR(getJavaField)}, | |
987 {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)}, | |
988 {CC"installCode0", CC"("HS_COMP_RESULT HS_INSTALLED_CODE HS_CODE_INFO")I", FN_PTR(installCode0)}, | |
989 {CC"disassembleNative", CC"([BJ)"STRING, FN_PTR(disassembleNative)}, | |
990 {CC"executeCompiledMethod", CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, | |
991 {CC"executeCompiledMethodVarargs", CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, | |
992 {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, | |
993 {CC"decodePC", CC"(J)"STRING, FN_PTR(decodePC)}, | |
994 }; | |
995 | |
996 int CompilerToVM_methods_count() { | |
997 return sizeof(CompilerToVM_methods) / sizeof(JNINativeMethod); | |
998 } | |
999 |