8155980: ARM InterpreterMacroAssembler::get_method_counters() should not be saving caller saved registers
Summary: make get_method_counters() only save registers specified by caller, not all of them
Reviewed-by: dlong, jiangli
--- a/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp Wed Mar 01 13:47:11 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp Wed Mar 01 14:59:36 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -234,8 +234,15 @@
#ifdef AARCH64
interpreter_frame->interpreter_frame_set_stack_top(stack_top);
+ // We have to add extra reserved slots to max_stack. There are 3 users of the extra slots,
+ // none of which are at the same time, so we just need to make sure there is enough room
+ // for the biggest user:
+ // -reserved slot for exception handler
+ // -reserved slots for JSR292. Method::extra_stack_entries() is the size.
+ // -3 reserved slots so get_method_counters() can save some registers before call_VM().
+ int max_stack = method->constMethod()->max_stack() + MAX2(3, Method::extra_stack_entries());
intptr_t* extended_sp = (intptr_t*) monbot -
- (method->max_stack() + 1) * Interpreter::stackElementWords - // +1 is reserved slot for exception handler
+ (max_stack * Interpreter::stackElementWords) -
popframe_extra_args;
extended_sp = (intptr_t*)round_down((intptr_t)extended_sp, StackAlignmentInBytes);
interpreter_frame->interpreter_frame_set_extended_sp(extended_sp);
--- a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp Wed Mar 01 13:47:11 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp Wed Mar 01 14:59:36 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2195,75 +2195,42 @@
void InterpreterMacroAssembler::get_method_counters(Register method,
Register Rcounters,
- Label& skip) {
+ Label& skip,
+ bool saveRegs,
+ Register reg1,
+ Register reg2,
+ Register reg3) {
const Address method_counters(method, Method::method_counters_offset());
Label has_counters;
ldr(Rcounters, method_counters);
cbnz(Rcounters, has_counters);
+ if (saveRegs) {
+ // Save and restore in use caller-saved registers since they will be trashed by call_VM
+ assert(reg1 != noreg, "must specify reg1");
+ assert(reg2 != noreg, "must specify reg2");
#ifdef AARCH64
- const Register tmp = Rcounters;
- const int saved_regs_size = 20*wordSize;
-
- // Note: call_VM will cut SP according to Rstack_top value before call, and restore SP to
- // extended_sp value from frame after the call.
- // So make sure there is enough stack space to save registers and adjust Rstack_top accordingly.
- {
- Label enough_stack_space;
- check_extended_sp(tmp);
- sub(Rstack_top, Rstack_top, saved_regs_size);
- cmp(SP, Rstack_top);
- b(enough_stack_space, ls);
-
- align_reg(tmp, Rstack_top, StackAlignmentInBytes);
- mov(SP, tmp);
- str(tmp, Address(FP, frame::interpreter_frame_extended_sp_offset * wordSize));
-
- bind(enough_stack_space);
- check_stack_top();
-
- int offset = 0;
- stp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize;
- stp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize;
- stp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize;
- stp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize;
- stp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize;
- stp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize;
- stp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize;
- stp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize;
- stp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize;
- stp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize;
- assert (offset == saved_regs_size, "should be");
+ assert(reg3 != noreg, "must specify reg3");
+ stp(reg1, reg2, Address(Rstack_top, -2*wordSize, pre_indexed));
+ stp(reg3, ZR, Address(Rstack_top, -2*wordSize, pre_indexed));
+#else
+ assert(reg3 == noreg, "must not specify reg3");
+ push(RegisterSet(reg1) | RegisterSet(reg2));
+#endif
}
-#else
- push(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14));
-#endif // AARCH64
mov(R1, method);
- call_VM(noreg, CAST_FROM_FN_PTR(address,
- InterpreterRuntime::build_method_counters), R1);
-
+ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), R1);
+
+ if (saveRegs) {
#ifdef AARCH64
- {
- int offset = 0;
- ldp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize;
- ldp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize;
- ldp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize;
- ldp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize;
- ldp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize;
- ldp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize;
- ldp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize;
- ldp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize;
- ldp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize;
- ldp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize;
- assert (offset == saved_regs_size, "should be");
-
- add(Rstack_top, Rstack_top, saved_regs_size);
+ ldp(reg3, ZR, Address(Rstack_top, 2*wordSize, post_indexed));
+ ldp(reg1, reg2, Address(Rstack_top, 2*wordSize, post_indexed));
+#else
+ pop(RegisterSet(reg1) | RegisterSet(reg2));
+#endif
}
-#else
- pop(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14));
-#endif // AARCH64
ldr(Rcounters, method_counters);
cbz(Rcounters, skip); // No MethodCounters created, OutOfMemory
--- a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp Wed Mar 01 13:47:11 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp Wed Mar 01 14:59:36 2017 -0800
@@ -349,7 +349,13 @@
void trace_state(const char* msg) PRODUCT_RETURN;
- void get_method_counters(Register method, Register Rcounters, Label& skip);
+void get_method_counters(Register method,
+ Register Rcounters,
+ Label& skip,
+ bool saveRegs = false,
+ Register reg1 = noreg,
+ Register reg2 = noreg,
+ Register reg3 = noreg);
};
#endif // CPU_ARM_VM_INTERP_MASM_ARM_HPP
--- a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp Wed Mar 01 13:47:11 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp Wed Mar 01 14:59:36 2017 -0800
@@ -1401,7 +1401,13 @@
#ifdef AARCH64
// setup RmaxStack
__ ldrh(RmaxStack, Address(RconstMethod, ConstMethod::max_stack_offset()));
- __ add(RmaxStack, RmaxStack, MAX2(1, Method::extra_stack_entries())); // reserve slots for exception handler and JSR292 appendix argument
+ // We have to add extra reserved slots to max_stack. There are 3 users of the extra slots,
+ // none of which are at the same time, so we just need to make sure there is enough room
+ // for the biggest user:
+ // -reserved slot for exception handler
+ // -reserved slots for JSR292. Method::extra_stack_entries() is the size.
+ // -3 reserved slots so get_method_counters() can save some registers before call_VM().
+ __ add(RmaxStack, RmaxStack, MAX2(3, Method::extra_stack_entries()));
#endif // AARCH64
// see if we've got enough room on the stack for locals plus overhead.
--- a/hotspot/src/cpu/arm/vm/templateTable_arm.cpp Wed Mar 01 13:47:11 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/templateTable_arm.cpp Wed Mar 01 14:59:36 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2286,13 +2286,18 @@
}
__ bind(no_mdo);
// Increment backedge counter in MethodCounters*
- __ get_method_counters(Rmethod, Rcounters, dispatch);
+ // Note Rbumped_taken_count is a callee saved registers for ARM32, but caller saved for ARM64
+ __ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/,
+ Rdisp, R3_bytecode,
+ AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg));
const Address mask(Rcounters, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(Rcounters, be_offset), increment, mask,
Rcnt, R4_tmp, eq, &backedge_counter_overflow);
} else {
- // increment counter
- __ get_method_counters(Rmethod, Rcounters, dispatch);
+ // Increment backedge counter in MethodCounters*
+ __ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/,
+ Rdisp, R3_bytecode,
+ AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg));
__ ldr_u32(Rtemp, Address(Rcounters, be_offset)); // load backedge counter
__ add(Rtemp, Rtemp, InvocationCounter::count_increment); // increment counter
__ str_32(Rtemp, Address(Rcounters, be_offset)); // store counter