Commit b2c246e0 authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: [Interpreter] Add ForInPrepare runtime function which returns a ObjectTriple.

Port 84f8a506

Original commit message:
    Adds a ForInPrepare Runtime function which returns a triple of
    cache_type, cache_array and cache_length.

    This requires adding support to CEntryStub to call runtime functions
    which return a ObjectTriple - a struct containing three Object*
    pointers. Also did some cleanup of the x64 CEntryStub to avoid
    replicated code.

    Replaces the interpreter's use of the ad-hock InterpreterForInPrepare
    Runtime function with ForInPrepare in preparation for fixing deopt in
    BytecodeGraphBuilder for ForIn (which will be done in a followup CL).

R=rmcilroy@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=v8:4280
LOG=N

Review URL: https://codereview.chromium.org/1586153004

Cr-Commit-Position: refs/heads/master@{#33342}
parent bbb95fba
...@@ -53,8 +53,11 @@ ...@@ -53,8 +53,11 @@
#define ABI_PASSES_HANDLES_IN_REGS \ #define ABI_PASSES_HANDLES_IN_REGS \
(!V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64) (!V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64)
#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS \ #if (!V8_HOST_ARCH_PPC || !V8_TARGET_ARCH_PPC64 || V8_TARGET_LITTLE_ENDIAN)
(!V8_HOST_ARCH_PPC || !V8_TARGET_ARCH_PPC64 || V8_TARGET_LITTLE_ENDIAN) #define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 1
#else
#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 0
#endif
#if !V8_HOST_ARCH_PPC || (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN) #if !V8_HOST_ARCH_PPC || (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
#define ABI_CALL_VIA_IP 1 #define ABI_CALL_VIA_IP 1
......
...@@ -1055,14 +1055,13 @@ void CEntryStub::Generate(MacroAssembler* masm) { ...@@ -1055,14 +1055,13 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Need at least one extra slot for return address location. // Need at least one extra slot for return address location.
int arg_stack_space = 1; int arg_stack_space = 1;
// PPC LINUX ABI:
#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
// Pass buffer for return value on stack if necessary // Pass buffer for return value on stack if necessary
if (result_size() > 1) { bool needs_return_buffer =
DCHECK_EQ(2, result_size()); result_size() > 2 ||
arg_stack_space += 2; (result_size() == 2 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS);
if (needs_return_buffer) {
arg_stack_space += result_size();
} }
#endif
__ EnterExitFrame(save_doubles(), arg_stack_space); __ EnterExitFrame(save_doubles(), arg_stack_space);
...@@ -1076,9 +1075,8 @@ void CEntryStub::Generate(MacroAssembler* masm) { ...@@ -1076,9 +1075,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Result returned in registers or stack, depending on result size and ABI. // Result returned in registers or stack, depending on result size and ABI.
Register isolate_reg = r5; Register isolate_reg = r5;
#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS if (needs_return_buffer) {
if (result_size() > 1) { // The return value is a non-scalar value.
// The return value is 16-byte non-scalar value.
// Use frame storage reserved by calling function to pass return // Use frame storage reserved by calling function to pass return
// buffer as implicit first argument. // buffer as implicit first argument.
__ mr(r5, r4); __ mr(r5, r4);
...@@ -1086,7 +1084,6 @@ void CEntryStub::Generate(MacroAssembler* masm) { ...@@ -1086,7 +1084,6 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize)); __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
isolate_reg = r6; isolate_reg = r6;
} }
#endif
// Call C built-in. // Call C built-in.
__ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate()))); __ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate())));
...@@ -1112,13 +1109,12 @@ void CEntryStub::Generate(MacroAssembler* masm) { ...@@ -1112,13 +1109,12 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ Call(target); __ Call(target);
__ bind(&after_call); __ bind(&after_call);
#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
// If return value is on the stack, pop it to registers. // If return value is on the stack, pop it to registers.
if (result_size() > 1) { if (needs_return_buffer) {
if (result_size() > 2) __ LoadP(r5, MemOperand(r3, 2 * kPointerSize));
__ LoadP(r4, MemOperand(r3, kPointerSize)); __ LoadP(r4, MemOperand(r3, kPointerSize));
__ LoadP(r3, MemOperand(r3)); __ LoadP(r3, MemOperand(r3));
} }
#endif
// Check result for exception sentinel. // Check result for exception sentinel.
Label exception_returned; Label exception_returned;
...@@ -1132,9 +1128,9 @@ void CEntryStub::Generate(MacroAssembler* masm) { ...@@ -1132,9 +1128,9 @@ void CEntryStub::Generate(MacroAssembler* masm) {
ExternalReference pending_exception_address( ExternalReference pending_exception_address(
Isolate::kPendingExceptionAddress, isolate()); Isolate::kPendingExceptionAddress, isolate());
__ mov(r5, Operand(pending_exception_address)); __ mov(r6, Operand(pending_exception_address));
__ LoadP(r5, MemOperand(r5)); __ LoadP(r6, MemOperand(r6));
__ CompareRoot(r5, Heap::kTheHoleValueRootIndex); __ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
// Cannot use check here as it attempts to generate call into runtime. // Cannot use check here as it attempts to generate call into runtime.
__ beq(&okay); __ beq(&okay);
__ stop("Unexpected pending exception"); __ stop("Unexpected pending exception");
......
...@@ -16,6 +16,7 @@ namespace internal { ...@@ -16,6 +16,7 @@ namespace internal {
// Give alias names to registers for calling conventions. // Give alias names to registers for calling conventions.
const Register kReturnRegister0 = {Register::kCode_r3}; const Register kReturnRegister0 = {Register::kCode_r3};
const Register kReturnRegister1 = {Register::kCode_r4}; const Register kReturnRegister1 = {Register::kCode_r4};
const Register kReturnRegister2 = {Register::kCode_r5};
const Register kJSFunctionRegister = {Register::kCode_r4}; const Register kJSFunctionRegister = {Register::kCode_r4};
const Register kContextRegister = {Register::kCode_r30}; const Register kContextRegister = {Register::kCode_r30};
const Register kInterpreterAccumulatorRegister = {Register::kCode_r3}; const Register kInterpreterAccumulatorRegister = {Register::kCode_r3};
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "src/ppc/constants-ppc.h" #include "src/ppc/constants-ppc.h"
#include "src/ppc/frames-ppc.h" #include "src/ppc/frames-ppc.h"
#include "src/ppc/simulator-ppc.h" #include "src/ppc/simulator-ppc.h"
#include "src/runtime/runtime-utils.h"
#if defined(USE_SIMULATOR) #if defined(USE_SIMULATOR)
...@@ -1171,20 +1172,11 @@ bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right, ...@@ -1171,20 +1172,11 @@ bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
#if V8_TARGET_ARCH_PPC64 #if V8_TARGET_ARCH_PPC64
struct ObjectPair {
intptr_t x;
intptr_t y;
};
static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) { static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) {
*x = pair->x; *x = reinterpret_cast<intptr_t>(pair->x);
*y = pair->y; *y = reinterpret_cast<intptr_t>(pair->y);
} }
#else #else
typedef uint64_t ObjectPair;
static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) { static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) {
#if V8_TARGET_BIG_ENDIAN #if V8_TARGET_BIG_ENDIAN
*x = static_cast<int32_t>(*pair >> 32); *x = static_cast<int32_t>(*pair >> 32);
...@@ -1207,6 +1199,11 @@ typedef ObjectPair (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1, ...@@ -1207,6 +1199,11 @@ typedef ObjectPair (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1,
intptr_t arg2, intptr_t arg3, intptr_t arg2, intptr_t arg3,
intptr_t arg4, intptr_t arg5); intptr_t arg4, intptr_t arg5);
typedef ObjectTriple (*SimulatorRuntimeTripleCall)(intptr_t arg0, intptr_t arg1,
intptr_t arg2, intptr_t arg3,
intptr_t arg4,
intptr_t arg5);
// These prototypes handle the four types of FP calls. // These prototypes handle the four types of FP calls.
typedef int (*SimulatorRuntimeCompareCall)(double darg0, double darg1); typedef int (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1); typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
...@@ -1237,13 +1234,13 @@ void Simulator::SoftwareInterrupt(Instruction* instr) { ...@@ -1237,13 +1234,13 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
Redirection* redirection = Redirection::FromSwiInstruction(instr); Redirection* redirection = Redirection::FromSwiInstruction(instr);
const int kArgCount = 6; const int kArgCount = 6;
int arg0_regnum = 3; int arg0_regnum = 3;
#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
intptr_t result_buffer = 0; intptr_t result_buffer = 0;
if (redirection->type() == ExternalReference::BUILTIN_OBJECTPAIR_CALL) { if (redirection->type() == ExternalReference::BUILTIN_CALL_TRIPLE ||
(redirection->type() == ExternalReference::BUILTIN_CALL_PAIR &&
!ABI_RETURNS_OBJECT_PAIRS_IN_REGS)) {
result_buffer = get_register(r3); result_buffer = get_register(r3);
arg0_regnum++; arg0_regnum++;
} }
#endif
intptr_t arg[kArgCount]; intptr_t arg[kArgCount];
for (int i = 0; i < kArgCount; i++) { for (int i = 0; i < kArgCount; i++) {
arg[i] = get_register(arg0_regnum + i); arg[i] = get_register(arg0_regnum + i);
...@@ -1430,19 +1427,36 @@ void Simulator::SoftwareInterrupt(Instruction* instr) { ...@@ -1430,19 +1427,36 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
PrintF("\n"); PrintF("\n");
} }
CHECK(stack_aligned); CHECK(stack_aligned);
DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL); if (redirection->type() == ExternalReference::BUILTIN_CALL_TRIPLE) {
SimulatorRuntimeCall target = SimulatorRuntimeTripleCall target =
reinterpret_cast<SimulatorRuntimeCall>(external); reinterpret_cast<SimulatorRuntimeTripleCall>(external);
ObjectPair result = ObjectTriple result =
target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]); target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
intptr_t x; if (::v8::internal::FLAG_trace_sim) {
intptr_t y; PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
decodeObjectPair(&result, &x, &y); "}\n",
if (::v8::internal::FLAG_trace_sim) { reinterpret_cast<intptr_t>(result.x),
PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR "}\n", x, y); reinterpret_cast<intptr_t>(result.y),
} reinterpret_cast<intptr_t>(result.z));
set_register(r3, x); }
set_register(r4, y); memcpy(reinterpret_cast<void*>(result_buffer), &result,
sizeof(ObjectTriple));
set_register(r3, result_buffer);
} else {
DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL);
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
ObjectPair result =
target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
intptr_t x;
intptr_t y;
decodeObjectPair(&result, &x, &y);
if (::v8::internal::FLAG_trace_sim) {
PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR "}\n", x, y);
}
set_register(r3, x);
set_register(r4, y);
}
} }
set_pc(saved_lr); set_pc(saved_lr);
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment