annotate src/share/vm/jvmci/jvmciCodeInstaller.cpp @ 22721:510846133438

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