Mercurial > hg > truffle
comparison src/share/vm/jvmci/jvmciCodeInstaller.cpp @ 21559:be896a1983c0
recast all Graal native code as JVMCI code (JBS:GRAAL-53)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Thu, 28 May 2015 15:36:48 +0200 |
parents | src/share/vm/graal/graalCodeInstaller.cpp@1da7aef31a08 |
children | ce2113326bc8 |
comparison
equal
deleted
inserted
replaced
21558:d563baeca9df | 21559:be896a1983c0 |
---|---|
1 /* | |
2 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 | |
24 #include "precompiled.hpp" | |
25 #include "code/compiledIC.hpp" | |
26 #include "compiler/compileBroker.hpp" | |
27 #include "compiler/disassembler.hpp" | |
28 #include "runtime/javaCalls.hpp" | |
29 #include "jvmci/jvmciEnv.hpp" | |
30 #include "jvmci/jvmciCompiler.hpp" | |
31 #include "jvmci/jvmciCodeInstaller.hpp" | |
32 #include "jvmci/jvmciJavaAccess.hpp" | |
33 #include "jvmci/jvmciCompilerToVM.hpp" | |
34 #include "jvmci/jvmciRuntime.hpp" | |
35 #include "asm/register.hpp" | |
36 #include "classfile/vmSymbols.hpp" | |
37 #include "code/vmreg.hpp" | |
38 | |
39 #ifdef TARGET_ARCH_x86 | |
40 # include "vmreg_x86.inline.hpp" | |
41 #endif | |
42 #ifdef TARGET_ARCH_sparc | |
43 # include "vmreg_sparc.inline.hpp" | |
44 #endif | |
45 #ifdef TARGET_ARCH_zero | |
46 # include "vmreg_zero.inline.hpp" | |
47 #endif | |
48 #ifdef TARGET_ARCH_arm | |
49 # include "vmreg_arm.inline.hpp" | |
50 #endif | |
51 #ifdef TARGET_ARCH_ppc | |
52 # include "vmreg_ppc.inline.hpp" | |
53 #endif | |
54 | |
55 | |
56 // frequently used constants | |
57 // Allocate them with new so they are never destroyed (otherwise, a | |
58 // forced exit could destroy these objects while they are still in | |
59 // use). | |
60 ConstantOopWriteValue* CodeInstaller::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL); | |
61 ConstantIntValue* CodeInstaller::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1); | |
62 ConstantIntValue* CodeInstaller::_int_0_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(0); | |
63 ConstantIntValue* CodeInstaller::_int_1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1); | |
64 ConstantIntValue* CodeInstaller::_int_2_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2); | |
65 LocationValue* CodeInstaller::_illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location()); | |
66 | |
67 Method* getMethodFromHotSpotMethod(oop hotspot_method) { | |
68 assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass()), "sanity"); | |
69 return asMethod(HotSpotResolvedJavaMethodImpl::metaspaceMethod(hotspot_method)); | |
70 } | |
71 | |
72 const int MapWordBits = 64; | |
73 | |
74 static int entry_value(typeArrayOop words, int i) { | |
75 jint words_idx = i / MapWordBits; | |
76 assert(words_idx >= 0 && words_idx < words->length(), "unexpected index"); | |
77 jlong word = words->long_at(words_idx); | |
78 return (word >> (i % MapWordBits)) & 15LL; | |
79 } | |
80 | |
81 static int fixedmap_size(oop bitset) { | |
82 typeArrayOop arr = HotSpotOopMap::words(bitset); | |
83 return arr->length() * MapWordBits; | |
84 } | |
85 | |
86 static void set_vmreg_oops(OopMap* map, VMReg reg, typeArrayOop words, int idx) { | |
87 int value = entry_value(words, 4 * idx); | |
88 switch (value) { | |
89 case 10: | |
90 map->set_oop(reg); | |
91 break; | |
92 case 5: | |
93 map->set_narrowoop(reg); | |
94 map->set_narrowoop(reg->next()); | |
95 break; | |
96 case 1: | |
97 map->set_narrowoop(reg); | |
98 break; | |
99 case 4: | |
100 map->set_narrowoop(reg->next()); | |
101 break; | |
102 case 0: | |
103 break; | |
104 default: | |
105 assert(false, err_msg("unexpected bit pattern at %d = 0x%x", idx, value)); | |
106 ShouldNotReachHere(); | |
107 } | |
108 } | |
109 | |
110 // creates a HotSpot oop map out of the byte arrays provided by DebugInfo | |
111 static OopMap* create_oop_map(jint total_frame_size, jint parameter_count, oop debug_info) { | |
112 OopMap* map = new OopMap(total_frame_size, parameter_count); | |
113 oop reference_map = DebugInfo::referenceMap(debug_info); | |
114 oop register_map = HotSpotReferenceMap::registerRefMap(reference_map); | |
115 oop frame_map = HotSpotReferenceMap::frameRefMap(reference_map); | |
116 oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info); | |
117 | |
118 if (register_map != NULL) { | |
119 typeArrayOop words = HotSpotOopMap::words(register_map); | |
120 int mapIdx = 0; | |
121 for (jint i = 0; i < RegisterImpl::number_of_registers; i++) { | |
122 set_vmreg_oops(map, as_Register(i)->as_VMReg(), words, mapIdx); | |
123 mapIdx++; | |
124 } | |
125 #ifdef TARGET_ARCH_x86 | |
126 for (jint i = 0; i < XMMRegisterImpl::number_of_registers; i++) { | |
127 VMReg reg = as_XMMRegister(i)->as_VMReg(); | |
128 for (jint j = 0; j < 4; j++) { | |
129 set_vmreg_oops(map, reg->next(2 * j), words, mapIdx++); | |
130 } | |
131 } | |
132 #endif | |
133 #ifdef TARGET_ARCH_sparc | |
134 for (jint i = 0; i < FloatRegisterImpl::number_of_registers; i++) { | |
135 VMReg reg = as_FloatRegister(i)->as_VMReg(); | |
136 set_vmreg_oops(map, reg, words, mapIdx++); | |
137 } | |
138 #endif | |
139 } | |
140 | |
141 typeArrayOop words = HotSpotOopMap::words(frame_map); | |
142 int size = fixedmap_size(frame_map) / 4; | |
143 for (jint i = 0; i < size; i++) { | |
144 // HotSpot stack slots are 4 bytes | |
145 VMReg reg = VMRegImpl::stack2reg(i * VMRegImpl::slots_per_word); | |
146 set_vmreg_oops(map, reg, words, i); | |
147 } | |
148 | |
149 if (callee_save_info != NULL) { | |
150 objArrayOop registers = RegisterSaveLayout::registers(callee_save_info); | |
151 typeArrayOop slots = RegisterSaveLayout::slots(callee_save_info); | |
152 for (jint i = 0; i < slots->length(); i++) { | |
153 oop jvmci_reg = registers->obj_at(i); | |
154 jint jvmci_reg_number = code_Register::number(jvmci_reg); | |
155 VMReg hotspot_reg = CodeInstaller::get_hotspot_reg(jvmci_reg_number); | |
156 // HotSpot stack slots are 4 bytes | |
157 jint jvmci_slot = slots->int_at(i); | |
158 jint hotspot_slot = jvmci_slot * VMRegImpl::slots_per_word; | |
159 VMReg hotspot_slot_as_reg = VMRegImpl::stack2reg(hotspot_slot); | |
160 map->set_callee_saved(hotspot_slot_as_reg, hotspot_reg); | |
161 #ifdef _LP64 | |
162 // (copied from generate_oop_map() in c1_Runtime1_x86.cpp) | |
163 VMReg hotspot_slot_hi_as_reg = VMRegImpl::stack2reg(hotspot_slot + 1); | |
164 map->set_callee_saved(hotspot_slot_hi_as_reg, hotspot_reg->next()); | |
165 #endif | |
166 } | |
167 } | |
168 return map; | |
169 } | |
170 | |
171 static void record_metadata_reference(oop obj, jlong prim, jboolean compressed, OopRecorder* oop_recorder) { | |
172 if (obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) { | |
173 Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj)); | |
174 if (compressed) { | |
175 assert(Klass::decode_klass((narrowKlass) prim) == klass, err_msg("%s @ " INTPTR_FORMAT " != " PTR64_FORMAT, klass->name()->as_C_string(), p2i(klass), prim)); | |
176 } else { | |
177 assert((Klass*) prim == klass, err_msg("%s @ " INTPTR_FORMAT " != " PTR64_FORMAT, klass->name()->as_C_string(), p2i(klass), prim)); | |
178 } | |
179 int index = oop_recorder->find_index(klass); | |
180 TRACE_jvmci_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string()); | |
181 } else if (obj->is_a(HotSpotResolvedJavaMethodImpl::klass())) { | |
182 Method* method = (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(obj); | |
183 assert(!compressed, err_msg("unexpected compressed method pointer %s @ " INTPTR_FORMAT " = " PTR64_FORMAT, method->name()->as_C_string(), p2i(method), prim)); | |
184 int index = oop_recorder->find_index(method); | |
185 TRACE_jvmci_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string()); | |
186 } else { | |
187 assert(java_lang_String::is_instance(obj), | |
188 err_msg("unexpected metadata reference (%s) for constant " JLONG_FORMAT " (" PTR64_FORMAT ")", obj->klass()->name()->as_C_string(), prim, prim)); | |
189 } | |
190 } | |
191 | |
192 // Records any Metadata values embedded in a Constant (e.g., the value returned by HotSpotResolvedObjectTypeImpl.klass()). | |
193 static void record_metadata_in_constant(oop constant, OopRecorder* oop_recorder) { | |
194 if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) { | |
195 oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant); | |
196 jlong prim = HotSpotMetaspaceConstantImpl::primitive(constant); | |
197 assert(Kind::typeChar(AbstractValue::kind(constant)) == 'j', "must have word kind"); | |
198 assert(obj != NULL, "must have an object"); | |
199 assert(prim != 0, "must have a primitive value"); | |
200 | |
201 record_metadata_reference(obj, prim, false, oop_recorder); | |
202 } | |
203 } | |
204 | |
205 static void record_metadata_in_patch(Handle& constant, OopRecorder* oop_recorder) { | |
206 record_metadata_reference(HotSpotMetaspaceConstantImpl::metaspaceObject(constant), HotSpotMetaspaceConstantImpl::primitive(constant), HotSpotMetaspaceConstantImpl::compressed(constant), oop_recorder); | |
207 } | |
208 | |
209 ScopeValue* CodeInstaller::get_scope_value(oop value, GrowableArray<ScopeValue*>* objects, ScopeValue* &second) { | |
210 second = NULL; | |
211 if (value == AbstractValue::ILLEGAL()) { | |
212 return _illegal_value; | |
213 } | |
214 | |
215 oop lirKind = AbstractValue::lirKind(value); | |
216 oop platformKind = LIRKind::platformKind(lirKind); | |
217 jint referenceMask = LIRKind::referenceMask(lirKind); | |
218 assert(referenceMask != -1, "derived pointers are not allowed"); | |
219 assert(referenceMask == 0 || referenceMask == 1, "unexpected referenceMask"); | |
220 bool reference = referenceMask == 1; | |
221 | |
222 BasicType type = JVMCIRuntime::kindToBasicType(Kind::typeChar(platformKind)); | |
223 | |
224 if (value->is_a(RegisterValue::klass())) { | |
225 oop reg = RegisterValue::reg(value); | |
226 jint number = code_Register::number(reg); | |
227 VMReg hotspotRegister = get_hotspot_reg(number); | |
228 if (is_general_purpose_reg(hotspotRegister)) { | |
229 Location::Type locationType; | |
230 if (type == T_INT) { | |
231 locationType = reference ? Location::narrowoop : Location::int_in_long; | |
232 } else if(type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN) { | |
233 locationType = Location::int_in_long; | |
234 } else if (type == T_FLOAT) { | |
235 locationType = Location::int_in_long; | |
236 } else if (type == T_LONG) { | |
237 locationType = reference ? Location::oop : Location::lng; | |
238 } else { | |
239 assert(type == T_OBJECT && reference, "unexpected type in cpu register"); | |
240 locationType = Location::oop; | |
241 } | |
242 ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, hotspotRegister)); | |
243 if (type == T_LONG && !reference) { | |
244 second = value; | |
245 } | |
246 return value; | |
247 } else { | |
248 assert(type == T_FLOAT || type == T_DOUBLE, "only float and double expected in xmm register"); | |
249 Location::Type locationType; | |
250 if (type == T_FLOAT) { | |
251 // this seems weird, but the same value is used in c1_LinearScan | |
252 locationType = Location::normal; | |
253 } else { | |
254 locationType = Location::dbl; | |
255 } | |
256 assert(!reference, "unexpected type in floating point register"); | |
257 ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, hotspotRegister)); | |
258 if (type == T_DOUBLE) { | |
259 second = value; | |
260 } | |
261 return value; | |
262 } | |
263 } else if (value->is_a(StackSlot::klass())) { | |
264 Location::Type locationType; | |
265 if (type == T_LONG) { | |
266 locationType = reference ? Location::oop : Location::lng; | |
267 } else if (type == T_INT) { | |
268 locationType = reference ? Location::narrowoop : Location::normal; | |
269 } else if(type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN) { | |
270 locationType = Location::normal; | |
271 } else if (type == T_FLOAT) { | |
272 assert(!reference, "unexpected type in stack slot"); | |
273 locationType = Location::normal; | |
274 } else if (type == T_DOUBLE) { | |
275 assert(!reference, "unexpected type in stack slot"); | |
276 locationType = Location::dbl; | |
277 } else { | |
278 assert(type == T_OBJECT && reference, "unexpected type in stack slot"); | |
279 locationType = Location::oop; | |
280 } | |
281 jint offset = StackSlot::offset(value); | |
282 #ifdef TARGET_ARCH_sparc | |
283 if(offset >= 0) { | |
284 offset += 128; | |
285 } | |
286 #endif | |
287 if (StackSlot::addFrameSize(value)) { | |
288 offset += _total_frame_size; | |
289 } | |
290 ScopeValue* value = new LocationValue(Location::new_stk_loc(locationType, offset)); | |
291 if (type == T_DOUBLE || (type == T_LONG && !reference)) { | |
292 second = value; | |
293 } | |
294 return value; | |
295 } else if (value->is_a(JavaConstant::klass())){ | |
296 record_metadata_in_constant(value, _oop_recorder); | |
297 if (value->is_a(PrimitiveConstant::klass())) { | |
298 assert(!reference, "unexpected primitive constant type"); | |
299 if(value->is_a(RawConstant::klass())) { | |
300 jlong prim = PrimitiveConstant::primitive(value); | |
301 return new ConstantLongValue(prim); | |
302 } else if (type == T_INT || type == T_FLOAT) { | |
303 jint prim = (jint)PrimitiveConstant::primitive(value); | |
304 switch (prim) { | |
305 case -1: return _int_m1_scope_value; | |
306 case 0: return _int_0_scope_value; | |
307 case 1: return _int_1_scope_value; | |
308 case 2: return _int_2_scope_value; | |
309 default: return new ConstantIntValue(prim); | |
310 } | |
311 } else { | |
312 assert(type == T_LONG || type == T_DOUBLE, "unexpected primitive constant type"); | |
313 jlong prim = PrimitiveConstant::primitive(value); | |
314 second = _int_1_scope_value; | |
315 return new ConstantLongValue(prim); | |
316 } | |
317 } else { | |
318 assert(reference, "unexpected object constant type"); | |
319 if (value->is_a(NullConstant::klass()) || value->is_a(HotSpotCompressedNullConstant::klass())) { | |
320 return _oop_null_scope_value; | |
321 } else { | |
322 assert(value->is_a(HotSpotObjectConstantImpl::klass()), "unexpected constant type"); | |
323 oop obj = HotSpotObjectConstantImpl::object(value); | |
324 assert(obj != NULL, "null value must be in NullConstant"); | |
325 return new ConstantOopWriteValue(JNIHandles::make_local(obj)); | |
326 } | |
327 } | |
328 } else if (value->is_a(VirtualObject::klass())) { | |
329 int id = VirtualObject::id(value); | |
330 ScopeValue* object = objects->at(id); | |
331 assert(object != NULL, "missing value"); | |
332 return object; | |
333 } else { | |
334 value->klass()->print(); | |
335 value->print(); | |
336 } | |
337 ShouldNotReachHere(); | |
338 return NULL; | |
339 } | |
340 | |
341 void CodeInstaller::record_object_value(ObjectValue* sv, oop value, GrowableArray<ScopeValue*>* objects) { | |
342 oop type = VirtualObject::type(value); | |
343 int id = VirtualObject::id(value); | |
344 oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); | |
345 Klass* klass = java_lang_Class::as_Klass(javaMirror); | |
346 bool isLongArray = klass == Universe::longArrayKlassObj(); | |
347 | |
348 objArrayOop values = VirtualObject::values(value); | |
349 for (jint i = 0; i < values->length(); i++) { | |
350 ScopeValue* cur_second = NULL; | |
351 oop object = values->obj_at(i); | |
352 ScopeValue* value = get_scope_value(object, objects, cur_second); | |
353 | |
354 if (isLongArray && cur_second == NULL) { | |
355 // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations. | |
356 // add an int 0 constant | |
357 cur_second = _int_0_scope_value; | |
358 } | |
359 | |
360 if (cur_second != NULL) { | |
361 sv->field_values()->append(cur_second); | |
362 } | |
363 assert(value != NULL, "missing value"); | |
364 sv->field_values()->append(value); | |
365 } | |
366 } | |
367 | |
368 MonitorValue* CodeInstaller::get_monitor_value(oop value, GrowableArray<ScopeValue*>* objects) { | |
369 guarantee(value->is_a(StackLockValue::klass()), "Monitors must be of type MonitorValue"); | |
370 | |
371 ScopeValue* second = NULL; | |
372 ScopeValue* owner_value = get_scope_value(StackLockValue::owner(value), objects, second); | |
373 assert(second == NULL, "monitor cannot occupy two stack slots"); | |
374 | |
375 ScopeValue* lock_data_value = get_scope_value(StackLockValue::slot(value), objects, second); | |
376 assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots"); | |
377 assert(lock_data_value->is_location(), "invalid monitor location"); | |
378 Location lock_data_loc = ((LocationValue*)lock_data_value)->location(); | |
379 | |
380 bool eliminated = false; | |
381 if (StackLockValue::eliminated(value)) { | |
382 eliminated = true; | |
383 } | |
384 | |
385 return new MonitorValue(owner_value, lock_data_loc, eliminated); | |
386 } | |
387 | |
388 void CodeInstaller::initialize_dependencies(oop compiled_code) { | |
389 JavaThread* thread = JavaThread::current(); | |
390 CompilerThread* compilerThread = thread->is_Compiler_thread() ? thread->as_CompilerThread() : NULL; | |
391 _oop_recorder = new OopRecorder(&_arena, true); | |
392 _dependencies = new Dependencies(&_arena, _oop_recorder, compilerThread != NULL ? compilerThread->log() : NULL); | |
393 objArrayHandle assumptions = CompilationResult::assumptions(HotSpotCompiledCode::comp(compiled_code)); | |
394 if (!assumptions.is_null()) { | |
395 int length = assumptions->length(); | |
396 for (int i = 0; i < length; ++i) { | |
397 Handle assumption = assumptions->obj_at(i); | |
398 if (!assumption.is_null()) { | |
399 if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) { | |
400 assumption_NoFinalizableSubclass(assumption); | |
401 } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) { | |
402 assumption_ConcreteSubtype(assumption); | |
403 } else if (assumption->klass() == Assumptions_LeafType::klass()) { | |
404 assumption_LeafType(assumption); | |
405 } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) { | |
406 assumption_ConcreteMethod(assumption); | |
407 } else if (assumption->klass() == Assumptions_CallSiteTargetValue::klass()) { | |
408 assumption_CallSiteTargetValue(assumption); | |
409 } else { | |
410 assumption->print(); | |
411 fatal("unexpected Assumption subclass"); | |
412 } | |
413 } | |
414 } | |
415 } | |
416 objArrayHandle methods = CompilationResult::methods(HotSpotCompiledCode::comp(compiled_code)); | |
417 if (!methods.is_null()) { | |
418 int length = methods->length(); | |
419 for (int i = 0; i < length; ++i) { | |
420 Handle method_handle = methods->obj_at(i); | |
421 methodHandle method = getMethodFromHotSpotMethod(method_handle()); | |
422 _dependencies->assert_evol_method(method()); | |
423 } | |
424 } | |
425 } | |
426 | |
427 // constructor used to create a method | |
428 JVMCIEnv::CodeInstallResult CodeInstaller::install(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log) { | |
429 BufferBlob* buffer_blob = JVMCIRuntime::initialize_buffer_blob(); | |
430 if (buffer_blob == NULL) { | |
431 return JVMCIEnv::cache_full; | |
432 } | |
433 | |
434 CodeBuffer buffer(buffer_blob); | |
435 jobject compiled_code_obj = JNIHandles::make_local(compiled_code()); | |
436 initialize_dependencies(JNIHandles::resolve(compiled_code_obj)); | |
437 | |
438 // Get instructions and constants CodeSections early because we need it. | |
439 _instructions = buffer.insts(); | |
440 _constants = buffer.consts(); | |
441 | |
442 { | |
443 initialize_fields(JNIHandles::resolve(compiled_code_obj)); | |
444 if (!initialize_buffer(buffer)) { | |
445 return JVMCIEnv::code_too_large; | |
446 } | |
447 process_exception_handlers(); | |
448 } | |
449 | |
450 int stack_slots = _total_frame_size / HeapWordSize; // conversion to words | |
451 | |
452 JVMCIEnv::CodeInstallResult result; | |
453 if (!compiled_code->is_a(HotSpotCompiledNmethod::klass())) { | |
454 oop stubName = CompilationResult::name(HotSpotCompiledCode::comp(compiled_code_obj)); | |
455 char* name = strdup(java_lang_String::as_utf8_string(stubName)); | |
456 cb = RuntimeStub::new_runtime_stub(name, | |
457 &buffer, | |
458 CodeOffsets::frame_never_safe, | |
459 stack_slots, | |
460 _debug_recorder->_oopmaps, | |
461 false); | |
462 result = JVMCIEnv::ok; | |
463 } else { | |
464 nmethod* nm = NULL; | |
465 methodHandle method = getMethodFromHotSpotMethod(HotSpotCompiledNmethod::method(compiled_code)); | |
466 jint entry_bci = HotSpotCompiledNmethod::entryBCI(compiled_code); | |
467 jint id = HotSpotCompiledNmethod::id(compiled_code); | |
468 JVMCIEnv* env = (JVMCIEnv*) (address) HotSpotCompiledNmethod::jvmciEnv(compiled_code); | |
469 if (id == -1) { | |
470 // Make sure a valid compile_id is associated with every compile | |
471 id = CompileBroker::assign_compile_id_unlocked(Thread::current(), method, entry_bci); | |
472 } | |
473 result = JVMCIEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, | |
474 JVMCICompiler::instance(), _debug_recorder, _dependencies, env, id, false, installed_code, compiled_code, speculation_log); | |
475 cb = nm; | |
476 } | |
477 | |
478 if (cb != NULL) { | |
479 // Make sure the pre-calculated constants section size was correct. | |
480 guarantee((cb->code_begin() - cb->content_begin()) >= _constants_size, err_msg("%d < %d", (int)(cb->code_begin() - cb->content_begin()), _constants_size)); | |
481 } | |
482 return result; | |
483 } | |
484 | |
485 void CodeInstaller::initialize_fields(oop compiled_code) { | |
486 Handle comp_result = HotSpotCompiledCode::comp(compiled_code); | |
487 if (compiled_code->is_a(HotSpotCompiledNmethod::klass())) { | |
488 Handle hotspotJavaMethod = HotSpotCompiledNmethod::method(compiled_code); | |
489 methodHandle method = getMethodFromHotSpotMethod(hotspotJavaMethod()); | |
490 _parameter_count = method->size_of_parameters(); | |
491 TRACE_jvmci_1("installing code for %s", method->name_and_sig_as_C_string()); | |
492 } else { | |
493 // Must be a HotSpotCompiledRuntimeStub | |
494 // TODO (ds) not sure if this is correct - only used in OopMap constructor for non-product builds | |
495 _parameter_count = 0; | |
496 } | |
497 _sites_handle = JNIHandles::make_local(HotSpotCompiledCode::sites(compiled_code)); | |
498 _exception_handlers_handle = JNIHandles::make_local(HotSpotCompiledCode::exceptionHandlers(compiled_code)); | |
499 | |
500 _code_handle = JNIHandles::make_local(CompilationResult::targetCode(comp_result)); | |
501 _code_size = CompilationResult::targetCodeSize(comp_result); | |
502 _total_frame_size = CompilationResult::totalFrameSize(comp_result); | |
503 _custom_stack_area_offset = CompilationResult::customStackAreaOffset(comp_result); | |
504 | |
505 // Pre-calculate the constants section size. This is required for PC-relative addressing. | |
506 _data_section_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSection(compiled_code)); | |
507 guarantee(HotSpotCompiledCode::dataSectionAlignment(compiled_code) <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin"); | |
508 _constants_size = data_section()->length(); | |
509 | |
510 _data_section_patches_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSectionPatches(compiled_code)); | |
511 | |
512 #ifndef PRODUCT | |
513 _comments_handle = JNIHandles::make_local(HotSpotCompiledCode::comments(compiled_code)); | |
514 #endif | |
515 | |
516 _next_call_type = INVOKE_INVALID; | |
517 } | |
518 | |
519 int CodeInstaller::estimate_stub_entries() { | |
520 // Estimate the number of static call stubs that might be emitted. | |
521 int static_call_stubs = 0; | |
522 objArrayOop sites = this->sites(); | |
523 for (int i = 0; i < sites->length(); i++) { | |
524 oop site = sites->obj_at(i); | |
525 if (site->is_a(CompilationResult_Mark::klass())) { | |
526 oop id_obj = CompilationResult_Mark::id(site); | |
527 if (id_obj != NULL) { | |
528 assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected"); | |
529 jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT)); | |
530 if (id == INVOKESTATIC || id == INVOKESPECIAL) { | |
531 static_call_stubs++; | |
532 } | |
533 } | |
534 } | |
535 } | |
536 return static_call_stubs; | |
537 } | |
538 | |
539 // perform data and call relocation on the CodeBuffer | |
540 bool CodeInstaller::initialize_buffer(CodeBuffer& buffer) { | |
541 HandleMark hm; | |
542 objArrayHandle sites = this->sites(); | |
543 int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo)); | |
544 char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size); | |
545 buffer.insts()->initialize_shared_locs((relocInfo*)locs_buffer, locs_buffer_size / sizeof(relocInfo)); | |
546 // Allocate enough space in the stub section for the static call | |
547 // stubs. Stubs have extra relocs but they are managed by the stub | |
548 // section itself so they don't need to be accounted for in the | |
549 // locs_buffer above. | |
550 buffer.initialize_stubs_size(estimate_stub_entries() * CompiledStaticCall::to_interp_stub_size()); | |
551 buffer.initialize_consts_size(_constants_size); | |
552 | |
553 _debug_recorder = new DebugInformationRecorder(_oop_recorder); | |
554 _debug_recorder->set_oopmaps(new OopMapSet()); | |
555 | |
556 buffer.initialize_oop_recorder(_oop_recorder); | |
557 | |
558 // copy the constant data into the newly created CodeBuffer | |
559 address end_data = _constants->start() + _constants_size; | |
560 memcpy(_constants->start(), data_section()->base(T_BYTE), _constants_size); | |
561 _constants->set_end(end_data); | |
562 | |
563 // copy the code into the newly created CodeBuffer | |
564 address end_pc = _instructions->start() + _code_size; | |
565 if (!_instructions->allocates2(end_pc)) { | |
566 return false; | |
567 } | |
568 memcpy(_instructions->start(), code()->base(T_BYTE), _code_size); | |
569 _instructions->set_end(end_pc); | |
570 | |
571 for (int i = 0; i < data_section_patches()->length(); i++) { | |
572 Handle patch = data_section_patches()->obj_at(i); | |
573 Handle reference = CompilationResult_DataPatch::reference(patch); | |
574 assert(reference->is_a(CompilationResult_ConstantReference::klass()), err_msg("patch in data section must be a ConstantReference")); | |
575 Handle constant = CompilationResult_ConstantReference::constant(reference); | |
576 if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) { | |
577 record_metadata_in_patch(constant, _oop_recorder); | |
578 } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) { | |
579 Handle obj = HotSpotObjectConstantImpl::object(constant); | |
580 jobject value = JNIHandles::make_local(obj()); | |
581 int oop_index = _oop_recorder->find_index(value); | |
582 | |
583 address dest = _constants->start() + CompilationResult_Site::pcOffset(patch); | |
584 if (HotSpotObjectConstantImpl::compressed(constant)) { | |
585 #ifdef _LP64 | |
586 _constants->relocate(dest, oop_Relocation::spec(oop_index), relocInfo::narrow_oop_in_const); | |
587 #else | |
588 fatal("unexpected compressed oop in 32-bit mode"); | |
589 #endif | |
590 } else { | |
591 _constants->relocate(dest, oop_Relocation::spec(oop_index)); | |
592 } | |
593 } else { | |
594 ShouldNotReachHere(); | |
595 } | |
596 } | |
597 jint last_pc_offset = -1; | |
598 for (int i = 0; i < sites->length(); i++) { | |
599 { | |
600 No_Safepoint_Verifier no_safepoint; | |
601 oop site = sites->obj_at(i); | |
602 jint pc_offset = CompilationResult_Site::pcOffset(site); | |
603 | |
604 if (site->is_a(CompilationResult_Call::klass())) { | |
605 TRACE_jvmci_4("call at %i", pc_offset); | |
606 site_Call(buffer, pc_offset, site); | |
607 } else if (site->is_a(CompilationResult_Infopoint::klass())) { | |
608 // three reasons for infopoints denote actual safepoints | |
609 oop reason = CompilationResult_Infopoint::reason(site); | |
610 if (InfopointReason::SAFEPOINT() == reason || InfopointReason::CALL() == reason || InfopointReason::IMPLICIT_EXCEPTION() == reason) { | |
611 TRACE_jvmci_4("safepoint at %i", pc_offset); | |
612 site_Safepoint(buffer, pc_offset, site); | |
613 } else { | |
614 // if the infopoint is not an actual safepoint, it must have one of the other reasons | |
615 // (safeguard against new safepoint types that require handling above) | |
616 assert(InfopointReason::METHOD_START() == reason || InfopointReason::METHOD_END() == reason || InfopointReason::LINE_NUMBER() == reason, ""); | |
617 site_Infopoint(buffer, pc_offset, site); | |
618 } | |
619 } else if (site->is_a(CompilationResult_DataPatch::klass())) { | |
620 TRACE_jvmci_4("datapatch at %i", pc_offset); | |
621 site_DataPatch(buffer, pc_offset, site); | |
622 } else if (site->is_a(CompilationResult_Mark::klass())) { | |
623 TRACE_jvmci_4("mark at %i", pc_offset); | |
624 site_Mark(buffer, pc_offset, site); | |
625 } else { | |
626 fatal("unexpected Site subclass"); | |
627 } | |
628 last_pc_offset = pc_offset; | |
629 } | |
630 if (CodeInstallSafepointChecks && SafepointSynchronize::do_call_back()) { | |
631 // this is a hacky way to force a safepoint check but nothing else was jumping out at me. | |
632 ThreadToNativeFromVM ttnfv(JavaThread::current()); | |
633 } | |
634 } | |
635 | |
636 #ifndef PRODUCT | |
637 if (comments() != NULL) { | |
638 No_Safepoint_Verifier no_safepoint; | |
639 for (int i = 0; i < comments()->length(); i++) { | |
640 oop comment = comments()->obj_at(i); | |
641 assert(comment->is_a(HotSpotCompiledCode_Comment::klass()), "cce"); | |
642 jint offset = HotSpotCompiledCode_Comment::pcOffset(comment); | |
643 char* text = java_lang_String::as_utf8_string(HotSpotCompiledCode_Comment::text(comment)); | |
644 buffer.block_comment(offset, text); | |
645 } | |
646 } | |
647 #endif | |
648 return true; | |
649 } | |
650 | |
651 void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) { | |
652 Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption()); | |
653 Klass* receiverType = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(receiverType_handle)); | |
654 _dependencies->assert_has_no_finalizable_subclasses(receiverType); | |
655 } | |
656 | |
657 void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) { | |
658 Handle context_handle = Assumptions_ConcreteSubtype::context(assumption()); | |
659 Handle subtype_handle = Assumptions_ConcreteSubtype::subtype(assumption()); | |
660 Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle)); | |
661 Klass* subtype = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(subtype_handle)); | |
662 | |
663 assert(context->is_abstract(), ""); | |
664 _dependencies->assert_abstract_with_unique_concrete_subtype(context, subtype); | |
665 } | |
666 | |
667 void CodeInstaller::assumption_LeafType(Handle assumption) { | |
668 Handle context_handle = Assumptions_LeafType::context(assumption()); | |
669 Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle)); | |
670 | |
671 _dependencies->assert_leaf_type(context); | |
672 } | |
673 | |
674 void CodeInstaller::assumption_ConcreteMethod(Handle assumption) { | |
675 Handle impl_handle = Assumptions_ConcreteMethod::impl(assumption()); | |
676 Handle context_handle = Assumptions_ConcreteMethod::context(assumption()); | |
677 | |
678 methodHandle impl = getMethodFromHotSpotMethod(impl_handle()); | |
679 Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle)); | |
680 | |
681 _dependencies->assert_unique_concrete_method(context, impl()); | |
682 } | |
683 | |
684 void CodeInstaller::assumption_CallSiteTargetValue(Handle assumption) { | |
685 Handle callSite = Assumptions_CallSiteTargetValue::callSite(assumption()); | |
686 Handle methodHandle = Assumptions_CallSiteTargetValue::methodHandle(assumption()); | |
687 | |
688 _dependencies->assert_call_site_target_value(callSite(), methodHandle()); | |
689 } | |
690 | |
691 void CodeInstaller::process_exception_handlers() { | |
692 if (exception_handlers() != NULL) { | |
693 objArrayOop handlers = exception_handlers(); | |
694 for (int i = 0; i < handlers->length(); i++) { | |
695 oop exc = handlers->obj_at(i); | |
696 jint pc_offset = CompilationResult_Site::pcOffset(exc); | |
697 jint handler_offset = CompilationResult_ExceptionHandler::handlerPos(exc); | |
698 | |
699 // Subtable header | |
700 _exception_handler_table.add_entry(HandlerTableEntry(1, pc_offset, 0)); | |
701 | |
702 // Subtable entry | |
703 _exception_handler_table.add_entry(HandlerTableEntry(-1, handler_offset, 0)); | |
704 } | |
705 } | |
706 } | |
707 | |
708 // If deoptimization happens, the interpreter should reexecute these bytecodes. | |
709 // This function mainly helps the compilers to set up the reexecute bit. | |
710 static bool bytecode_should_reexecute(Bytecodes::Code code) { | |
711 switch (code) { | |
712 case Bytecodes::_invokedynamic: | |
713 case Bytecodes::_invokevirtual: | |
714 case Bytecodes::_invokeinterface: | |
715 case Bytecodes::_invokespecial: | |
716 case Bytecodes::_invokestatic: | |
717 return false; | |
718 default: | |
719 return true; | |
720 } | |
721 return true; | |
722 } | |
723 | |
724 GrowableArray<ScopeValue*>* CodeInstaller::record_virtual_objects(oop debug_info) { | |
725 objArrayOop virtualObjects = DebugInfo::virtualObjectMapping(debug_info); | |
726 if (virtualObjects == NULL) { | |
727 return NULL; | |
728 } | |
729 GrowableArray<ScopeValue*>* objects = new GrowableArray<ScopeValue*>(virtualObjects->length(), virtualObjects->length(), NULL); | |
730 // Create the unique ObjectValues | |
731 for (int i = 0; i < virtualObjects->length(); i++) { | |
732 oop value = virtualObjects->obj_at(i); | |
733 int id = VirtualObject::id(value); | |
734 oop type = VirtualObject::type(value); | |
735 oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); | |
736 ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror))); | |
737 assert(objects->at(id) == NULL, "once"); | |
738 objects->at_put(id, sv); | |
739 } | |
740 // All the values which could be referenced by the VirtualObjects | |
741 // exist, so now describe all the VirtualObjects themselves. | |
742 for (int i = 0; i < virtualObjects->length(); i++) { | |
743 oop value = virtualObjects->obj_at(i); | |
744 int id = VirtualObject::id(value); | |
745 record_object_value(objects->at(id)->as_ObjectValue(), value, objects); | |
746 } | |
747 _debug_recorder->dump_object_pool(objects); | |
748 return objects; | |
749 } | |
750 | |
751 void CodeInstaller::record_scope(jint pc_offset, oop debug_info) { | |
752 oop position = DebugInfo::bytecodePosition(debug_info); | |
753 if (position == NULL) { | |
754 // Stubs do not record scope info, just oop maps | |
755 return; | |
756 } | |
757 | |
758 GrowableArray<ScopeValue*>* objectMapping = record_virtual_objects(debug_info); | |
759 record_scope(pc_offset, position, objectMapping); | |
760 } | |
761 | |
762 void CodeInstaller::record_scope(jint pc_offset, oop position, GrowableArray<ScopeValue*>* objects) { | |
763 oop frame = NULL; | |
764 if (position->is_a(BytecodeFrame::klass())) { | |
765 frame = position; | |
766 } | |
767 oop caller_frame = BytecodePosition::caller(position); | |
768 if (caller_frame != NULL) { | |
769 record_scope(pc_offset, caller_frame, objects); | |
770 } | |
771 | |
772 oop hotspot_method = BytecodePosition::method(position); | |
773 Method* method = getMethodFromHotSpotMethod(hotspot_method); | |
774 jint bci = BytecodePosition::bci(position); | |
775 if (bci == BytecodeFrame::BEFORE_BCI()) { | |
776 bci = SynchronizationEntryBCI; | |
777 } | |
778 | |
779 if (TraceJVMCI >= 2) { | |
780 tty->print_cr("Recording scope pc_offset=%d bci=%d method=%s", pc_offset, bci, method->name_and_sig_as_C_string()); | |
781 } | |
782 | |
783 bool reexecute = false; | |
784 if (frame != NULL) { | |
785 if (bci == SynchronizationEntryBCI){ | |
786 reexecute = false; | |
787 } else { | |
788 Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci)); | |
789 reexecute = bytecode_should_reexecute(code); | |
790 if (frame != NULL) { | |
791 reexecute = (BytecodeFrame::duringCall(frame) == JNI_FALSE); | |
792 } | |
793 } | |
794 } | |
795 | |
796 DebugToken* locals_token = NULL; | |
797 DebugToken* expressions_token = NULL; | |
798 DebugToken* monitors_token = NULL; | |
799 bool throw_exception = false; | |
800 | |
801 if (frame != NULL) { | |
802 jint local_count = BytecodeFrame::numLocals(frame); | |
803 jint expression_count = BytecodeFrame::numStack(frame); | |
804 jint monitor_count = BytecodeFrame::numLocks(frame); | |
805 objArrayOop values = BytecodeFrame::values(frame); | |
806 | |
807 assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length"); | |
808 | |
809 GrowableArray<ScopeValue*>* locals = local_count > 0 ? new GrowableArray<ScopeValue*> (local_count) : NULL; | |
810 GrowableArray<ScopeValue*>* expressions = expression_count > 0 ? new GrowableArray<ScopeValue*> (expression_count) : NULL; | |
811 GrowableArray<MonitorValue*>* monitors = monitor_count > 0 ? new GrowableArray<MonitorValue*> (monitor_count) : NULL; | |
812 | |
813 if (TraceJVMCI >= 2) { | |
814 tty->print_cr("Scope at bci %d with %d values", bci, values->length()); | |
815 tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); | |
816 } | |
817 | |
818 for (jint i = 0; i < values->length(); i++) { | |
819 ScopeValue* second = NULL; | |
820 oop value = values->obj_at(i); | |
821 if (i < local_count) { | |
822 ScopeValue* first = get_scope_value(value, objects, second); | |
823 if (second != NULL) { | |
824 locals->append(second); | |
825 } | |
826 locals->append(first); | |
827 } else if (i < local_count + expression_count) { | |
828 ScopeValue* first = get_scope_value(value, objects, second); | |
829 if (second != NULL) { | |
830 expressions->append(second); | |
831 } | |
832 expressions->append(first); | |
833 } else { | |
834 monitors->append(get_monitor_value(value, objects)); | |
835 } | |
836 if (second != NULL) { | |
837 i++; | |
838 assert(i < values->length(), "double-slot value not followed by Value.ILLEGAL"); | |
839 assert(values->obj_at(i) == AbstractValue::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL"); | |
840 } | |
841 } | |
842 | |
843 locals_token = _debug_recorder->create_scope_values(locals); | |
844 expressions_token = _debug_recorder->create_scope_values(expressions); | |
845 monitors_token = _debug_recorder->create_monitor_values(monitors); | |
846 | |
847 throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE; | |
848 } | |
849 | |
850 _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, | |
851 locals_token, expressions_token, monitors_token); | |
852 } | |
853 | |
854 void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { | |
855 oop debug_info = CompilationResult_Infopoint::debugInfo(site); | |
856 assert(debug_info != NULL, "debug info expected"); | |
857 | |
858 // address instruction = _instructions->start() + pc_offset; | |
859 // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start(); | |
860 _debug_recorder->add_safepoint(pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); | |
861 record_scope(pc_offset, debug_info); | |
862 _debug_recorder->end_safepoint(pc_offset); | |
863 } | |
864 | |
865 void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, oop site) { | |
866 oop debug_info = CompilationResult_Infopoint::debugInfo(site); | |
867 assert(debug_info != NULL, "debug info expected"); | |
868 | |
869 _debug_recorder->add_non_safepoint(pc_offset); | |
870 record_scope(pc_offset, debug_info); | |
871 _debug_recorder->end_non_safepoint(pc_offset); | |
872 } | |
873 | |
874 void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) { | |
875 oop target = CompilationResult_Call::target(site); | |
876 InstanceKlass* target_klass = InstanceKlass::cast(target->klass()); | |
877 | |
878 oop hotspot_method = NULL; // JavaMethod | |
879 oop foreign_call = NULL; | |
880 | |
881 if (target_klass->is_subclass_of(SystemDictionary::HotSpotForeignCallTarget_klass())) { | |
882 foreign_call = target; | |
883 } else { | |
884 hotspot_method = target; | |
885 } | |
886 | |
887 oop debug_info = CompilationResult_Call::debugInfo(site); | |
888 | |
889 assert(!!hotspot_method ^ !!foreign_call, "Call site needs exactly one type"); | |
890 | |
891 NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); | |
892 jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method); | |
893 | |
894 if (debug_info != NULL) { | |
895 _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); | |
896 record_scope(next_pc_offset, debug_info); | |
897 } | |
898 | |
899 if (foreign_call != NULL) { | |
900 jlong foreign_call_destination = HotSpotForeignCallTarget::address(foreign_call); | |
901 CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination); | |
902 } else { // method != NULL | |
903 assert(hotspot_method != NULL, "unexpected JavaMethod"); | |
904 assert(debug_info != NULL, "debug info expected"); | |
905 | |
906 TRACE_jvmci_3("method call"); | |
907 CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset); | |
908 if (_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) { | |
909 // Need a static call stub for transitions from compiled to interpreted. | |
910 CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset); | |
911 } | |
912 } | |
913 | |
914 _next_call_type = INVOKE_INVALID; | |
915 | |
916 if (debug_info != NULL) { | |
917 _debug_recorder->end_safepoint(next_pc_offset); | |
918 } | |
919 } | |
920 | |
921 void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) { | |
922 oop reference = CompilationResult_DataPatch::reference(site); | |
923 if (reference->is_a(CompilationResult_ConstantReference::klass())) { | |
924 Handle constant = CompilationResult_ConstantReference::constant(reference); | |
925 if (constant->is_a(HotSpotObjectConstantImpl::klass())) { | |
926 pd_patch_OopConstant(pc_offset, constant); | |
927 } else if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) { | |
928 record_metadata_in_patch(constant, _oop_recorder); | |
929 } else { | |
930 fatal("unknown constant type in data patch"); | |
931 } | |
932 } else if (reference->is_a(CompilationResult_DataSectionReference::klass())) { | |
933 int data_offset = CompilationResult_DataSectionReference::offset(reference); | |
934 assert(0 <= data_offset && data_offset < _constants_size, err_msg("data offset 0x%X points outside data section (size 0x%X)", data_offset, _constants_size)); | |
935 pd_patch_DataSectionReference(pc_offset, data_offset); | |
936 } else { | |
937 fatal("unknown data patch type"); | |
938 } | |
939 } | |
940 | |
941 void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) { | |
942 oop id_obj = CompilationResult_Mark::id(site); | |
943 | |
944 if (id_obj != NULL) { | |
945 assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected"); | |
946 jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT)); | |
947 | |
948 address pc = _instructions->start() + pc_offset; | |
949 | |
950 switch (id) { | |
951 case UNVERIFIED_ENTRY: | |
952 _offsets.set_value(CodeOffsets::Entry, pc_offset); | |
953 break; | |
954 case VERIFIED_ENTRY: | |
955 _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset); | |
956 break; | |
957 case OSR_ENTRY: | |
958 _offsets.set_value(CodeOffsets::OSR_Entry, pc_offset); | |
959 break; | |
960 case EXCEPTION_HANDLER_ENTRY: | |
961 _offsets.set_value(CodeOffsets::Exceptions, pc_offset); | |
962 break; | |
963 case DEOPT_HANDLER_ENTRY: | |
964 _offsets.set_value(CodeOffsets::Deopt, pc_offset); | |
965 break; | |
966 case INVOKEVIRTUAL: | |
967 case INVOKEINTERFACE: | |
968 case INLINE_INVOKE: | |
969 case INVOKESTATIC: | |
970 case INVOKESPECIAL: | |
971 _next_call_type = (MarkId) id; | |
972 _invoke_mark_pc = pc; | |
973 break; | |
974 case POLL_NEAR: | |
975 case POLL_FAR: | |
976 case POLL_RETURN_NEAR: | |
977 case POLL_RETURN_FAR: | |
978 pd_relocate_poll(pc, id); | |
979 break; | |
980 case CARD_TABLE_SHIFT: | |
981 case CARD_TABLE_ADDRESS: | |
982 break; | |
983 default: | |
984 ShouldNotReachHere(); | |
985 break; | |
986 } | |
987 } | |
988 } | |
989 |