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