Mercurial > hg > graal-jvmci-8
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()); |