comparison src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp @ 22711:316e768645c0

8139589: [JVMCI] throw exceptions in faulty code installation operations
author Roland Schatz <roland.schatz@oracle.com>
date Thu, 29 Oct 2015 15:21:55 +0100
parents ceca35d52380
children 510846133438
comparison
equal deleted inserted replaced
22710:7e7573382a23 22711:316e768645c0
32 #include "asm/register.hpp" 32 #include "asm/register.hpp"
33 #include "classfile/vmSymbols.hpp" 33 #include "classfile/vmSymbols.hpp"
34 #include "code/vmreg.hpp" 34 #include "code/vmreg.hpp"
35 #include "vmreg_x86.inline.hpp" 35 #include "vmreg_x86.inline.hpp"
36 36
37 jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) { 37 jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
38 if (inst->is_call() || inst->is_jump()) { 38 if (inst->is_call() || inst->is_jump()) {
39 assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size"); 39 assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
40 return (pc_offset + NativeCall::instruction_size); 40 return (pc_offset + NativeCall::instruction_size);
41 } else if (inst->is_mov_literal64()) { 41 } else if (inst->is_mov_literal64()) {
42 // mov+call instruction pair 42 // mov+call instruction pair
49 assert(call[0] == 0xFF, "expected call"); 49 assert(call[0] == 0xFF, "expected call");
50 offset += 2; /* opcode byte + modrm byte */ 50 offset += 2; /* opcode byte + modrm byte */
51 return (offset); 51 return (offset);
52 } else if (inst->is_call_reg()) { 52 } else if (inst->is_call_reg()) {
53 // the inlined vtable stub contains a "call register" instruction 53 // the inlined vtable stub contains a "call register" instruction
54 assert(method != NULL, "only valid for virtual calls"); 54 assert(method.not_null(), "only valid for virtual calls");
55 return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset()); 55 return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
56 } else if (inst->is_cond_jump()) { 56 } else if (inst->is_cond_jump()) {
57 address pc = (address) (inst); 57 address pc = (address) (inst);
58 return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc); 58 return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc);
59 } else { 59 } else {
60 fatal("unsupported type of instruction for call site"); 60 JVMCI_ERROR_0("unsupported type of instruction for call site");
61 return 0; 61 }
62 } 62 }
63 } 63
64 64 void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
65 void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
66 address pc = _instructions->start() + pc_offset; 65 address pc = _instructions->start() + pc_offset;
67 Handle obj = HotSpotObjectConstantImpl::object(constant); 66 Handle obj = HotSpotObjectConstantImpl::object(constant);
68 jobject value = JNIHandles::make_local(obj()); 67 jobject value = JNIHandles::make_local(obj());
69 if (HotSpotObjectConstantImpl::compressed(constant)) { 68 if (HotSpotObjectConstantImpl::compressed(constant)) {
70 #ifdef _LP64 69 #ifdef _LP64
71 address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand); 70 address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
72 int oop_index = _oop_recorder->find_index(value); 71 int oop_index = _oop_recorder->find_index(value);
73 _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand); 72 _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
74 TRACE_jvmci_3("relocating (narrow oop constant) at %p/%p", pc, operand); 73 TRACE_jvmci_3("relocating (narrow oop constant) at %p/%p", pc, operand);
75 #else 74 #else
76 fatal("compressed oop on 32bit"); 75 JVMCI_ERROR("compressed oop on 32bit");
77 #endif 76 #endif
78 } else { 77 } else {
79 address operand = Assembler::locate_operand(pc, Assembler::imm_operand); 78 address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
80 *((jobject*) operand) = value; 79 *((jobject*) operand) = value;
81 _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); 80 _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
82 TRACE_jvmci_3("relocating (oop constant) at %p/%p", pc, operand); 81 TRACE_jvmci_3("relocating (oop constant) at %p/%p", pc, operand);
83 } 82 }
84 } 83 }
85 84
86 void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) { 85 void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
87 address pc = _instructions->start() + pc_offset; 86 address pc = _instructions->start() + pc_offset;
88 if (HotSpotMetaspaceConstantImpl::compressed(constant)) { 87 if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
89 #ifdef _LP64 88 #ifdef _LP64
90 address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand); 89 address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
91 *((narrowKlass*) operand) = record_narrow_metadata_reference(constant); 90 *((narrowKlass*) operand) = record_narrow_metadata_reference(constant, CHECK);
92 TRACE_jvmci_3("relocating (narrow metaspace constant) at %p/%p", pc, operand); 91 TRACE_jvmci_3("relocating (narrow metaspace constant) at %p/%p", pc, operand);
93 #else 92 #else
94 fatal("compressed Klass* on 32bit"); 93 JVMCI_ERROR("compressed Klass* on 32bit");
95 #endif 94 #endif
96 } else { 95 } else {
97 address operand = Assembler::locate_operand(pc, Assembler::imm_operand); 96 address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
98 *((Metadata**) operand) = record_metadata_reference(constant); 97 *((Metadata**) operand) = record_metadata_reference(constant, CHECK);
99 TRACE_jvmci_3("relocating (metaspace constant) at %p/%p", pc, operand); 98 TRACE_jvmci_3("relocating (metaspace constant) at %p/%p", pc, operand);
100 } 99 }
101 } 100 }
102 101
103 void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) { 102 void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
113 112
114 _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); 113 _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
115 TRACE_jvmci_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, data_offset); 114 TRACE_jvmci_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, data_offset);
116 } 115 }
117 116
118 void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { 117 void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
119 address pc = (address) inst; 118 address pc = (address) inst;
120 if (inst->is_call()) { 119 if (inst->is_call()) {
121 // NOTE: for call without a mov, the offset must fit a 32-bit immediate 120 // NOTE: for call without a mov, the offset must fit a 32-bit immediate
122 // see also CompilerToVM.getMaxCallTargetOffset() 121 // see also CompilerToVM.getMaxCallTargetOffset()
123 NativeCall* call = nativeCall_at(pc); 122 NativeCall* call = nativeCall_at(pc);
135 address old_dest = nativeGeneralJump_at(pc)->jump_destination(); 134 address old_dest = nativeGeneralJump_at(pc)->jump_destination();
136 address disp = Assembler::locate_operand(pc, Assembler::call32_operand); 135 address disp = Assembler::locate_operand(pc, Assembler::call32_operand);
137 *(jint*) disp += ((address) foreign_call_destination) - old_dest; 136 *(jint*) disp += ((address) foreign_call_destination) - old_dest;
138 _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand); 137 _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand);
139 } else { 138 } else {
140 fatal("unsupported relocation for foreign call"); 139 JVMCI_ERROR("unsupported relocation for foreign call");
141 } 140 }
142 141
143 TRACE_jvmci_3("relocating (foreign call) at %p", inst); 142 TRACE_jvmci_3("relocating (foreign call) at %p", inst);
144 } 143 }
145 144
146 void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) { 145 void CodeInstaller::pd_relocate_JavaMethod(Handle hotspot_method, jint pc_offset, TRAPS) {
147 #ifdef ASSERT 146 #ifdef ASSERT
148 Method* method = NULL; 147 Method* method = NULL;
149 // we need to check, this might also be an unresolved method 148 // we need to check, this might also be an unresolved method
150 if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) { 149 if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
151 method = getMethodFromHotSpotMethod(hotspot_method); 150 method = getMethodFromHotSpotMethod(hotspot_method());
152 } 151 }
153 #endif 152 #endif
154 switch (_next_call_type) { 153 switch (_next_call_type) {
155 case INLINE_INVOKE: 154 case INLINE_INVOKE:
156 break; 155 break;
181 _instructions->relocate(call->instruction_address(), 180 _instructions->relocate(call->instruction_address(),
182 relocInfo::opt_virtual_call_type, Assembler::call32_operand); 181 relocInfo::opt_virtual_call_type, Assembler::call32_operand);
183 break; 182 break;
184 } 183 }
185 default: 184 default:
185 JVMCI_ERROR("invalid _next_call_type value");
186 break; 186 break;
187 } 187 }
188 } 188 }
189 189
190 static void relocate_poll_near(address pc) { 190 static void relocate_poll_near(address pc) {
194 intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni; 194 intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
195 *disp = (int32_t)new_disp; 195 *disp = (int32_t)new_disp;
196 } 196 }
197 197
198 198
199 void CodeInstaller::pd_relocate_poll(address pc, jint mark) { 199 void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
200 switch (mark) { 200 switch (mark) {
201 case POLL_NEAR: { 201 case POLL_NEAR: {
202 relocate_poll_near(pc); 202 relocate_poll_near(pc);
203 _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand); 203 _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand);
204 break; 204 break;
218 case POLL_RETURN_FAR: 218 case POLL_RETURN_FAR:
219 // see comment above for POLL_FAR 219 // see comment above for POLL_FAR
220 _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand); 220 _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand);
221 break; 221 break;
222 default: 222 default:
223 fatal("invalid mark value"); 223 JVMCI_ERROR(err_msg("invalid mark value: %d", mark));
224 break; 224 break;
225 } 225 }
226 } 226 }
227 227
228 // convert JVMCI register indices (as used in oop maps) to HotSpot registers 228 // convert JVMCI register indices (as used in oop maps) to HotSpot registers
229 VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) { 229 VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
230 if (jvmci_reg < RegisterImpl::number_of_registers) { 230 if (jvmci_reg < RegisterImpl::number_of_registers) {
231 return as_Register(jvmci_reg)->as_VMReg(); 231 return as_Register(jvmci_reg)->as_VMReg();
232 } else { 232 } else {
233 jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers; 233 jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers;
234 if (floatRegisterNumber < XMMRegisterImpl::number_of_registers) { 234 if (floatRegisterNumber < XMMRegisterImpl::number_of_registers) {
235 return as_XMMRegister(floatRegisterNumber)->as_VMReg(); 235 return as_XMMRegister(floatRegisterNumber)->as_VMReg();
236 } 236 }
237 ShouldNotReachHere(); 237 JVMCI_ERROR_NULL(err_msg("invalid register number: %d", jvmci_reg));
238 return NULL;
239 } 238 }
240 } 239 }
241 240
242 bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) { 241 bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
243 return !(hotspotRegister->is_FloatRegister() || hotspotRegister->is_XMMRegister()); 242 return !(hotspotRegister->is_FloatRegister() || hotspotRegister->is_XMMRegister());