Commit 22611e8e authored by Jaideep Bajwa's avatar Jaideep Bajwa Committed by Commit Bot

PPC/s390: [Interpreter] Remove new.target from fixed frame slot.

Port c820b89b

Original Commit Message:

    Removes the new.target slot from the interpreter's fixed frame. Instead
    adds a field to BytecodeArray to get the bytecode's incoming
    new.target or generator object register. The InterpreterEntryTrampoline
    then sets this register with the incoming new.target (or generator object)
    when the function is called. This register can be directly the new.target
    or generator object variable if they are LOCAL location, otherwise it is a
    temporary register which is then moved to the variable's location during the
    function prologue.

    This fixes a hack in the deoptimizer where we would set the new.target fixed
    slot to undefined in order to avoid extending it's lifetime through the
    optimized code - now it's just a standard register and can be optimized away
    as normal.

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

Change-Id: Ifb93179153016ad989c6ae3675554e70c426e2fa
Reviewed-on: https://chromium-review.googlesource.com/612746Reviewed-by: 's avatarJoran Siu <joransiu@ca.ibm.com>
Commit-Queue: Jaideep Bajwa <bjaideep@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#47344}
parent 0b799e66
...@@ -1116,7 +1116,7 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, ...@@ -1116,7 +1116,7 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm,
// //
// The live registers are: // The live registers are:
// o r4: the JS function object being called. // o r4: the JS function object being called.
// o r6: the new target // o r6: the incoming new target or generator object
// o cp: our context // o cp: our context
// o pp: the caller's constant pool pointer (if enabled) // o pp: the caller's constant pool pointer (if enabled)
// o fp: the caller's frame pointer // o fp: the caller's frame pointer
...@@ -1196,9 +1196,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { ...@@ -1196,9 +1196,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ mov(kInterpreterBytecodeOffsetRegister, __ mov(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag)); Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
// Push new.target, bytecode array and Smi tagged bytecode array offset. // Push bytecode array and Smi tagged bytecode array offset.
__ SmiTag(r3, kInterpreterBytecodeOffsetRegister); __ SmiTag(r3, kInterpreterBytecodeOffsetRegister);
__ Push(r6, kInterpreterBytecodeArrayRegister, r3); __ Push(kInterpreterBytecodeArrayRegister, r3);
// Allocate the local and temporary register file on the stack. // Allocate the local and temporary register file on the stack.
{ {
...@@ -1208,9 +1208,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { ...@@ -1208,9 +1208,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// Do a stack check to ensure we don't go over the limit. // Do a stack check to ensure we don't go over the limit.
Label ok; Label ok;
__ sub(r6, sp, r5); __ sub(r8, sp, r5);
__ LoadRoot(r0, Heap::kRealStackLimitRootIndex); __ LoadRoot(r0, Heap::kRealStackLimitRootIndex);
__ cmpl(r6, r0); __ cmpl(r8, r0);
__ bge(&ok); __ bge(&ok);
__ CallRuntime(Runtime::kThrowStackOverflow); __ CallRuntime(Runtime::kThrowStackOverflow);
__ bind(&ok); __ bind(&ok);
...@@ -1218,16 +1218,29 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { ...@@ -1218,16 +1218,29 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// If ok, push undefined as the initial value for all register file entries. // If ok, push undefined as the initial value for all register file entries.
// TODO(rmcilroy): Consider doing more than one push per loop iteration. // TODO(rmcilroy): Consider doing more than one push per loop iteration.
Label loop, no_args; Label loop, no_args;
__ LoadRoot(r6, Heap::kUndefinedValueRootIndex); __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
__ ShiftRightImm(r5, r5, Operand(kPointerSizeLog2), SetRC); __ ShiftRightImm(r5, r5, Operand(kPointerSizeLog2), SetRC);
__ beq(&no_args, cr0); __ beq(&no_args, cr0);
__ mtctr(r5); __ mtctr(r5);
__ bind(&loop); __ bind(&loop);
__ push(r6); __ push(r8);
__ bdnz(&loop); __ bdnz(&loop);
__ bind(&no_args); __ bind(&no_args);
} }
// If the bytecode array has a valid incoming new target or generator object
// register, initialize it with incoming value which was passed in r6.
Label no_incoming_new_target_or_generator_register;
__ LoadWordArith(
r8, FieldMemOperand(
kInterpreterBytecodeArrayRegister,
BytecodeArray::kIncomingNewTargetOrGeneratorRegisterOffset));
__ cmpi(r8, Operand::Zero());
__ beq(&no_incoming_new_target_or_generator_register);
__ ShiftLeftImm(r8, r8, Operand(kPointerSizeLog2));
__ StorePX(r6, MemOperand(fp, r8));
__ bind(&no_incoming_new_target_or_generator_register);
// Load accumulator and dispatch table into registers. // Load accumulator and dispatch table into registers.
__ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex); __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
__ mov(kInterpreterDispatchTableRegister, __ mov(kInterpreterDispatchTableRegister,
......
...@@ -1114,7 +1114,7 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, ...@@ -1114,7 +1114,7 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm,
// //
// The live registers are: // The live registers are:
// o r3: the JS function object being called. // o r3: the JS function object being called.
// o r5: the new target // o r5: the incoming new target or generator object
// o cp: our context // o cp: our context
// o pp: the caller's constant pool pointer (if enabled) // o pp: the caller's constant pool pointer (if enabled)
// o fp: the caller's frame pointer // o fp: the caller's frame pointer
...@@ -1190,9 +1190,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { ...@@ -1190,9 +1190,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ mov(kInterpreterBytecodeOffsetRegister, __ mov(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag)); Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
// Push new.target, bytecode array and Smi tagged bytecode array offset. // Push bytecode array and Smi tagged bytecode array offset.
__ SmiTag(r4, kInterpreterBytecodeOffsetRegister); __ SmiTag(r4, kInterpreterBytecodeOffsetRegister);
__ Push(r5, kInterpreterBytecodeArrayRegister, r4); __ Push(kInterpreterBytecodeArrayRegister, r4);
// Allocate the local and temporary register file on the stack. // Allocate the local and temporary register file on the stack.
{ {
...@@ -1202,9 +1202,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { ...@@ -1202,9 +1202,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// Do a stack check to ensure we don't go over the limit. // Do a stack check to ensure we don't go over the limit.
Label ok; Label ok;
__ SubP(r5, sp, r4); __ SubP(r8, sp, r4);
__ LoadRoot(r0, Heap::kRealStackLimitRootIndex); __ LoadRoot(r0, Heap::kRealStackLimitRootIndex);
__ CmpLogicalP(r5, r0); __ CmpLogicalP(r8, r0);
__ bge(&ok); __ bge(&ok);
__ CallRuntime(Runtime::kThrowStackOverflow); __ CallRuntime(Runtime::kThrowStackOverflow);
__ bind(&ok); __ bind(&ok);
...@@ -1212,18 +1212,30 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { ...@@ -1212,18 +1212,30 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// If ok, push undefined as the initial value for all register file entries. // If ok, push undefined as the initial value for all register file entries.
// TODO(rmcilroy): Consider doing more than one push per loop iteration. // TODO(rmcilroy): Consider doing more than one push per loop iteration.
Label loop, no_args; Label loop, no_args;
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex); __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
__ ShiftRightP(r4, r4, Operand(kPointerSizeLog2)); __ ShiftRightP(r4, r4, Operand(kPointerSizeLog2));
__ LoadAndTestP(r4, r4); __ LoadAndTestP(r4, r4);
__ beq(&no_args); __ beq(&no_args);
__ LoadRR(r1, r4); __ LoadRR(r1, r4);
__ bind(&loop); __ bind(&loop);
__ push(r5); __ push(r8);
__ SubP(r1, Operand(1)); __ SubP(r1, Operand(1));
__ bne(&loop); __ bne(&loop);
__ bind(&no_args); __ bind(&no_args);
} }
// If the bytecode array has a valid incoming new target or generator object
// register, initialize it with incoming value which was passed in r6.
Label no_incoming_new_target_or_generator_register;
__ LoadW(r8, FieldMemOperand(
kInterpreterBytecodeArrayRegister,
BytecodeArray::kIncomingNewTargetOrGeneratorRegisterOffset));
__ CmpP(r8, Operand::Zero());
__ beq(&no_incoming_new_target_or_generator_register);
__ ShiftLeftP(r8, r8, Operand(kPointerSizeLog2));
__ StoreP(r5, MemOperand(fp, r8));
__ bind(&no_incoming_new_target_or_generator_register);
// Load accumulator and dispatch table into registers. // Load accumulator and dispatch table into registers.
__ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex); __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
__ mov(kInterpreterDispatchTableRegister, __ mov(kInterpreterDispatchTableRegister,
......
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