Commit 4445c095 authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: [runtime] Unify and simplify how frames are marked

Port 9dcd0857

Original commit message:
    Before this CL, various code stubs used different techniques
    for marking their frames to enable stack-crawling and other
    access to data in the frame. All of them were based on a abuse
    of the "standard" frame representation, e.g. storing the a
    context pointer immediately below the frame's fp, and a
    function pointer after that. Although functional, this approach
    tends to make stubs and builtins do an awkward, unnecessary
    dance to appear like standard frames, even if they have
    nothing to do with JavaScript execution.

    This CL attempts to improve this by:

    * Ensuring that there are only two fundamentally different
      types of frames, a "standard" frame and a "typed" frame.
      Standard frames, as before, contain both a context and
      function pointer. Typed frames contain only a minimum
      of a smi marker in the position immediately below the fp
      where the context is in standard frames.
    * Only interpreted, full codegen, and optimized Crankshaft and
      TurboFan JavaScript frames use the "standard" format. All
      other frames use the type frame format with an explicit
      marker.
    * Typed frames can contain one or more values below the
      type marker. There is new magic macro machinery in
      frames.h that simplifies defining the offsets of these fields
      in typed frames.
    * A new flag in the CallDescriptor enables specifying whether
      a frame is a standard frame or a typed frame. Secondary
      register location spilling is now only enabled for standard
      frames.
    * A zillion places in the code have been updated to deal with
      the fact that most code stubs and internal frames use the
      typed frame format. This includes changes in the
      deoptimizer, debugger, and liveedit.
    * StandardFrameConstants::kMarkerOffset is deprecated,
      (CommonFrameConstants::kContextOrFrameTypeOffset
      and StandardFrameConstants::kFrameOffset are now used
      in its stead).

R=danno@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=

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

Cr-Commit-Position: refs/heads/master@{#34643}
parent 50e43bc3
......@@ -1648,25 +1648,29 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (descriptor->IsCFunctionCall()) {
__ function_descriptor();
__ mflr(r0);
if (FLAG_enable_embedded_constant_pool) {
__ Push(r0, fp, kConstantPoolRegister);
// Adjust FP to point to saved FP.
__ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
} else {
__ Push(r0, fp);
__ mr(fp, sp);
}
} else if (descriptor->IsJSFunctionCall()) {
__ Prologue(this->info()->GeneratePreagedPrologue(), ip);
} else if (frame()->needs_frame()) {
if (!ABI_CALL_VIA_IP && info()->output_code_kind() == Code::WASM_FUNCTION) {
// TODO(mbrandy): Restrict only to the wasm wrapper case.
__ StubPrologue();
if (frame()->needs_frame()) {
if (descriptor->IsCFunctionCall()) {
__ function_descriptor();
__ mflr(r0);
if (FLAG_enable_embedded_constant_pool) {
__ Push(r0, fp, kConstantPoolRegister);
// Adjust FP to point to saved FP.
__ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
} else {
__ Push(r0, fp);
__ mr(fp, sp);
}
} else if (descriptor->IsJSFunctionCall()) {
__ Prologue(this->info()->GeneratePreagedPrologue(), ip);
} else {
__ StubPrologue(ip);
StackFrame::Type type = info()->GetOutputStackFrameType();
if (!ABI_CALL_VIA_IP &&
info()->output_code_kind() == Code::WASM_FUNCTION) {
// TODO(mbrandy): Restrict only to the wasm wrapper case.
__ StubPrologue(type);
} else {
__ StubPrologue(type, ip);
}
}
} else {
frame()->SetElidedFrameSizeInSlots(0);
......
......@@ -123,7 +123,7 @@ bool LCodeGen::GeneratePrologue() {
info()->set_prologue_offset(prologue_offset);
if (NeedsEagerFrame()) {
if (info()->IsStub()) {
__ StubPrologue(ip, prologue_offset);
__ StubPrologue(StackFrame::STUB, ip, prologue_offset);
} else {
__ Prologue(info()->GeneratePreagedPrologue(), ip, prologue_offset);
}
......@@ -265,15 +265,14 @@ bool LCodeGen::GenerateDeferredCode() {
DCHECK(info()->IsStub());
frame_is_built_ = true;
__ LoadSmiLiteral(scratch0(), Smi::FromInt(StackFrame::STUB));
__ PushFixedFrame(scratch0());
__ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ PushCommonFrame(scratch0());
Comment(";;; Deferred code");
}
code->Generate();
if (NeedsDeferredFrame()) {
Comment(";;; Destroy frame");
DCHECK(frame_is_built_);
__ PopFixedFrame(ip);
__ PopCommonFrame(scratch0());
frame_is_built_ = false;
}
__ b(code->exit());
......@@ -322,7 +321,7 @@ bool LCodeGen::GenerateJumpTable() {
if (table_entry->needs_frame) {
DCHECK(!info()->saves_caller_doubles());
Comment(";;; call deopt with frame");
__ PushFixedFrame();
__ PushCommonFrame();
__ b(&needs_frame, SetLK);
} else {
__ b(&call_deopt_entry, SetLK);
......@@ -336,10 +335,9 @@ bool LCodeGen::GenerateJumpTable() {
// This variant of deopt can only be used with stubs. Since we don't
// have a function pointer to install in the stack frame that we're
// building, install a special marker there instead.
DCHECK(info()->IsStub());
__ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::STUB));
__ push(ip);
__ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
DCHECK(info()->IsStub());
}
Comment(";;; call deopt");
......@@ -3211,8 +3209,9 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
} else {
// Check if the calling frame is an arguments adaptor frame.
__ LoadP(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ LoadP(result,
MemOperand(scratch, StandardFrameConstants::kContextOffset));
__ LoadP(
result,
MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
// Result is the frame pointer for the frame if not adapted and for the real
......
......@@ -121,8 +121,7 @@ void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
// Load the function pointer off of our current stack frame.
__ LoadP(r4, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset -
kPointerSize));
__ LoadP(r4, MemOperand(fp, FrameDropperFrameConstants::kFunctionOffset));
// Pop return address and frame
__ LeaveFrame(StackFrame::INTERNAL);
......
......@@ -1899,9 +1899,7 @@ void FullCodeGenerator::EmitGeneratorResume(
// fp = caller's frame pointer.
// cp = callee's context,
// r7 = callee's JS function.
__ PushFixedFrame(r7);
// Adjust FP to point to saved FP.
__ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ PushStandardFrame(r7);
// Load the operand stack size.
__ LoadP(r6, FieldMemOperand(r4, JSGeneratorObject::kOperandStackOffset));
......
......@@ -28,6 +28,9 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(cp);
if (accessor_index >= 0) {
DCHECK(!holder.is(scratch));
DCHECK(!receiver.is(scratch));
......@@ -51,7 +54,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
}
// Restore context register.
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ pop(cp);
}
__ Ret();
}
......@@ -66,8 +69,9 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
// Save context register
// Save value register, so we can restore it later.
__ push(value());
__ Push(cp, value());
if (accessor_index >= 0) {
DCHECK(!holder.is(scratch));
......@@ -93,10 +97,8 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
}
// We have to return the passed value, not the return value of the setter.
__ pop(r3);
// Restore context register.
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ Pop(cp, r3);
}
__ Ret();
}
......
......@@ -532,6 +532,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// -- r4 : constructor function
// -- r5 : allocation site or undefined
// -- r6 : new target
// -- cp : context
// -- lr : return address
// -- sp[...]: constructor arguments
// -----------------------------------
......@@ -547,11 +548,11 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
if (!create_implicit_receiver) {
__ SmiTag(r7, r3, SetRC);
__ Push(r5, r7);
__ Push(cp, r5, r7);
__ PushRoot(Heap::kTheHoleValueRootIndex);
} else {
__ SmiTag(r3);
__ Push(r5, r3);
__ Push(cp, r5, r3);
// Allocate the new receiver object.
__ Push(r4, r6);
......@@ -623,7 +624,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// r3: result
// sp[0]: receiver
// sp[1]: number of arguments (smi-tagged)
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
if (create_implicit_receiver) {
// If the result is an object (in the ECMA sense), we should get rid
......@@ -754,9 +755,6 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// r0,r8-r9, cp may be clobbered
ProfileEntryHookStub::MaybeCallEntryHook(masm);
// Clear the context before we push it when entering the internal frame.
__ li(cp, Operand::Zero());
// Enter an internal frame.
{
FrameScope scope(masm, StackFrame::INTERNAL);
......@@ -853,8 +851,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// MANUAL indicates that the scope shouldn't actually generate code to set up
// the frame (that is done below).
FrameScope frame_scope(masm, StackFrame::MANUAL);
__ PushFixedFrame(r4);
__ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ PushStandardFrame(r4);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
......@@ -1208,8 +1205,7 @@ void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
__ mr(ip, r3);
// Perform prologue operations usually performed by the young code stub.
__ PushFixedFrame(r4);
__ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ PushStandardFrame(r4);
// Jump to point after the code-age stub.
__ addi(r3, ip, Operand(kNoCodeAgeSequenceLength));
......@@ -1982,7 +1978,8 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
__ LoadP(scratch3, MemOperand(fp, StandardFrameConstants::kMarkerOffset));
__ LoadP(scratch3,
MemOperand(fp, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(scratch3, Smi::FromInt(StackFrame::STUB), r0);
__ bne(&no_interpreter_frame);
__ LoadP(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
......@@ -1993,8 +1990,9 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
Register caller_args_count_reg = scratch1;
Label no_arguments_adaptor, formal_parameter_count_loaded;
__ LoadP(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ LoadP(scratch3,
MemOperand(scratch2, StandardFrameConstants::kContextOffset));
__ LoadP(
scratch3,
MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(scratch3, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
__ bne(&no_arguments_adaptor);
......@@ -2007,7 +2005,8 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
__ bind(&no_arguments_adaptor);
// Load caller's formal parameter count
__ LoadP(scratch1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ LoadP(scratch1,
MemOperand(fp, ArgumentsAdaptorFrameConstants::kFunctionOffset));
__ LoadP(scratch1,
FieldMemOperand(scratch1, JSFunction::kSharedFunctionInfoOffset));
__ LoadWordArith(
......
......@@ -3813,7 +3813,7 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
CEntryStub ces(isolate(), 1, kSaveFPRegs);
__ Call(ces.GetCode(), RelocInfo::CODE_TARGET);
int parameter_count_offset =
StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
StubFailureTrampolineFrameConstants::kArgumentsLengthOffset;
__ LoadP(r4, MemOperand(fp, parameter_count_offset));
if (function_mode() == JS_FUNCTION_STUB_MODE) {
__ addi(r4, r4, Operand(1));
......@@ -4825,7 +4825,7 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
__ bind(&loop);
__ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
__ bind(&loop_entry);
__ LoadP(ip, MemOperand(r5, StandardFrameConstants::kMarkerOffset));
__ LoadP(ip, MemOperand(r5, StandardFrameConstants::kFunctionOffset));
__ cmp(ip, r4);
__ bne(&loop);
}
......@@ -4834,7 +4834,7 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
// arguments adaptor frame below the function frame).
Label no_rest_parameters;
__ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
__ LoadP(ip, MemOperand(r5, StandardFrameConstants::kContextOffset));
__ LoadP(ip, MemOperand(r5, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
__ bne(&no_rest_parameters);
......@@ -4979,7 +4979,7 @@ void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) {
// Check if the calling frame is an arguments adaptor frame.
Label adaptor_frame, try_allocate, runtime;
__ LoadP(r7, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ LoadP(r3, MemOperand(r7, StandardFrameConstants::kContextOffset));
__ LoadP(r3, MemOperand(r7, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(r3, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
__ beq(&adaptor_frame);
......@@ -5221,7 +5221,7 @@ void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
__ bind(&loop);
__ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
__ bind(&loop_entry);
__ LoadP(ip, MemOperand(r5, StandardFrameConstants::kMarkerOffset));
__ LoadP(ip, MemOperand(r5, StandardFrameConstants::kFunctionOffset));
__ cmp(ip, r4);
__ bne(&loop);
}
......@@ -5229,7 +5229,7 @@ void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
// Check if we have an arguments adaptor frame below the function frame.
Label arguments_adaptor, arguments_done;
__ LoadP(r6, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
__ LoadP(ip, MemOperand(r6, StandardFrameConstants::kContextOffset));
__ LoadP(ip, MemOperand(r6, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
__ beq(&arguments_adaptor);
{
......
......@@ -616,9 +616,7 @@ CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {
young_sequence_.length() / Assembler::kInstrSize,
CodePatcher::DONT_FLUSH));
PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length());
patcher->masm()->PushFixedFrame(r4);
patcher->masm()->addi(fp, sp,
Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
patcher->masm()->PushStandardFrame(r4);
for (int i = 0; i < kNoCodeAgeSequenceNops; i++) {
patcher->masm()->nop();
}
......
......@@ -162,7 +162,12 @@ void Deoptimizer::TableEntryGenerator::Generate() {
// Allocate a new deoptimizer object.
// Pass six arguments in r3 to r8.
__ PrepareCallCFunction(6, r8);
__ li(r3, Operand::Zero());
Label context_check;
__ LoadP(r4, MemOperand(fp, CommonFrameConstants::kContextOrFrameTypeOffset));
__ JumpIfSmi(r4, &context_check);
__ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ bind(&context_check);
__ li(r4, Operand(type())); // bailout type,
// r5: bailout id already loaded.
// r6: code address or 0 already loaded.
......
......@@ -152,16 +152,11 @@ class EntryFrameConstants : public AllStatic {
-(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize);
};
class ExitFrameConstants : public AllStatic {
class ExitFrameConstants : public TypedFrameConstants {
public:
static const int kFrameSize =
FLAG_enable_embedded_constant_pool ? 3 * kPointerSize : 2 * kPointerSize;
static const int kConstantPoolOffset =
FLAG_enable_embedded_constant_pool ? -3 * kPointerSize : 0;
static const int kCodeOffset = -2 * kPointerSize;
static const int kSPOffset = -1 * kPointerSize;
static const int kSPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
static const int kCodeOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
DEFINE_TYPED_FRAME_SIZES(2);
// The caller fields are below the frame pointer on the stack.
static const int kCallerFPOffset = 0 * kPointerSize;
......@@ -179,7 +174,7 @@ class JavaScriptFrameConstants : public AllStatic {
// FP-relative.
static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset;
static const int kLastParameterOffset = +2 * kPointerSize;
static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
static const int kFunctionOffset = StandardFrameConstants::kFunctionOffset;
// Caller SP-relative.
static const int kParam0Offset = -2 * kPointerSize;
......
......@@ -591,42 +591,69 @@ void MacroAssembler::RememberedSetHelper(Register object, // For debug tests.
}
}
void MacroAssembler::PushFixedFrame(Register marker_reg) {
void MacroAssembler::PushCommonFrame(Register marker_reg) {
int fp_delta = 0;
mflr(r0);
if (FLAG_enable_embedded_constant_pool) {
if (marker_reg.is_valid()) {
Push(r0, fp, kConstantPoolRegister, cp, marker_reg);
Push(r0, fp, kConstantPoolRegister, marker_reg);
fp_delta = 2;
} else {
Push(r0, fp, kConstantPoolRegister, cp);
Push(r0, fp, kConstantPoolRegister);
fp_delta = 1;
}
} else {
if (marker_reg.is_valid()) {
Push(r0, fp, cp, marker_reg);
Push(r0, fp, marker_reg);
fp_delta = 1;
} else {
Push(r0, fp, cp);
Push(r0, fp);
fp_delta = 0;
}
}
addi(fp, sp, Operand(fp_delta * kPointerSize));
}
void MacroAssembler::PopFixedFrame(Register marker_reg) {
void MacroAssembler::PopCommonFrame(Register marker_reg) {
if (FLAG_enable_embedded_constant_pool) {
if (marker_reg.is_valid()) {
Pop(r0, fp, kConstantPoolRegister, cp, marker_reg);
Pop(r0, fp, kConstantPoolRegister, marker_reg);
} else {
Pop(r0, fp, kConstantPoolRegister, cp);
Pop(r0, fp, kConstantPoolRegister);
}
} else {
if (marker_reg.is_valid()) {
Pop(r0, fp, cp, marker_reg);
Pop(r0, fp, marker_reg);
} else {
Pop(r0, fp, cp);
Pop(r0, fp);
}
}
mtlr(r0);
}
void MacroAssembler::PushStandardFrame(Register function_reg) {
int fp_delta = 0;
mflr(r0);
if (FLAG_enable_embedded_constant_pool) {
if (function_reg.is_valid()) {
Push(r0, fp, kConstantPoolRegister, cp, function_reg);
fp_delta = 3;
} else {
Push(r0, fp, kConstantPoolRegister, cp);
fp_delta = 2;
}
} else {
if (function_reg.is_valid()) {
Push(r0, fp, cp, function_reg);
fp_delta = 2;
} else {
Push(r0, fp, cp);
fp_delta = 1;
}
}
addi(fp, sp, Operand(fp_delta * kPointerSize));
}
void MacroAssembler::RestoreFrameStateForTailCall() {
if (FLAG_enable_embedded_constant_pool) {
LoadP(kConstantPoolRegister,
......@@ -870,12 +897,10 @@ void MacroAssembler::LoadConstantPoolPointerRegister() {
mov_label_addr(kConstantPoolRegister, ConstantPoolPosition());
}
void MacroAssembler::StubPrologue(Register base, int prologue_offset) {
LoadSmiLiteral(r11, Smi::FromInt(StackFrame::STUB));
PushFixedFrame(r11);
// Adjust FP to point to saved FP.
addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
void MacroAssembler::StubPrologue(StackFrame::Type type, Register base,
int prologue_offset) {
LoadSmiLiteral(r11, Smi::FromInt(type));
PushCommonFrame(r11);
if (FLAG_enable_embedded_constant_pool) {
if (!base.is(no_reg)) {
// base contains prologue address
......@@ -911,9 +936,7 @@ void MacroAssembler::Prologue(bool code_pre_aging, Register base,
}
} else {
// This matches the code found in GetNoCodeAgeSequence()
PushFixedFrame(r4);
// Adjust fp to point to saved fp.
addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
PushStandardFrame(r4);
for (int i = 0; i < kNoCodeAgeSequenceNops; i++) {
nop();
}
......@@ -938,20 +961,20 @@ void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
void MacroAssembler::EnterFrame(StackFrame::Type type,
bool load_constant_pool_pointer_reg) {
if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) {
PushFixedFrame();
// This path should not rely on ip containing code entry.
// Push type explicitly so we can leverage the constant pool.
// This path cannot rely on ip containing code entry.
PushCommonFrame();
LoadConstantPoolPointerRegister();
LoadSmiLiteral(ip, Smi::FromInt(type));
push(ip);
} else {
LoadSmiLiteral(ip, Smi::FromInt(type));
PushFixedFrame(ip);
PushCommonFrame(ip);
}
if (type == StackFrame::INTERNAL) {
mov(r0, Operand(CodeObject()));
push(r0);
}
// Adjust FP to point to saved FP.
addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
mov(r0, Operand(CodeObject()));
push(r0);
}
......@@ -967,11 +990,8 @@ int MacroAssembler::LeaveFrame(StackFrame::Type type, int stack_adjustment) {
LoadP(r0, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
LoadP(ip, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
if (FLAG_enable_embedded_constant_pool) {
const int exitOffset = ExitFrameConstants::kConstantPoolOffset;
const int standardOffset = StandardFrameConstants::kConstantPoolOffset;
const int offset =
((type == StackFrame::EXIT) ? exitOffset : standardOffset);
LoadP(kConstantPoolRegister, MemOperand(fp, offset));
LoadP(kConstantPoolRegister,
MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
}
mtlr(r0);
frame_ends = pc_offset();
......@@ -1008,12 +1028,10 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
// all of the pushes that have happened inside of V8
// since we were called from C code
// replicate ARM frame - TODO make this more closely follow PPC ABI
mflr(r0);
Push(r0, fp);
mr(fp, sp);
LoadSmiLiteral(ip, Smi::FromInt(StackFrame::EXIT));
PushCommonFrame(ip);
// Reserve room for saved entry sp and code object.
subi(sp, sp, Operand(ExitFrameConstants::kFrameSize));
subi(sp, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp));
if (emit_debug_code()) {
li(r8, Operand::Zero());
......@@ -1098,7 +1116,7 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
// Calculate the stack location of the saved doubles and restore them.
const int kNumRegs = kNumCallerSavedDoubles;
const int offset =
(ExitFrameConstants::kFrameSize + kNumRegs * kDoubleSize);
(ExitFrameConstants::kFixedFrameSizeFromFp + kNumRegs * kDoubleSize);
addi(r6, fp, Operand(-offset));
MultiPopDoubles(kCallerSavedDoubles, r6);
}
......@@ -1477,8 +1495,20 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
DCHECK(!holder_reg.is(ip));
DCHECK(!scratch.is(ip));
// Load current lexical context from the stack frame.
LoadP(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Load current lexical context from the active StandardFrame, which
// may require crawling past STUB frames.
Label load_context;
Label has_context;
DCHECK(!ip.is(scratch));
mr(ip, fp);
bind(&load_context);
LoadP(scratch,
MemOperand(ip, CommonFrameConstants::kContextOrFrameTypeOffset));
JumpIfNotSmi(scratch, &has_context);
LoadP(ip, MemOperand(ip, CommonFrameConstants::kCallerFPOffset));
b(&load_context);
bind(&has_context);
// In debug mode, make sure the lexical context is set.
#ifdef DEBUG
cmpi(scratch, Operand::Zero());
......
......@@ -338,10 +338,14 @@ class MacroAssembler : public Assembler {
addi(sp, sp, Operand(5 * kPointerSize));
}
// Push a fixed frame, consisting of lr, fp, context and
// JS function / marker id if marker_reg is a valid register.
void PushFixedFrame(Register marker_reg = no_reg);
void PopFixedFrame(Register marker_reg = no_reg);
// Push a fixed frame, consisting of lr, fp, constant pool.
void PushCommonFrame(Register marker_reg = no_reg);
// Push a standard frame, consisting of lr, fp, constant pool,
// context and JS function
void PushStandardFrame(Register function_reg);
void PopCommonFrame(Register marker_reg = no_reg);
// Restore caller's frame pointer and return address prior to being
// overwritten by tail call stack preparation.
......@@ -418,7 +422,8 @@ class MacroAssembler : public Assembler {
#endif
// Generates function and stub prologue code.
void StubPrologue(Register base = no_reg, int prologue_offset = 0);
void StubPrologue(StackFrame::Type type, Register base = no_reg,
int prologue_offset = 0);
void Prologue(bool code_pre_aging, Register base, int prologue_offset = 0);
// Enter exit frame.
......
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