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