mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8305387: JDK-8301995 breaks arm 32-bit
Reviewed-by: shade, matsaave
This commit is contained in:
parent
3d9d84b742
commit
60a29a668c
4 changed files with 103 additions and 13 deletions
|
@ -290,6 +290,27 @@ void InterpreterMacroAssembler::load_resolved_klass_at_offset(
|
||||||
ldr(Rklass, Address(Rklass, Array<Klass*>::base_offset_in_bytes()));
|
ldr(Rklass, Address(Rklass, Array<Klass*>::base_offset_in_bytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterpreterMacroAssembler::load_resolved_indy_entry(Register cache, Register index) {
|
||||||
|
// Get index out of bytecode pointer, get_cache_entry_pointer_at_bcp
|
||||||
|
assert_different_registers(cache, index, Rtemp);
|
||||||
|
|
||||||
|
get_index_at_bcp(index, 1, Rtemp, sizeof(u4));
|
||||||
|
|
||||||
|
// load constant pool cache pointer
|
||||||
|
ldr(cache, Address(FP, frame::interpreter_frame_cache_offset * wordSize));
|
||||||
|
|
||||||
|
// Get address of invokedynamic array
|
||||||
|
ldr(cache, Address(cache, in_bytes(ConstantPoolCache::invokedynamic_entries_offset())));
|
||||||
|
|
||||||
|
// Scale the index to be the entry index * sizeof(ResolvedInvokeDynamicInfo)
|
||||||
|
// On ARM32 sizeof(ResolvedIndyEntry) is 12, use mul instead of lsl
|
||||||
|
mov(Rtemp, sizeof(ResolvedIndyEntry));
|
||||||
|
mul(index, index, Rtemp);
|
||||||
|
|
||||||
|
add(cache, cache, Array<ResolvedIndyEntry>::base_offset_in_bytes());
|
||||||
|
add(cache, cache, index);
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a subtype check: branch to not_subtype if sub_klass is
|
// Generate a subtype check: branch to not_subtype if sub_klass is
|
||||||
// not a subtype of super_klass.
|
// not a subtype of super_klass.
|
||||||
// Profiling code for the subtype check failure (profile_typecheck_failed)
|
// Profiling code for the subtype check failure (profile_typecheck_failed)
|
||||||
|
|
|
@ -69,7 +69,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
inline void check_extended_sp(Register tmp) {}
|
inline void check_extended_sp(Register tmp) {}
|
||||||
inline void check_no_cached_stack_top(Register tmp) {}
|
inline void check_no_cached_stack_top(Register tmp) {}
|
||||||
|
|
||||||
|
|
||||||
void save_bcp() { str(Rbcp, Address(FP, frame::interpreter_frame_bcp_offset * wordSize)); }
|
void save_bcp() { str(Rbcp, Address(FP, frame::interpreter_frame_bcp_offset * wordSize)); }
|
||||||
void restore_bcp() { ldr(Rbcp, Address(FP, frame::interpreter_frame_bcp_offset * wordSize)); }
|
void restore_bcp() { ldr(Rbcp, Address(FP, frame::interpreter_frame_bcp_offset * wordSize)); }
|
||||||
void restore_locals() {
|
void restore_locals() {
|
||||||
|
@ -103,6 +102,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
// load cpool->resolved_klass_at(index); Rtemp is corrupted upon return
|
// load cpool->resolved_klass_at(index); Rtemp is corrupted upon return
|
||||||
void load_resolved_klass_at_offset(Register Rcpool, Register Rindex, Register Rklass);
|
void load_resolved_klass_at_offset(Register Rcpool, Register Rindex, Register Rklass);
|
||||||
|
|
||||||
|
void load_resolved_indy_entry(Register cache, Register index);
|
||||||
|
|
||||||
void pop_ptr(Register r);
|
void pop_ptr(Register r);
|
||||||
void pop_i(Register r = R0_tos);
|
void pop_i(Register r = R0_tos);
|
||||||
void pop_l(Register lo = R0_tos_lo, Register hi = R1_tos_hi);
|
void pop_l(Register lo = R0_tos_lo, Register hi = R1_tos_hi);
|
||||||
|
|
|
@ -364,24 +364,32 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
|
||||||
|
|
||||||
const Register Rcache = R2_tmp;
|
const Register Rcache = R2_tmp;
|
||||||
const Register Rindex = R3_tmp;
|
const Register Rindex = R3_tmp;
|
||||||
__ get_cache_and_index_at_bcp(Rcache, Rindex, 1, index_size);
|
|
||||||
|
|
||||||
__ add(Rtemp, Rcache, AsmOperand(Rindex, lsl, LogBytesPerWord));
|
if (index_size == sizeof(u4)) {
|
||||||
__ ldrb(Rtemp, Address(Rtemp, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()));
|
__ load_resolved_indy_entry(Rcache, Rindex);
|
||||||
__ check_stack_top();
|
__ ldrh(Rcache, Address(Rcache, in_bytes(ResolvedIndyEntry::num_parameters_offset())));
|
||||||
__ add(Rstack_top, Rstack_top, AsmOperand(Rtemp, lsl, Interpreter::logStackElementSize));
|
__ check_stack_top();
|
||||||
|
__ add(Rstack_top, Rstack_top, AsmOperand(Rcache, lsl, Interpreter::logStackElementSize));
|
||||||
|
} else {
|
||||||
|
// Pop N words from the stack
|
||||||
|
__ get_cache_and_index_at_bcp(Rcache, Rindex, 1, index_size);
|
||||||
|
|
||||||
|
__ add(Rtemp, Rcache, AsmOperand(Rindex, lsl, LogBytesPerWord));
|
||||||
|
__ ldrb(Rtemp, Address(Rtemp, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()));
|
||||||
|
__ check_stack_top();
|
||||||
|
__ add(Rstack_top, Rstack_top, AsmOperand(Rtemp, lsl, Interpreter::logStackElementSize));
|
||||||
|
}
|
||||||
|
|
||||||
__ convert_retval_to_tos(state);
|
__ convert_retval_to_tos(state);
|
||||||
|
|
||||||
__ check_and_handle_popframe();
|
__ check_and_handle_popframe();
|
||||||
__ check_and_handle_earlyret();
|
__ check_and_handle_earlyret();
|
||||||
|
|
||||||
__ dispatch_next(state, step);
|
__ dispatch_next(state, step);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step, address continuation) {
|
address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step, address continuation) {
|
||||||
address entry = __ pc();
|
address entry = __ pc();
|
||||||
|
|
||||||
|
|
|
@ -2608,6 +2608,66 @@ void TemplateTable::load_field_cp_cache_entry(Register Rcache,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The rmethod register is input and overwritten to be the adapter method for the
|
||||||
|
// indy call. Link Register (lr) is set to the return address for the adapter and
|
||||||
|
// an appendix may be pushed to the stack. Registers R1-R3, Rtemp (R12) are clobbered
|
||||||
|
void TemplateTable::load_invokedynamic_entry(Register method) {
|
||||||
|
// setup registers
|
||||||
|
const Register appendix = R1;
|
||||||
|
const Register cache = R2_tmp;
|
||||||
|
const Register index = R3_tmp;
|
||||||
|
assert_different_registers(method, appendix, cache, index);
|
||||||
|
|
||||||
|
__ save_bcp();
|
||||||
|
|
||||||
|
Label resolved;
|
||||||
|
__ load_resolved_indy_entry(cache, index);
|
||||||
|
// Load-acquire the adapter method to match store-release in ResolvedIndyEntry::fill_in()
|
||||||
|
__ ldr(method, Address(cache, in_bytes(ResolvedIndyEntry::method_offset())));
|
||||||
|
TemplateTable::volatile_barrier(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg, true);
|
||||||
|
// Compare the method to zero
|
||||||
|
__ cbnz(method, resolved);
|
||||||
|
|
||||||
|
Bytecodes::Code code = bytecode();
|
||||||
|
|
||||||
|
// Call to the interpreter runtime to resolve invokedynamic
|
||||||
|
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
|
||||||
|
__ mov(R1, code); // this is essentially Bytecodes::_invokedynamic, call_VM requires R1
|
||||||
|
__ call_VM(noreg, entry, R1);
|
||||||
|
// Update registers with resolved info
|
||||||
|
__ load_resolved_indy_entry(cache, index);
|
||||||
|
// Load-acquire the adapter method to match store-release in ResolvedIndyEntry::fill_in()
|
||||||
|
__ ldr(method, Address(cache, in_bytes(ResolvedIndyEntry::method_offset())));
|
||||||
|
TemplateTable::volatile_barrier(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg, true);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
__ cbnz(method, resolved);
|
||||||
|
__ stop("Should be resolved by now");
|
||||||
|
#endif // ASSERT
|
||||||
|
__ bind(resolved);
|
||||||
|
|
||||||
|
Label L_no_push;
|
||||||
|
// Check if there is an appendix
|
||||||
|
__ ldrb(index, Address(cache, in_bytes(ResolvedIndyEntry::flags_offset())));
|
||||||
|
__ tbz(index, ResolvedIndyEntry::has_appendix_shift, L_no_push);
|
||||||
|
// Get appendix
|
||||||
|
__ ldrh(index, Address(cache, in_bytes(ResolvedIndyEntry::resolved_references_index_offset())));
|
||||||
|
// Push the appendix as a trailing parameter
|
||||||
|
// since the parameter_size includes it.
|
||||||
|
__ load_resolved_reference_at_index(appendix, index);
|
||||||
|
__ verify_oop(appendix);
|
||||||
|
__ push(appendix); // push appendix (MethodType, CallSite, etc.)
|
||||||
|
__ bind(L_no_push);
|
||||||
|
|
||||||
|
// compute return type
|
||||||
|
__ ldrb(index, Address(cache, in_bytes(ResolvedIndyEntry::result_type_offset())));
|
||||||
|
// load return address
|
||||||
|
{
|
||||||
|
const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
|
||||||
|
__ mov_address(Rtemp, table_addr);
|
||||||
|
__ ldr(LR, Address(Rtemp, index, lsl, Interpreter::logStackElementSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Blows all volatile registers: R0-R3, Rtemp, LR.
|
// Blows all volatile registers: R0-R3, Rtemp, LR.
|
||||||
void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
|
void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
|
||||||
|
@ -2616,7 +2676,7 @@ void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
|
||||||
Register flags,
|
Register flags,
|
||||||
bool is_invokevirtual,
|
bool is_invokevirtual,
|
||||||
bool is_invokevfinal/*unused*/,
|
bool is_invokevfinal/*unused*/,
|
||||||
bool is_invokedynamic) {
|
bool is_invokedynamic /*unused*/) {
|
||||||
// setup registers
|
// setup registers
|
||||||
const Register cache = R2_tmp;
|
const Register cache = R2_tmp;
|
||||||
const Register index = R3_tmp;
|
const Register index = R3_tmp;
|
||||||
|
@ -2639,7 +2699,7 @@ void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
|
||||||
const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
|
const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
|
||||||
ConstantPoolCacheEntry::f2_offset());
|
ConstantPoolCacheEntry::f2_offset());
|
||||||
|
|
||||||
size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
|
size_t index_size = sizeof(u2);
|
||||||
resolve_cache_and_index(byte_no, cache, index, index_size);
|
resolve_cache_and_index(byte_no, cache, index, index_size);
|
||||||
__ add(temp_reg, cache, AsmOperand(index, lsl, LogBytesPerWord));
|
__ add(temp_reg, cache, AsmOperand(index, lsl, LogBytesPerWord));
|
||||||
__ ldr(method, Address(temp_reg, method_offset));
|
__ ldr(method, Address(temp_reg, method_offset));
|
||||||
|
@ -3565,7 +3625,7 @@ void TemplateTable::prepare_invoke(int byte_no,
|
||||||
load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
|
load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
|
||||||
|
|
||||||
// maybe push extra argument
|
// maybe push extra argument
|
||||||
if (is_invokedynamic || is_invokehandle) {
|
if (is_invokehandle) {
|
||||||
Label L_no_push;
|
Label L_no_push;
|
||||||
__ tbz(flags, ConstantPoolCacheEntry::has_appendix_shift, L_no_push);
|
__ tbz(flags, ConstantPoolCacheEntry::has_appendix_shift, L_no_push);
|
||||||
__ mov(temp, index);
|
__ mov(temp, index);
|
||||||
|
@ -3810,7 +3870,7 @@ void TemplateTable::invokedynamic(int byte_no) {
|
||||||
const Register Rcallsite = R4_tmp;
|
const Register Rcallsite = R4_tmp;
|
||||||
const Register R5_method = R5_tmp; // can't reuse Rmethod!
|
const Register R5_method = R5_tmp; // can't reuse Rmethod!
|
||||||
|
|
||||||
prepare_invoke(byte_no, R5_method, Rcallsite);
|
load_invokedynamic_entry(R5_method);
|
||||||
|
|
||||||
// Rcallsite: CallSite object (from cpool->resolved_references[f1])
|
// Rcallsite: CallSite object (from cpool->resolved_references[f1])
|
||||||
// Rmethod: MH.linkToCallSite method (from f2)
|
// Rmethod: MH.linkToCallSite method (from f2)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue