Mercurial > hg > graal-compiler
comparison src/share/vm/graal/graalCompilerToVM.cpp @ 4220:5c80ccb80036
Renaming of VMExits and VMEntries part 1.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Wed, 04 Jan 2012 20:59:11 +0100 |
parents | src/share/vm/graal/graalVMEntries.cpp@aaac4894175c |
children | 8e2985cdaaa5 |
comparison
equal
deleted
inserted
replaced
4214:35b05867c94a | 4220:5c80ccb80036 |
---|---|
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 "c1/c1_Runtime1.hpp" | |
27 #include "ci/ciMethodData.hpp" | |
28 #include "compiler/compileBroker.hpp" | |
29 #include "graal/graalVMEntries.hpp" | |
30 #include "graal/graalCompiler.hpp" | |
31 #include "graal/graalEnv.hpp" | |
32 #include "graal/graalJavaAccess.hpp" | |
33 #include "graal/graalCodeInstaller.hpp" | |
34 #include "graal/graalVMExits.hpp" | |
35 #include "graal/graalVmIds.hpp" | |
36 #include "memory/oopFactory.hpp" | |
37 #include "oops/generateOopMap.hpp" | |
38 | |
39 methodOop getMethodFromHotSpotMethod(jobject hotspot_method) { | |
40 return getMethodFromHotSpotMethod(JNIHandles::resolve(hotspot_method)); | |
41 } | |
42 | |
43 methodOop getMethodFromHotSpotMethod(oop hotspot_method) { | |
44 return (methodOop)HotSpotMethodResolved::javaMirror(hotspot_method); | |
45 } | |
46 | |
47 // public byte[] RiMethod_code(HotSpotResolvedMethod method); | |
48 JNIEXPORT jbyteArray JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1code(JNIEnv *env, jobject, jobject hotspot_method) { | |
49 TRACE_graal_3("CompilerToVM::RiMethod_code"); | |
50 methodHandle method = getMethodFromHotSpotMethod(hotspot_method); | |
51 int code_size = method->code_size(); | |
52 jbyteArray result = env->NewByteArray(code_size); | |
53 env->SetByteArrayRegion(result, 0, code_size, (const jbyte *) method->code_base()); | |
54 return result; | |
55 } | |
56 | |
57 // public String RiMethod_signature(HotSpotResolvedMethod method); | |
58 JNIEXPORT jstring JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1signature(JNIEnv *env, jobject, jobject hotspot_method) { | |
59 TRACE_graal_3("CompilerToVM::RiMethod_signature"); | |
60 VM_ENTRY_MARK | |
61 methodOop method = getMethodFromHotSpotMethod(hotspot_method); | |
62 assert(method != NULL && method->signature() != NULL, "signature required"); | |
63 return VmIds::toString<jstring>(method->signature(), THREAD); | |
64 } | |
65 | |
66 // public RiExceptionHandler[] RiMethod_exceptionHandlers(long vmId); | |
67 JNIEXPORT jobjectArray JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1exceptionHandlers(JNIEnv *, jobject, jobject hotspot_method) { | |
68 TRACE_graal_3("CompilerToVM::RiMethod_exceptionHandlers"); | |
69 VM_ENTRY_MARK | |
70 ResourceMark rm; | |
71 methodHandle method = getMethodFromHotSpotMethod(hotspot_method); | |
72 typeArrayHandle handlers = method->exception_table(); | |
73 int handler_count = handlers.is_null() ? 0 : handlers->length() / 4; | |
74 | |
75 instanceKlass::cast(HotSpotExceptionHandler::klass())->initialize(CHECK_NULL); | |
76 objArrayHandle array = oopFactory::new_objArray(SystemDictionary::RiExceptionHandler_klass(), handler_count, CHECK_NULL); | |
77 | |
78 for (int i = 0; i < handler_count; i++) { | |
79 // exception handlers are stored as four integers: start bci, end bci, handler bci, catch class constant pool index | |
80 int base = i * 4; | |
81 Handle entry = instanceKlass::cast(HotSpotExceptionHandler::klass())->allocate_instance(CHECK_NULL); | |
82 HotSpotExceptionHandler::set_startBci(entry, handlers->int_at(base + 0)); | |
83 HotSpotExceptionHandler::set_endBci(entry, handlers->int_at(base + 1)); | |
84 HotSpotExceptionHandler::set_handlerBci(entry, handlers->int_at(base + 2)); | |
85 int catch_class_index = handlers->int_at(base + 3); | |
86 HotSpotExceptionHandler::set_catchClassIndex(entry, catch_class_index); | |
87 | |
88 if (catch_class_index == 0) { | |
89 HotSpotExceptionHandler::set_catchClass(entry, NULL); | |
90 } else { | |
91 constantPoolOop cp = instanceKlass::cast(method->method_holder())->constants(); | |
92 KlassHandle loading_klass = method->method_holder(); | |
93 Handle catch_class = GraalCompiler::get_RiType(cp, catch_class_index, loading_klass, CHECK_NULL); | |
94 if (catch_class->klass() == HotSpotTypeResolved::klass() && java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(catch_class)) == SystemDictionary::Throwable_klass()) { | |
95 HotSpotExceptionHandler::set_catchClass(entry, NULL); | |
96 HotSpotExceptionHandler::set_catchClassIndex(entry, 0); | |
97 } else { | |
98 HotSpotExceptionHandler::set_catchClass(entry, catch_class()); | |
99 } | |
100 } | |
101 array->obj_at_put(i, entry()); | |
102 } | |
103 | |
104 return (jobjectArray) JNIHandles::make_local(array()); | |
105 } | |
106 | |
107 // public boolean RiMethod_hasBalancedMonitors(long vmId); | |
108 JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1hasBalancedMonitors(JNIEnv *, jobject, jobject hotspot_method) { | |
109 TRACE_graal_3("CompilerToVM::RiMethod_hasBalancedMonitors"); | |
110 | |
111 VM_ENTRY_MARK; | |
112 | |
113 // Analyze the method to see if monitors are used properly. | |
114 methodHandle method(THREAD, getMethodFromHotSpotMethod(hotspot_method)); | |
115 assert(method->has_monitor_bytecodes(), "should have checked this"); | |
116 | |
117 // Check to see if a previous compilation computed the monitor-matching analysis. | |
118 if (method->guaranteed_monitor_matching()) { | |
119 return true; | |
120 } | |
121 | |
122 { | |
123 EXCEPTION_MARK; | |
124 ResourceMark rm(THREAD); | |
125 GeneratePairingInfo gpi(method); | |
126 gpi.compute_map(CATCH); | |
127 if (!gpi.monitor_safe()) { | |
128 return false; | |
129 } | |
130 method->set_guaranteed_monitor_matching(); | |
131 } | |
132 return true; | |
133 } | |
134 | |
135 // public RiMethod getRiMethod(java.lang.reflect.Method reflectionMethod); | |
136 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getRiMethod(JNIEnv *, jobject, jobject reflection_method_handle) { | |
137 TRACE_graal_3("CompilerToVM::getRiMethod"); | |
138 VM_ENTRY_MARK; | |
139 oop reflection_method = JNIHandles::resolve(reflection_method_handle); | |
140 oop reflection_holder = java_lang_reflect_Method::clazz(reflection_method); | |
141 int slot = java_lang_reflect_Method::slot(reflection_method); | |
142 klassOop holder = java_lang_Class::as_klassOop(reflection_holder); | |
143 methodOop method = instanceKlass::cast(holder)->method_with_idnum(slot); | |
144 Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); | |
145 return JNIHandles::make_local(THREAD, ret()); | |
146 } | |
147 | |
148 // public boolean RiMethod_uniqueConcreteMethod(long vmId); | |
149 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1uniqueConcreteMethod(JNIEnv *, jobject, jobject hotspot_method) { | |
150 TRACE_graal_3("CompilerToVM::RiMethod_uniqueConcreteMethod"); | |
151 | |
152 VM_ENTRY_MARK; | |
153 methodHandle method = getMethodFromHotSpotMethod(hotspot_method); | |
154 KlassHandle holder = method->method_holder(); | |
155 if (holder->is_interface()) { | |
156 // Cannot trust interfaces. Because of: | |
157 // interface I { void foo(); } | |
158 // class A { public void foo() {} } | |
159 // class B extends A implements I { } | |
160 // class C extends B { public void foo() { } } | |
161 // class D extends B { } | |
162 // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo(). | |
163 return false; | |
164 } | |
165 methodHandle unique_concrete; | |
166 { | |
167 ResourceMark rm; | |
168 MutexLocker locker(Compile_lock); | |
169 unique_concrete = Dependencies::find_unique_concrete_method(holder(), method()); | |
170 } | |
171 if (unique_concrete.is_null()) { | |
172 return NULL; | |
173 } else { | |
174 Handle method_resolved = GraalCompiler::createHotSpotMethodResolved(unique_concrete, CHECK_NULL); | |
175 return JNIHandles::make_local(THREAD, method_resolved()); | |
176 } | |
177 } | |
178 | |
179 // public native int RiMethod_invocationCount(long vmId); | |
180 JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1invocationCount(JNIEnv *, jobject, jobject hotspot_method) { | |
181 TRACE_graal_3("CompilerToVM::RiMethod_invocationCount"); | |
182 return getMethodFromHotSpotMethod(hotspot_method)->invocation_count(); | |
183 } | |
184 | |
185 // public native int RiMethod_exceptionProbability(long vmId, int bci); | |
186 JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_2exceptionProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { | |
187 TRACE_graal_3("CompilerToVM::RiMethod_exceptionProbability"); | |
188 VM_ENTRY_MARK; | |
189 ResourceMark rm; | |
190 methodHandle method = getMethodFromHotSpotMethod(hotspot_method); | |
191 methodDataHandle method_data = method->method_data(); | |
192 if (method_data == NULL || !method_data->is_mature()) { | |
193 return -1; | |
194 } | |
195 ProfileData* data = method_data->bci_to_data(bci); | |
196 if (data == NULL) { | |
197 return 0; | |
198 } | |
199 uint trap = Deoptimization::trap_state_is_recompiled(data->trap_state())? 1: 0; | |
200 if (trap > 0) { | |
201 return 100; | |
202 } else { | |
203 return trap; | |
204 } | |
205 } | |
206 | |
207 // ------------------------------------------------------------------ | |
208 // Adjust a CounterData count to be commensurate with | |
209 // interpreter_invocation_count. If the MDO exists for | |
210 // only 25% of the time the method exists, then the | |
211 // counts in the MDO should be scaled by 4X, so that | |
212 // they can be usefully and stably compared against the | |
213 // invocation counts in methods. | |
214 int scale_count(methodDataOop method_data, int count) { | |
215 if (count > 0) { | |
216 int counter_life; | |
217 int method_life = method_data->method()->interpreter_invocation_count(); | |
218 int current_mileage = methodDataOopDesc::mileage_of(method_data->method()); | |
219 int creation_mileage = method_data->creation_mileage(); | |
220 counter_life = current_mileage - creation_mileage; | |
221 | |
222 // counter_life due to backedge_counter could be > method_life | |
223 if (counter_life > method_life) | |
224 counter_life = method_life; | |
225 if (0 < counter_life && counter_life <= method_life) { | |
226 count = (int)((double)count * method_life / counter_life + 0.5); | |
227 count = (count > 0) ? count : 1; | |
228 } | |
229 } | |
230 return count; | |
231 } | |
232 | |
233 // public native RiTypeProfile RiMethod_typeProfile(long vmId, int bci); | |
234 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_2typeProfile(JNIEnv *, jobject, jobject hotspot_method, jint bci) { | |
235 TRACE_graal_3("CompilerToVM::RiMethod_typeProfile"); | |
236 VM_ENTRY_MARK; | |
237 Handle obj; | |
238 | |
239 methodHandle method = getMethodFromHotSpotMethod(hotspot_method); | |
240 methodDataHandle method_data = method->method_data(); | |
241 if (method_data == NULL || !method_data->is_mature()) { | |
242 return NULL; | |
243 } | |
244 ResourceMark rm; | |
245 ProfileData* data = method_data->bci_to_data(bci); | |
246 if (data != NULL && data->is_ReceiverTypeData()) { | |
247 ReceiverTypeData* recv = data->as_ReceiverTypeData(); | |
248 GrowableArray<KlassHandle> receivers; | |
249 GrowableArray<int> counts; | |
250 // determine morphism | |
251 uint total_count = 0; | |
252 for (uint i = 0; i < recv->row_limit(); i++) { | |
253 klassOop receiver = recv->receiver(i); | |
254 if (receiver == NULL) continue; | |
255 uint count = recv->receiver_count(i); | |
256 total_count += count; | |
257 receivers.append(receiver); | |
258 counts.append(count); | |
259 } | |
260 | |
261 instanceKlass::cast(RiTypeProfile::klass())->initialize(CHECK_NULL); | |
262 obj = instanceKlass::cast(RiTypeProfile::klass())->allocate_instance(CHECK_NULL); | |
263 assert(obj() != NULL, "must succeed in allocating instance"); | |
264 | |
265 int count = MAX2(total_count, recv->count()); | |
266 RiTypeProfile::set_count(obj, scale_count(method_data(), count)); | |
267 RiTypeProfile::set_morphism(obj, receivers.length()); | |
268 | |
269 if (receivers.length() > 0) { | |
270 typeArrayHandle probabilities = oopFactory::new_typeArray(T_FLOAT, receivers.length(), CHECK_NULL); | |
271 objArrayHandle types = oopFactory::new_objArray(SystemDictionary::RiType_klass(), receivers.length(), CHECK_NULL); | |
272 for (int i = 0; i < receivers.length(); i++) { | |
273 KlassHandle receiver = receivers.at(i); | |
274 | |
275 float prob = counts.at(i) / (float) total_count; | |
276 Handle type = GraalCompiler::get_RiType(receiver, CHECK_NULL); | |
277 | |
278 probabilities->float_at_put(i, prob); | |
279 types->obj_at_put(i, type()); | |
280 | |
281 } | |
282 | |
283 RiTypeProfile::set_probabilities(obj, probabilities()); | |
284 RiTypeProfile::set_types(obj, types()); | |
285 } else { | |
286 RiTypeProfile::set_probabilities(obj, NULL); | |
287 RiTypeProfile::set_types(obj, NULL); | |
288 } | |
289 } | |
290 return JNIHandles::make_local(obj()); | |
291 } | |
292 | |
293 JNIEXPORT jdouble JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_2branchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { | |
294 TRACE_graal_3("CompilerToVM::RiMethod_typeProfile"); | |
295 ResourceMark rm; | |
296 methodHandle method = getMethodFromHotSpotMethod(hotspot_method); | |
297 methodDataHandle method_data = method->method_data(); | |
298 | |
299 if (method_data == NULL || !method_data->is_mature()) return -1; | |
300 method_data->bci_to_data(bci); | |
301 | |
302 ProfileData* data = method_data->bci_to_data(bci); | |
303 if (data == NULL || !data->is_JumpData()) return -1; | |
304 | |
305 // get taken and not taken values | |
306 int taken = data->as_JumpData()->taken(); | |
307 int not_taken = 0; | |
308 if (data->is_BranchData()) { | |
309 not_taken = data->as_BranchData()->not_taken(); | |
310 } | |
311 | |
312 // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful. | |
313 // We also check that individual counters are positive first, otherwise the sum can become positive. | |
314 if (taken < 0 || not_taken < 0 || taken + not_taken < 40) return -1; | |
315 | |
316 // Pin probability to sane limits | |
317 if (taken == 0) | |
318 return 0; | |
319 else if (not_taken == 0) | |
320 return 1; | |
321 else { // Compute probability of true path | |
322 return (jdouble)(taken) / (taken + not_taken); | |
323 } | |
324 } | |
325 | |
326 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_2switchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { | |
327 TRACE_graal_3("CompilerToVM::RiMethod_typeProfile"); | |
328 VM_ENTRY_MARK; | |
329 ResourceMark rm; | |
330 methodHandle method = getMethodFromHotSpotMethod(hotspot_method); | |
331 methodDataHandle method_data = method->method_data(); | |
332 | |
333 if (method_data == NULL || !method_data->is_mature()) return NULL; | |
334 | |
335 ProfileData* data = method_data->bci_to_data(bci); | |
336 if (data == NULL || !data->is_MultiBranchData()) return NULL; | |
337 | |
338 MultiBranchData* branch_data = data->as_MultiBranchData(); | |
339 | |
340 long sum = 0; | |
341 int cases = branch_data->number_of_cases(); | |
342 GrowableArray<uint>* counts = new GrowableArray<uint>(cases + 1); | |
343 | |
344 for (int i = 0; i < cases; i++) { | |
345 uint value = branch_data->count_at(i); | |
346 sum += value; | |
347 counts->append(value); | |
348 } | |
349 uint value = branch_data->default_count(); | |
350 sum += value; | |
351 counts->append(value); | |
352 | |
353 // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful. | |
354 // We also check that individual counters are positive first, otherwise the sum can become positive. | |
355 if (sum < 10 * (cases + 3)) return NULL; | |
356 | |
357 typeArrayOop probability = oopFactory::new_typeArray(T_DOUBLE, cases + 1, CHECK_NULL); | |
358 for (int i = 0; i < cases + 1; i++) { | |
359 probability->double_at_put(i, counts->at(i) / (double) sum); | |
360 } | |
361 return JNIHandles::make_local(probability); | |
362 } | |
363 | |
364 // public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); | |
365 JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1hasCompiledCode(JNIEnv *, jobject, jobject hotspot_method) { | |
366 TRACE_graal_3("CompilerToVM::RiMethod_hasCompiledCode"); | |
367 return getMethodFromHotSpotMethod(hotspot_method)->has_compiled_code(); | |
368 } | |
369 | |
370 // public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); | |
371 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) { | |
372 TRACE_graal_3("CompilerToVM::RiSignature_lookupType"); | |
373 VM_ENTRY_MARK; | |
374 ResourceMark rm; | |
375 | |
376 Symbol* nameSymbol = VmIds::toSymbol(jname); | |
377 Handle name = JNIHandles::resolve(jname); | |
378 | |
379 oop result; | |
380 if (nameSymbol == vmSymbols::int_signature()) { | |
381 result = VMToCompiler::createRiTypePrimitive((int) T_INT, THREAD); | |
382 } else if (nameSymbol == vmSymbols::long_signature()) { | |
383 result = VMToCompiler::createRiTypePrimitive((int) T_LONG, THREAD); | |
384 } else if (nameSymbol == vmSymbols::bool_signature()) { | |
385 result = VMToCompiler::createRiTypePrimitive((int) T_BOOLEAN, THREAD); | |
386 } else if (nameSymbol == vmSymbols::char_signature()) { | |
387 result = VMToCompiler::createRiTypePrimitive((int) T_CHAR, THREAD); | |
388 } else if (nameSymbol == vmSymbols::short_signature()) { | |
389 result = VMToCompiler::createRiTypePrimitive((int) T_SHORT, THREAD); | |
390 } else if (nameSymbol == vmSymbols::byte_signature()) { | |
391 result = VMToCompiler::createRiTypePrimitive((int) T_BYTE, THREAD); | |
392 } else if (nameSymbol == vmSymbols::double_signature()) { | |
393 result = VMToCompiler::createRiTypePrimitive((int) T_DOUBLE, THREAD); | |
394 } else if (nameSymbol == vmSymbols::float_signature()) { | |
395 result = VMToCompiler::createRiTypePrimitive((int) T_FLOAT, THREAD); | |
396 } else { | |
397 klassOop resolved_type = NULL; | |
398 // if the name isn't in the symbol table then the class isn't loaded anyway... | |
399 if (nameSymbol != NULL) { | |
400 Handle classloader; | |
401 Handle protectionDomain; | |
402 if (JNIHandles::resolve(accessingClass) != NULL) { | |
403 classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader(); | |
404 protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain(); | |
405 } | |
406 resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); | |
407 if (HAS_PENDING_EXCEPTION) { | |
408 CLEAR_PENDING_EXCEPTION; | |
409 resolved_type = NULL; | |
410 } | |
411 } | |
412 if (resolved_type != NULL) { | |
413 Handle type = GraalCompiler::createHotSpotTypeResolved(resolved_type, name, CHECK_NULL); | |
414 result = type(); | |
415 } else { | |
416 Handle type = VMToCompiler::createRiTypeUnresolved(name, THREAD); | |
417 result = type(); | |
418 } | |
419 } | |
420 | |
421 return JNIHandles::make_local(THREAD, result); | |
422 } | |
423 | |
424 // public Object RiConstantPool_lookupConstant(HotSpotTypeResolved type, int cpi); | |
425 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1lookupConstant(JNIEnv *env, jobject, jobject type, jint index) { | |
426 TRACE_graal_3("CompilerToVM::RiConstantPool_lookupConstant"); | |
427 VM_ENTRY_MARK; | |
428 | |
429 constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); | |
430 | |
431 oop result = NULL; | |
432 constantTag tag = cp->tag_at(index); | |
433 if (tag.is_int()) { | |
434 result = VMToCompiler::createCiConstant(CiKind::Int(), cp->int_at(index), CHECK_0); | |
435 } else if (tag.is_long()) { | |
436 result = VMToCompiler::createCiConstant(CiKind::Long(), cp->long_at(index), CHECK_0); | |
437 } else if (tag.is_float()) { | |
438 result = VMToCompiler::createCiConstantFloat(cp->float_at(index), CHECK_0); | |
439 } else if (tag.is_double()) { | |
440 result = VMToCompiler::createCiConstantDouble(cp->double_at(index), CHECK_0); | |
441 } else if (tag.is_string() || tag.is_unresolved_string()) { | |
442 oop string = NULL; | |
443 if (cp->is_pseudo_string_at(index)) { | |
444 string = cp->pseudo_string_at(index); | |
445 } else { | |
446 string = cp->string_at(index, THREAD); | |
447 if (HAS_PENDING_EXCEPTION) { | |
448 CLEAR_PENDING_EXCEPTION; | |
449 // TODO: Gracefully exit compilation. | |
450 fatal("out of memory during compilation!"); | |
451 return NULL; | |
452 } | |
453 } | |
454 result = VMToCompiler::createCiConstantObject(string, CHECK_0); | |
455 } else if (tag.is_klass() || tag.is_unresolved_klass()) { | |
456 Handle type = GraalCompiler::get_RiType(cp, index, cp->pool_holder(), CHECK_NULL); | |
457 result = type(); | |
458 } else if (tag.is_object()) { | |
459 oop obj = cp->object_at(index); | |
460 assert(obj->is_instance(), "must be an instance"); | |
461 result = VMToCompiler::createCiConstantObject(obj, CHECK_NULL); | |
462 } else { | |
463 ShouldNotReachHere(); | |
464 } | |
465 | |
466 return JNIHandles::make_local(THREAD, result); | |
467 } | |
468 | |
469 // public RiMethod RiConstantPool_lookupMethod(long vmId, int cpi, byte byteCode); | |
470 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1lookupMethod(JNIEnv *env, jobject, jobject type, jint index, jbyte byteCode) { | |
471 TRACE_graal_3("CompilerToVM::RiConstantPool_lookupMethod"); | |
472 VM_ENTRY_MARK; | |
473 index = GraalCompiler::to_cp_index_u2(index); | |
474 constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); | |
475 instanceKlassHandle pool_holder(cp->pool_holder()); | |
476 | |
477 Bytecodes::Code bc = (Bytecodes::Code) (((int) byteCode) & 0xFF); | |
478 methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); | |
479 if (!method.is_null()) { | |
480 Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); | |
481 return JNIHandles::make_local(THREAD, ret()); | |
482 } else { | |
483 // Get the method's name and signature. | |
484 Handle name = VmIds::toString<Handle>(cp->name_ref_at(index), CHECK_NULL); | |
485 Handle signature = VmIds::toString<Handle>(cp->signature_ref_at(index), CHECK_NULL); | |
486 int holder_index = cp->klass_ref_index_at(index); | |
487 Handle type = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL); | |
488 return JNIHandles::make_local(THREAD, VMToCompiler::createRiMethodUnresolved(name, signature, type, THREAD)); | |
489 } | |
490 } | |
491 | |
492 // public RiType RiConstantPool_lookupType(long vmId, int cpi); | |
493 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1lookupType(JNIEnv *env, jobject, jobject type, jint index) { | |
494 TRACE_graal_3("CompilerToVM::RiConstantPool_lookupType"); | |
495 VM_ENTRY_MARK; | |
496 | |
497 constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); | |
498 Handle result = GraalCompiler::get_RiType(cp, index, cp->pool_holder(), CHECK_NULL); | |
499 return JNIHandles::make_local(THREAD, result()); | |
500 } | |
501 | |
502 // public void RiConstantPool_loadReferencedType(long vmId, int cpi); | |
503 JNIEXPORT void JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1loadReferencedType(JNIEnv *env, jobject, jobject type, jint index, jbyte op) { | |
504 TRACE_graal_3("CompilerToVM::RiConstantPool_loadReferencedType"); | |
505 VM_ENTRY_MARK; | |
506 | |
507 constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); | |
508 int byteCode = (op & 0xFF); | |
509 if (byteCode != Bytecodes::_checkcast && byteCode != Bytecodes::_instanceof && byteCode != Bytecodes::_new && byteCode != Bytecodes::_anewarray && byteCode != Bytecodes::_multianewarray) { | |
510 index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index_u2(index)); | |
511 } | |
512 constantTag tag = cp->tag_at(index); | |
513 if (tag.is_field_or_method()) { | |
514 index = cp->uncached_klass_ref_index_at(index); | |
515 tag = cp->tag_at(index); | |
516 } | |
517 | |
518 if (tag.is_unresolved_klass() || tag.is_klass()) { | |
519 klassOop klass = cp->klass_at(index, CHECK); | |
520 if (klass->klass_part()->oop_is_instance()) { | |
521 instanceKlass::cast(klass)->initialize(CHECK); | |
522 } | |
523 } | |
524 } | |
525 | |
526 // public RiField RiConstantPool_lookupField(long vmId, int cpi); | |
527 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1lookupField(JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte byteCode) { | |
528 TRACE_graal_3("CompilerToVM::RiConstantPool_lookupField"); | |
529 VM_ENTRY_MARK; | |
530 ResourceMark rm; | |
531 | |
532 index = GraalCompiler::to_cp_index_u2(index); | |
533 constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(constantPoolHolder)))->constants(); | |
534 | |
535 int nt_index = cp->name_and_type_ref_index_at(index); | |
536 int sig_index = cp->signature_ref_index_at(nt_index); | |
537 Symbol* signature = cp->symbol_at(sig_index); | |
538 int name_index = cp->name_ref_index_at(nt_index); | |
539 Symbol* name = cp->symbol_at(name_index); | |
540 int holder_index = cp->klass_ref_index_at(index); | |
541 Handle holder = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL); | |
542 instanceKlassHandle holder_klass; | |
543 | |
544 Bytecodes::Code code = (Bytecodes::Code)(((int) byteCode) & 0xFF); | |
545 int offset = -1; | |
546 AccessFlags flags; | |
547 BasicType basic_type; | |
548 if (holder->klass() == SystemDictionary::HotSpotTypeResolved_klass()) { | |
549 FieldAccessInfo result; | |
550 LinkResolver::resolve_field(result, cp, index, | |
551 Bytecodes::java_code(code), | |
552 true, false, Thread::current()); | |
553 if (HAS_PENDING_EXCEPTION) { | |
554 CLEAR_PENDING_EXCEPTION; | |
555 } else { | |
556 offset = result.field_offset(); | |
557 flags = result.access_flags(); | |
558 holder_klass = result.klass()->as_klassOop(); | |
559 basic_type = result.field_type(); | |
560 holder = GraalCompiler::get_RiType(holder_klass, CHECK_NULL); | |
561 } | |
562 } | |
563 | |
564 Handle type = GraalCompiler::get_RiTypeFromSignature(cp, sig_index, cp->pool_holder(), CHECK_NULL); | |
565 Handle field_handle = GraalCompiler::get_RiField(offset, flags.as_int(), name, holder, type, code, THREAD); | |
566 | |
567 oop constant_object = NULL; | |
568 // Check to see if the field is constant. | |
569 if (!holder_klass.is_null() && holder_klass->is_initialized() && flags.is_final() && flags.is_static()) { | |
570 // This field just may be constant. The only cases where it will | |
571 // not be constant are: | |
572 // | |
573 // 1. The field holds a non-perm-space oop. The field is, strictly | |
574 // speaking, constant but we cannot embed non-perm-space oops into | |
575 // generated code. For the time being we need to consider the | |
576 // field to be not constant. | |
577 // 2. The field is a *special* static&final field whose value | |
578 // may change. The three examples are java.lang.System.in, | |
579 // java.lang.System.out, and java.lang.System.err. | |
580 | |
581 bool ok = true; | |
582 assert( SystemDictionary::System_klass() != NULL, "Check once per vm"); | |
583 if( holder_klass->as_klassOop() == SystemDictionary::System_klass() ) { | |
584 // Check offsets for case 2: System.in, System.out, or System.err | |
585 if( offset == java_lang_System::in_offset_in_bytes() || | |
586 offset == java_lang_System::out_offset_in_bytes() || | |
587 offset == java_lang_System::err_offset_in_bytes() ) { | |
588 ok = false; | |
589 } | |
590 } | |
591 | |
592 if (ok) { | |
593 Handle mirror = holder_klass->java_mirror(); | |
594 switch(basic_type) { | |
595 case T_OBJECT: | |
596 case T_ARRAY: | |
597 constant_object = VMToCompiler::createCiConstantObject(mirror->obj_field(offset), CHECK_0); | |
598 break; | |
599 case T_DOUBLE: | |
600 constant_object = VMToCompiler::createCiConstantDouble(mirror->double_field(offset), CHECK_0); | |
601 break; | |
602 case T_FLOAT: | |
603 constant_object = VMToCompiler::createCiConstantFloat(mirror->float_field(offset), CHECK_0); | |
604 break; | |
605 case T_LONG: | |
606 constant_object = VMToCompiler::createCiConstant(CiKind::Long(), mirror->long_field(offset), CHECK_0); | |
607 break; | |
608 case T_INT: | |
609 constant_object = VMToCompiler::createCiConstant(CiKind::Int(), mirror->int_field(offset), CHECK_0); | |
610 break; | |
611 case T_SHORT: | |
612 constant_object = VMToCompiler::createCiConstant(CiKind::Short(), mirror->short_field(offset), CHECK_0); | |
613 break; | |
614 case T_CHAR: | |
615 constant_object = VMToCompiler::createCiConstant(CiKind::Char(), mirror->char_field(offset), CHECK_0); | |
616 break; | |
617 case T_BYTE: | |
618 constant_object = VMToCompiler::createCiConstant(CiKind::Byte(), mirror->byte_field(offset), CHECK_0); | |
619 break; | |
620 case T_BOOLEAN: | |
621 constant_object = VMToCompiler::createCiConstant(CiKind::Boolean(), mirror->bool_field(offset), CHECK_0); | |
622 break; | |
623 default: | |
624 fatal("Unhandled constant"); | |
625 break; | |
626 } | |
627 } | |
628 } | |
629 if (constant_object != NULL) { | |
630 HotSpotField::set_constant(field_handle, constant_object); | |
631 } | |
632 return JNIHandles::make_local(THREAD, field_handle()); | |
633 } | |
634 | |
635 // public RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature); | |
636 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_3resolveMethodImpl(JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature) { | |
637 TRACE_graal_3("CompilerToVM::RiType_resolveMethodImpl"); | |
638 VM_ENTRY_MARK; | |
639 | |
640 assert(JNIHandles::resolve(resolved_type) != NULL, ""); | |
641 klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(resolved_type)); | |
642 Symbol* name_symbol = VmIds::toSymbol(name); | |
643 Symbol* signature_symbol = VmIds::toSymbol(signature); | |
644 methodHandle method = klass->klass_part()->lookup_method(name_symbol, signature_symbol); | |
645 if (method == NULL) { | |
646 if (TraceGraal >= 3) { | |
647 ResourceMark rm; | |
648 tty->print_cr("Could not resolve method %s %s on klass %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), klass->klass_part()->name()->as_C_string()); | |
649 } | |
650 return NULL; | |
651 } | |
652 Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); | |
653 return JNIHandles::make_local(THREAD, ret()); | |
654 } | |
655 | |
656 // public boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); | |
657 JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_2isSubtypeOf(JNIEnv *, jobject, jobject klass, jobject jother) { | |
658 TRACE_graal_3("CompilerToVM::RiType_isSubtypeOf"); | |
659 oop other = JNIHandles::resolve(jother); | |
660 assert(other->is_a(HotSpotTypeResolved::klass()), "resolved hotspot type expected"); | |
661 assert(JNIHandles::resolve(klass) != NULL, ""); | |
662 klassOop thisKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); | |
663 klassOop otherKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(other)); | |
664 if (thisKlass->klass_part()->oop_is_instance_slow()) { | |
665 return instanceKlass::cast(thisKlass)->is_subtype_of(otherKlass); | |
666 } else if (thisKlass->klass_part()->oop_is_array()) { | |
667 return arrayKlass::cast(thisKlass)->is_subtype_of(otherKlass); | |
668 } else { | |
669 fatal("unexpected class type"); | |
670 return false; | |
671 } | |
672 } | |
673 | |
674 // public RiType RiType_componentType(HotSpotResolvedType klass); | |
675 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1componentType(JNIEnv *, jobject, jobject klass) { | |
676 TRACE_graal_3("CompilerToVM::RiType_componentType"); | |
677 VM_ENTRY_MARK; | |
678 KlassHandle array_klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); | |
679 if(array_klass->oop_is_typeArray()) { | |
680 BasicType t = typeArrayKlass::cast(array_klass())->element_type(); | |
681 oop primitive_type = VMToCompiler::createRiTypePrimitive((int) t, CHECK_NULL); | |
682 return JNIHandles::make_local(primitive_type); | |
683 } | |
684 assert(array_klass->oop_is_objArray(), "just checking"); | |
685 klassOop element_type = objArrayKlass::cast(array_klass())->element_klass(); | |
686 assert(JNIHandles::resolve(klass) != NULL, ""); | |
687 return JNIHandles::make_local(GraalCompiler::get_RiType(element_type, THREAD)()); | |
688 } | |
689 | |
690 // public RiType RiType_superType(HotSpotResolvedType klass); | |
691 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1superType(JNIEnv *, jobject, jobject klass) { | |
692 TRACE_graal_3("CompilerToVM::RiType_superType"); | |
693 VM_ENTRY_MARK; | |
694 KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); | |
695 klassOop k; | |
696 | |
697 if (klass_handle->oop_is_array()) { | |
698 k = SystemDictionary::Object_klass(); | |
699 } else { | |
700 guarantee(klass_handle->oop_is_instance(), "must be instance klass"); | |
701 k = klass_handle->super(); | |
702 } | |
703 | |
704 if (k != NULL) { | |
705 return JNIHandles::make_local(GraalCompiler::get_RiType(k, THREAD)()); | |
706 } else { | |
707 return NULL; | |
708 } | |
709 } | |
710 | |
711 // public RiType RiType_uniqueConcreteSubtype(HotSpotResolvedType klass); | |
712 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1uniqueConcreteSubtype(JNIEnv *, jobject, jobject klass) { | |
713 TRACE_graal_3("CompilerToVM::RiType_uniqueConcreteSubtype"); | |
714 VM_ENTRY_MARK; | |
715 KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); | |
716 Klass *up_cast = klass_handle->up_cast_abstract(); | |
717 if (up_cast->is_leaf_class()) { | |
718 return JNIHandles::make_local(GraalCompiler::get_RiType(up_cast, THREAD)()); | |
719 } | |
720 return NULL; | |
721 } | |
722 | |
723 // public bool RiType_isInitialized(HotSpotResolvedType klass); | |
724 JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1isInitialized(JNIEnv *, jobject, jobject hotspot_klass) { | |
725 TRACE_graal_3("CompilerToVM::RiType_isInitialized"); | |
726 klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(hotspot_klass)); | |
727 assert(klass != NULL, "method must not be called for primitive types"); | |
728 return instanceKlass::cast(klass)->is_initialized(); | |
729 } | |
730 | |
731 // public RiType RiType_arrayOf(HotSpotTypeResolved klass); | |
732 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1arrayOf(JNIEnv *, jobject, jobject klass) { | |
733 TRACE_graal_3("CompilerToVM::RiType_arrayOf"); | |
734 VM_ENTRY_MARK; | |
735 | |
736 KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); | |
737 KlassHandle arr = klass_handle->array_klass(THREAD); | |
738 Handle name = VmIds::toString<Handle>(arr->name(), CHECK_NULL); | |
739 assert(arr->oop_is_array(), ""); | |
740 return JNIHandles::make_local(THREAD, GraalCompiler::createHotSpotTypeResolved(arr, name, THREAD)()); | |
741 } | |
742 | |
743 // public RiResolvedField[] RiType_fields(HotSpotTypeResolved klass); | |
744 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1fields(JNIEnv *, jobject, jobject klass) { | |
745 TRACE_graal_3("CompilerToVM::RiType_fields"); | |
746 VM_ENTRY_MARK; | |
747 ResourceMark rm; | |
748 | |
749 instanceKlassHandle k = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); | |
750 class MyFieldClosure : public FieldClosure { | |
751 public: | |
752 instanceKlassHandle _holder; | |
753 Handle _resolved_type_holder; | |
754 GrowableArray<Handle> _field_array; | |
755 | |
756 MyFieldClosure(instanceKlassHandle& holder, Handle resolved_type_holder) : _holder(holder), _resolved_type_holder(resolved_type_holder) { } | |
757 | |
758 virtual void do_field(fieldDescriptor* fd) { | |
759 if (!Thread::current()->has_pending_exception()) { | |
760 if (fd->field_holder() == _holder()) { | |
761 Handle type = GraalCompiler::get_RiTypeFromSignature(fd->constants(), fd->signature_index(), fd->field_holder(), Thread::current()); | |
762 Handle field = VMToCompiler::createRiField(_resolved_type_holder, VmIds::toString<Handle>(fd->name(), Thread::current()), type, fd->offset(), fd->access_flags().as_int(), Thread::current()); | |
763 _field_array.append(field()); | |
764 } | |
765 } | |
766 } | |
767 }; | |
768 MyFieldClosure closure(k, JNIHandles::resolve(klass)); | |
769 k->do_nonstatic_fields(&closure); | |
770 objArrayHandle field_array = oopFactory::new_objArray(SystemDictionary::RiResolvedField_klass(), closure._field_array.length(), CHECK_NULL); | |
771 for (int i=0; i<closure._field_array.length(); ++i) { | |
772 field_array->obj_at_put(i, closure._field_array.at(i)()); | |
773 } | |
774 return JNIHandles::make_local(field_array()); | |
775 } | |
776 | |
777 // public RiType getPrimitiveArrayType(CiKind kind); | |
778 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getPrimitiveArrayType(JNIEnv *env, jobject, jobject kind) { | |
779 TRACE_graal_3("CompilerToVM::getPrimitiveArrayType"); | |
780 VM_ENTRY_MARK; | |
781 BasicType type = GraalCompiler::kindToBasicType(CiKind::typeChar(kind)); | |
782 assert(type != T_OBJECT, "primitive type expecteds"); | |
783 Handle result = GraalCompiler::get_RiType(Universe::typeArrayKlassObj(type), CHECK_NULL); | |
784 return JNIHandles::make_local(THREAD, result()); | |
785 } | |
786 | |
787 // public long getMaxCallTargetOffset(CiRuntimeCall rtcall); | |
788 JNIEXPORT jlong JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getMaxCallTargetOffset(JNIEnv *env, jobject, jobject rtcall) { | |
789 TRACE_graal_3("CompilerToVM::getMaxCallTargetOffset"); | |
790 VM_ENTRY_MARK; | |
791 oop call = JNIHandles::resolve(rtcall); | |
792 address target_addr = CodeInstaller::runtime_call_target_address(call); | |
793 if (target_addr != 0x0) { | |
794 int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int)); | |
795 int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int)); | |
796 return MAX2(ABS(off_low), ABS(off_high)); | |
797 } | |
798 return -1; | |
799 } | |
800 | |
801 // public RiType getType(Class<?> javaClass); | |
802 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getType(JNIEnv *env, jobject, jobject javaClass) { | |
803 TRACE_graal_3("CompilerToVM::getType"); | |
804 VM_ENTRY_MARK; | |
805 oop javaClassOop = JNIHandles::resolve(javaClass); | |
806 if (javaClassOop == NULL) { | |
807 fatal("argument to CompilerToVM.getType must not be NULL"); | |
808 return NULL; | |
809 } else if (java_lang_Class::is_primitive(javaClassOop)) { | |
810 BasicType basicType = java_lang_Class::primitive_type(javaClassOop); | |
811 return JNIHandles::make_local(THREAD, VMToCompiler::createRiTypePrimitive((int) basicType, THREAD)); | |
812 } else { | |
813 KlassHandle klass = java_lang_Class::as_klassOop(javaClassOop); | |
814 Handle name = java_lang_String::create_from_symbol(klass->name(), CHECK_NULL); | |
815 | |
816 Handle type = GraalCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL); | |
817 return JNIHandles::make_local(THREAD, type()); | |
818 } | |
819 } | |
820 | |
821 | |
822 // helpers used to set fields in the HotSpotVMConfig object | |
823 jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { | |
824 jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); | |
825 if (id == NULL) { | |
826 fatal(err_msg("field not found: %s (%s)", name, sig)); | |
827 } | |
828 return id; | |
829 } | |
830 | |
831 void set_boolean(JNIEnv* env, jobject obj, const char* name, bool value) { env->SetBooleanField(obj, getFieldID(env, obj, name, "Z"), value); } | |
832 void set_int(JNIEnv* env, jobject obj, const char* name, int value) { env->SetIntField(obj, getFieldID(env, obj, name, "I"), value); } | |
833 void set_long(JNIEnv* env, jobject obj, const char* name, jlong value) { env->SetLongField(obj, getFieldID(env, obj, name, "J"), value); } | |
834 void set_object(JNIEnv* env, jobject obj, const char* name, jobject value) { env->SetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;"), value); } | |
835 void set_int_array(JNIEnv* env, jobject obj, const char* name, jarray value) { env->SetObjectField(obj, getFieldID(env, obj, name, "[I"), value); } | |
836 | |
837 jboolean get_boolean(JNIEnv* env, jobject obj, const char* name) { return env->GetBooleanField(obj, getFieldID(env, obj, name, "Z")); } | |
838 jint get_int(JNIEnv* env, jobject obj, const char* name) { return env->GetIntField(obj, getFieldID(env, obj, name, "I")); } | |
839 jlong get_long(JNIEnv* env, jobject obj, const char* name) { return env->GetLongField(obj, getFieldID(env, obj, name, "J")); } | |
840 jobject get_object(JNIEnv* env, jobject obj, const char* name) { return env->GetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;")); } | |
841 jobject get_object(JNIEnv* env, jobject obj, const char* name, const char* sig) { return env->GetObjectField(obj, getFieldID(env, obj, name, sig)); } | |
842 | |
843 | |
844 BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; | |
845 int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); | |
846 | |
847 // public HotSpotVMConfig getConfiguration(); | |
848 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getConfiguration(JNIEnv *env, jobject) { | |
849 jclass klass = env->FindClass("com/oracle/max/graal/hotspot/HotSpotVMConfig"); | |
850 assert(klass != NULL, "HotSpot vm config class not found"); | |
851 jobject config = env->AllocObject(klass); | |
852 #ifdef _WIN64 | |
853 set_boolean(env, config, "windowsOs", true); | |
854 #else | |
855 set_boolean(env, config, "windowsOs", false); | |
856 #endif | |
857 set_boolean(env, config, "verifyPointers", VerifyOops); | |
858 set_boolean(env, config, "useFastLocking", UseFastLocking); | |
859 set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray); | |
860 set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray); | |
861 set_int(env, config, "codeEntryAlignment", CodeEntryAlignment); | |
862 set_int(env, config, "vmPageSize", os::vm_page_size()); | |
863 set_int(env, config, "stackShadowPages", StackShadowPages); | |
864 set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); | |
865 set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); | |
866 set_int(env, config, "klassStateOffset", instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)); | |
867 set_int(env, config, "klassStateFullyInitialized", (int)instanceKlass::fully_initialized); | |
868 set_int(env, config, "threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); | |
869 set_int(env, config, "threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); | |
870 set_int(env, config, "threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); | |
871 set_int(env, config, "instanceHeaderPrototypeOffset", Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); | |
872 set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); | |
873 set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); | |
874 set_int(env, config, "threadMultiNewArrayStorage", in_bytes(JavaThread::graal_multinewarray_storage_offset())); | |
875 set_int(env, config, "classMirrorOffset", klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes()); | |
876 | |
877 set_long(env, config, "debugStub", VmIds::addStub((address)warning)); | |
878 set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); | |
879 set_long(env, config, "verifyPointerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_pointer_id))); | |
880 set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::fast_new_instance_init_check_id))); | |
881 set_long(env, config, "unresolvedNewInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_instance_id))); | |
882 set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id))); | |
883 set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id))); | |
884 set_long(env, config, "newMultiArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_multi_array_id))); | |
885 set_long(env, config, "loadKlassStub", VmIds::addStub(Runtime1::entry_for(Runtime1::load_klass_patching_id))); | |
886 set_long(env, config, "accessFieldStub", VmIds::addStub(Runtime1::entry_for(Runtime1::access_field_patching_id))); | |
887 set_long(env, config, "resolveStaticCallStub", VmIds::addStub(SharedRuntime::get_resolve_static_call_stub())); | |
888 set_long(env, config, "inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); | |
889 set_long(env, config, "unwindExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id))); | |
890 set_long(env, config, "handleExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); | |
891 set_long(env, config, "handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); | |
892 set_long(env, config, "monitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorenter_id))); | |
893 set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorexit_id))); | |
894 set_long(env, config, "fastMonitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorenter_id))); | |
895 set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorexit_id))); | |
896 set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); | |
897 set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); | |
898 set_int(env, config, "klassModifierFlagsOffset", Klass::modifier_flags_offset_in_bytes() + sizeof(oopDesc)); | |
899 set_int(env, config, "klassOopOffset", java_lang_Class::klass_offset_in_bytes()); | |
900 set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far()); | |
901 | |
902 set_int(env, config, "nmethodEntryOffset", nmethod::verified_entry_point_offset()); | |
903 | |
904 BarrierSet* bs = Universe::heap()->barrier_set(); | |
905 switch (bs->kind()) { | |
906 case BarrierSet::CardTableModRef: | |
907 case BarrierSet::CardTableExtension: { | |
908 jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; | |
909 assert(base != 0, "unexpected byte_map_base"); | |
910 set_long(env, config, "cardtableStartAddress", base); | |
911 set_int(env, config, "cardtableShift", CardTableModRefBS::card_shift); | |
912 break; | |
913 } | |
914 case BarrierSet::ModRef: | |
915 case BarrierSet::Other: | |
916 set_long(env, config, "cardtableStartAddress", 0); | |
917 set_int(env, config, "cardtableShift", 0); | |
918 // No post barriers | |
919 break; | |
920 #ifndef SERIALGC | |
921 case BarrierSet::G1SATBCT: | |
922 case BarrierSet::G1SATBCTLogging: | |
923 #endif // SERIALGC | |
924 default: | |
925 ShouldNotReachHere(); | |
926 break; | |
927 } | |
928 | |
929 jintArray arrayOffsets = env->NewIntArray(basicTypeCount); | |
930 for (int i=0; i<basicTypeCount; i++) { | |
931 jint offset = arrayOopDesc::base_offset_in_bytes(basicTypes[i]); | |
932 env->SetIntArrayRegion(arrayOffsets, i, 1, &offset); | |
933 } | |
934 set_int_array(env, config, "arrayOffsets", arrayOffsets); | |
935 set_int(env, config, "arrayClassElementOffset", objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)); | |
936 return config; | |
937 } | |
938 | |
939 // public HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean installCode); | |
940 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod, jboolean install_code) { | |
941 VM_ENTRY_MARK; | |
942 ResourceMark rm; | |
943 HandleMark hm; | |
944 Handle targetMethodHandle = JNIHandles::resolve(targetMethod); | |
945 nmethod* nm = NULL; | |
946 Arena arena; | |
947 ciEnv env(&arena); | |
948 CodeInstaller installer(targetMethodHandle, nm, install_code != 0); | |
949 | |
950 // if install_code is true then we installed the code into the given method, no need to return an RiCompiledMethod | |
951 if (!install_code && nm != NULL) { | |
952 instanceKlass::cast(HotSpotCompiledMethod::klass())->initialize(CHECK_NULL); | |
953 Handle obj = instanceKlass::cast(HotSpotCompiledMethod::klass())->allocate_permanent_instance(CHECK_NULL); | |
954 assert(obj() != NULL, "must succeed in allocating instance"); | |
955 HotSpotCompiledMethod::set_nmethod(obj, (jlong) nm); | |
956 HotSpotCompiledMethod::set_method(obj, HotSpotTargetMethod::method(targetMethod)); | |
957 nm->set_graal_compiled_method(obj()); | |
958 return JNIHandles::make_local(obj()); | |
959 } else { | |
960 return NULL; | |
961 } | |
962 } | |
963 | |
964 // public long installStub(HotSpotTargetMethod targetMethod, String name); | |
965 JNIEXPORT jlong JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installStub(JNIEnv *jniEnv, jobject, jobject targetMethod) { | |
966 VM_ENTRY_MARK; | |
967 ResourceMark rm; | |
968 HandleMark hm; | |
969 Handle targetMethodHandle = JNIHandles::resolve(targetMethod); | |
970 jlong id; | |
971 Arena arena; | |
972 ciEnv env(&arena); | |
973 CodeInstaller installer(targetMethodHandle, id); | |
974 return id; | |
975 } | |
976 | |
977 | |
978 | |
979 #define CC (char*) /*cast a literal from (const char*)*/ | |
980 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_##f)) | |
981 | |
982 #define PROXY "J" | |
983 #define TYPE "Lcom/oracle/max/cri/ri/RiType;" | |
984 #define RESOLVED_TYPE "Lcom/oracle/max/graal/hotspot/ri/HotSpotTypeResolved;" | |
985 #define METHOD "Lcom/oracle/max/cri/ri/RiMethod;" | |
986 #define RESOLVED_METHOD "Lcom/oracle/max/graal/hotspot/ri/HotSpotMethodResolved;" | |
987 #define REFLECT_METHOD "Ljava/lang/reflect/Method;" | |
988 #define TYPE_PROFILE "Lcom/oracle/max/cri/ri/RiTypeProfile;" | |
989 #define SIGNATURE "Lcom/oracle/max/cri/ri/RiSignature;" | |
990 #define FIELD "Lcom/oracle/max/cri/ri/RiField;" | |
991 #define RESOLVED_FIELD "Lcom/oracle/max/cri/ri/RiResolvedField;" | |
992 #define CONSTANT_POOL "Lcom/oracle/max/cri/ri/RiConstantPool;" | |
993 #define EXCEPTION_HANDLERS "[Lcom/oracle/max/cri/ri/RiExceptionHandler;" | |
994 #define TARGET_METHOD "Lcom/oracle/max/graal/hotspot/HotSpotTargetMethod;" | |
995 #define CONFIG "Lcom/oracle/max/graal/hotspot/HotSpotVMConfig;" | |
996 #define HS_METHOD "Lcom/oracle/max/graal/hotspot/ri/HotSpotMethod;" | |
997 #define HS_COMP_METHOD "Lcom/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod;" | |
998 #define CI_CONSTANT "Lcom/oracle/max/cri/ci/CiConstant;" | |
999 #define CI_KIND "Lcom/oracle/max/cri/ci/CiKind;" | |
1000 #define CI_RUNTIME_CALL "Lcom/oracle/max/cri/ci/CiRuntimeCall;" | |
1001 #define STRING "Ljava/lang/String;" | |
1002 #define OBJECT "Ljava/lang/Object;" | |
1003 #define CLASS "Ljava/lang/Class;" | |
1004 | |
1005 JNINativeMethod CompilerToVM_methods[] = { | |
1006 {CC"RiMethod_code", CC"("RESOLVED_METHOD")[B", FN_PTR(RiMethod_1code)}, | |
1007 {CC"RiMethod_signature", CC"("RESOLVED_METHOD")"STRING, FN_PTR(RiMethod_1signature)}, | |
1008 {CC"RiMethod_exceptionHandlers", CC"("RESOLVED_METHOD")"EXCEPTION_HANDLERS, FN_PTR(RiMethod_1exceptionHandlers)}, | |
1009 {CC"RiMethod_hasBalancedMonitors", CC"("RESOLVED_METHOD")Z", FN_PTR(RiMethod_1hasBalancedMonitors)}, | |
1010 {CC"RiMethod_uniqueConcreteMethod", CC"("RESOLVED_METHOD")"METHOD, FN_PTR(RiMethod_1uniqueConcreteMethod)}, | |
1011 {CC"getRiMethod", CC"("REFLECT_METHOD")"METHOD, FN_PTR(getRiMethod)}, | |
1012 {CC"RiMethod_typeProfile", CC"("RESOLVED_METHOD"I)"TYPE_PROFILE, FN_PTR(RiMethod_2typeProfile)}, | |
1013 {CC"RiMethod_branchProbability", CC"("RESOLVED_METHOD"I)D", FN_PTR(RiMethod_2branchProbability)}, | |
1014 {CC"RiMethod_switchProbability", CC"("RESOLVED_METHOD"I)[D", FN_PTR(RiMethod_2switchProbability)}, | |
1015 {CC"RiMethod_invocationCount", CC"("RESOLVED_METHOD")I", FN_PTR(RiMethod_1invocationCount)}, | |
1016 {CC"RiMethod_exceptionProbability", CC"("RESOLVED_METHOD"I)I", FN_PTR(RiMethod_2exceptionProbability)}, | |
1017 {CC"RiMethod_hasCompiledCode", CC"("RESOLVED_METHOD")Z", FN_PTR(RiMethod_1hasCompiledCode)}, | |
1018 {CC"RiSignature_lookupType", CC"("STRING RESOLVED_TYPE")"TYPE, FN_PTR(RiSignature_1lookupType)}, | |
1019 {CC"RiConstantPool_lookupConstant", CC"("RESOLVED_TYPE"I)"OBJECT, FN_PTR(RiConstantPool_1lookupConstant)}, | |
1020 {CC"RiConstantPool_lookupMethod", CC"("RESOLVED_TYPE"IB)"METHOD, FN_PTR(RiConstantPool_1lookupMethod)}, | |
1021 {CC"RiConstantPool_lookupType", CC"("RESOLVED_TYPE"I)"TYPE, FN_PTR(RiConstantPool_1lookupType)}, | |
1022 {CC"RiConstantPool_loadReferencedType", CC"("RESOLVED_TYPE"IB)V", FN_PTR(RiConstantPool_1loadReferencedType)}, | |
1023 {CC"RiConstantPool_lookupField", CC"("RESOLVED_TYPE"IB)"FIELD, FN_PTR(RiConstantPool_1lookupField)}, | |
1024 {CC"RiType_resolveMethodImpl", CC"("RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(RiType_3resolveMethodImpl)}, | |
1025 {CC"RiType_isSubtypeOf", CC"("RESOLVED_TYPE TYPE")Z", FN_PTR(RiType_2isSubtypeOf)}, | |
1026 {CC"RiType_componentType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(RiType_1componentType)}, | |
1027 {CC"RiType_uniqueConcreteSubtype", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(RiType_1uniqueConcreteSubtype)}, | |
1028 {CC"RiType_superType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(RiType_1superType)}, | |
1029 {CC"RiType_arrayOf", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(RiType_1arrayOf)}, | |
1030 {CC"RiType_fields", CC"("RESOLVED_TYPE")["RESOLVED_FIELD, FN_PTR(RiType_1fields)}, | |
1031 {CC"RiType_isInitialized", CC"("RESOLVED_TYPE")Z", FN_PTR(RiType_1isInitialized)}, | |
1032 {CC"getPrimitiveArrayType", CC"("CI_KIND")"TYPE, FN_PTR(getPrimitiveArrayType)}, | |
1033 {CC"getMaxCallTargetOffset", CC"("CI_RUNTIME_CALL")J", FN_PTR(getMaxCallTargetOffset)}, | |
1034 {CC"getType", CC"("CLASS")"TYPE, FN_PTR(getType)}, | |
1035 {CC"getConfiguration", CC"()"CONFIG, FN_PTR(getConfiguration)}, | |
1036 {CC"installMethod", CC"("TARGET_METHOD"Z)"HS_COMP_METHOD, FN_PTR(installMethod)}, | |
1037 {CC"installStub", CC"("TARGET_METHOD")"PROXY, FN_PTR(installStub)} | |
1038 }; | |
1039 | |
1040 int CompilerToVM_methods_count() { | |
1041 return sizeof(CompilerToVM_methods) / sizeof(JNINativeMethod); | |
1042 } | |
1043 |