From 892b0cac3c686cc452440dcb30f392e916e2dbf0 Mon Sep 17 00:00:00 2001 From: "kasperl@chromium.org" Date: Mon, 6 Oct 2008 11:04:03 +0000 Subject: [PATCH] Refactor the arguments access code to make it easier to read. Review URL: http://codereview.chromium.org/6491 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@442 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/codegen-arm.cc | 156 +++++++++++++++++++++----------------------- src/codegen-ia32.cc | 150 ++++++++++++++++++++++-------------------- src/codegen.cc | 9 +++ src/codegen.h | 4 ++ 4 files changed, 169 insertions(+), 150 deletions(-) diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc index 89fc0db7c1..5eb11bee7d 100644 --- a/src/codegen-arm.cc +++ b/src/codegen-arm.cc @@ -4403,102 +4403,96 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { } -void ArgumentsAccessStub::Generate(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- r0: formal number of parameters for the calling function - // -- r1: key (if value access) - // -- lr: return address - // ----------------------------------- - - // If we're reading an element we need to check that the key is a smi. - Label slow; - if (type_ == READ_ELEMENT) { - __ tst(r1, Operand(kSmiTagMask)); - __ b(ne, &slow); - } - +void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { // Check if the calling frame is an arguments adaptor frame. - // r0: formal number of parameters - // r1: key (if access) Label adaptor; __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL)); - if (type_ == NEW_OBJECT) { - __ b(ne, &slow); - } else { - __ b(eq, &adaptor); - } + __ b(eq, &adaptor); - static const int kParamDisplacement = + // Nothing to do: The formal number of parameters has already been + // passed in register r0 by calling function. Just return it. + __ mov(pc, lr); + + // Arguments adaptor case: Read the arguments length from the + // adaptor frame and return it. + __ bind(&adaptor); + __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ mov(pc, lr); +} + + +void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { + // The displacement is the offset of the last parameter (if any) + // relative to the frame pointer. + static const int kDisplacement = StandardFrameConstants::kCallerSPOffset - kPointerSize; - if (type_ == READ_LENGTH) { - // Nothing to do: The formal number of parameters has already been - // passed in register r0 by calling function. Just return it. - __ mov(pc, lr); - } else if (type_ == READ_ELEMENT) { - // Check index against formal parameter count. Use unsigned comparison to - // get the negative check for free. - // r0: formal number of parameters - // r1: index - __ cmp(r1, r0); - __ b(cs, &slow); + // Check that the key is a smi. + Label slow; + __ tst(r1, Operand(kSmiTagMask)); + __ b(ne, &slow); - // Read the argument from the current frame and return it. - __ sub(r3, r0, r1); - __ add(r3, fp, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); - __ ldr(r0, MemOperand(r3, kParamDisplacement)); - __ mov(pc, lr); - } else { - ASSERT(type_ == NEW_OBJECT); - // Do nothing here. - } + // Check if the calling frame is an arguments adaptor frame. + Label adaptor; + __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); + __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); + __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL)); + __ b(eq, &adaptor); - // An arguments adaptor frame is present. Find the length or the actual - // argument in the calling frame. - // r0: formal number of parameters - // r1: key - // r2: adaptor frame pointer + // Check index against formal parameters count limit passed in + // through register eax. Use unsigned comparison to get negative + // check for free. + __ cmp(r1, r0); + __ b(cs, &slow); + + // Read the argument from the stack and return it. + __ sub(r3, r0, r1); + __ add(r3, fp, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); + __ ldr(r0, MemOperand(r3, kDisplacement)); + __ mov(pc, lr); + + // Arguments adaptor case: Check index against actual arguments + // limit found in the arguments adaptor frame. Use unsigned + // comparison to get negative check for free. __ bind(&adaptor); - // Read the arguments length from the adaptor frame. This is the result if - // only accessing the length, otherwise it is used in accessing the value __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ cmp(r1, r0); + __ b(cs, &slow); - if (type_ == READ_LENGTH) { - // Return the length in r0. - __ mov(pc, lr); - } else if (type_ == READ_ELEMENT) { - // Check index against actual arguments count. Use unsigned comparison to - // get the negative check for free. - // r0: actual number of parameter - // r1: index - // r2: adaptor frame point - __ cmp(r1, r0); - __ b(cs, &slow); + // Read the argument from the adaptor frame and return it. + __ sub(r3, r0, r1); + __ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); + __ ldr(r0, MemOperand(r3, kDisplacement)); + __ mov(pc, lr); - // Read the argument from the adaptor frame and return it. - __ sub(r3, r0, r1); - __ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); - __ ldr(r0, MemOperand(r3, kParamDisplacement)); - __ mov(pc, lr); - } else { - ASSERT(type_ == NEW_OBJECT); - // Patch the arguments.length and the parameters pointer. - __ str(r0, MemOperand(sp, 0 * kPointerSize)); - __ add(r3, r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); - __ add(r3, r3, Operand(kParamDisplacement + 1 * kPointerSize)); - __ str(r3, MemOperand(sp, 1 * kPointerSize)); - __ bind(&slow); - __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); - } + // Slow-case: Handle non-smi or out-of-bounds access to arguments + // by calling the runtime system. + __ bind(&slow); + __ push(r1); + __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); +} - // Return to the calling function. - if (type_ == READ_ELEMENT) { - __ bind(&slow); - __ push(r1); - __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); - } + +void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { + // Check if the calling frame is an arguments adaptor frame. + Label runtime; + __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); + __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); + __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL)); + __ b(ne, &runtime); + + // Patch the arguments.length and the parameters pointer. + __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ str(r0, MemOperand(sp, 0 * kPointerSize)); + __ add(r3, r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); + __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); + __ str(r3, MemOperand(sp, 1 * kPointerSize)); + + // Do the runtime call to allocate the arguments object. + __ bind(&runtime); + __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); } diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc index 9f97626b22..4332d41bea 100644 --- a/src/codegen-ia32.cc +++ b/src/codegen-ia32.cc @@ -4795,90 +4795,102 @@ void UnarySubStub::Generate(MacroAssembler* masm) { } -void ArgumentsAccessStub::Generate(MacroAssembler* masm) { - // If we're reading an element we need to check that the key is a smi. +void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { + // Check if the calling frame is an arguments adaptor frame. + Label adaptor; + __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); + __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); + __ cmp(ecx, ArgumentsAdaptorFrame::SENTINEL); + __ j(equal, &adaptor); + + // Nothing to do: The formal number of parameters has already been + // passed in register eax by calling function. Just return it. + __ ret(0); + + // Arguments adaptor case: Read the arguments length from the + // adaptor frame and return it. + __ bind(&adaptor); + __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ ret(0); +} + + +void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { + // The displacement is used for skipping the frame pointer on the + // stack. It is the offset of the last parameter (if any) relative + // to the frame pointer. + static const int kDisplacement = 1 * kPointerSize; + + // Check that the key is a smi. Label slow; - if (type_ == READ_ELEMENT) { - __ mov(ebx, Operand(esp, 1 * kPointerSize)); // skip return address - __ test(ebx, Immediate(kSmiTagMask)); - __ j(not_zero, &slow, not_taken); - } + __ mov(ebx, Operand(esp, 1 * kPointerSize)); // skip return address + __ test(ebx, Immediate(kSmiTagMask)); + __ j(not_zero, &slow, not_taken); // Check if the calling frame is an arguments adaptor frame. Label adaptor; __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); __ cmp(ecx, ArgumentsAdaptorFrame::SENTINEL); - if (type_ == NEW_OBJECT) { - __ j(not_equal, &slow); - } else { - __ j(equal, &adaptor); - } + __ j(equal, &adaptor); - // The displacement is used for skipping the return address on the - // stack. It is the offset of the last parameter (if any) relative - // to the frame pointer. - static const int kDisplacement = 1 * kPointerSize; + // Check index against formal parameters count limit passed in + // through register eax. Use unsigned comparison to get negative + // check for free. + __ cmp(ebx, Operand(eax)); + __ j(above_equal, &slow, not_taken); + + // Read the argument from the stack and return it. ASSERT(kSmiTagSize == 1 && kSmiTag == 0); // shifting code depends on this + __ lea(edx, Operand(ebp, eax, times_2, 0)); + __ neg(ebx); + __ mov(eax, Operand(edx, ebx, times_2, kDisplacement)); + __ ret(0); - if (type_ == READ_LENGTH) { - // Nothing to do: The formal number of parameters has already been - // passed in register eax by calling function. Just return it. - __ ret(0); - } else if (type_ == READ_ELEMENT) { - // Check index against formal parameters count limit passed in - // through register eax. Use unsigned comparison to get negative - // check for free. - __ cmp(ebx, Operand(eax)); - __ j(above_equal, &slow, not_taken); - - // Read the argument from the stack and return it. - __ lea(edx, Operand(ebp, eax, times_2, 0)); - __ neg(ebx); - __ mov(eax, Operand(edx, ebx, times_2, kDisplacement)); - __ ret(0); - } else { - ASSERT(type_ == NEW_OBJECT); - // Do nothing here. - } - - // Arguments adaptor case: Find the length or the actual argument in - // the calling frame. + // Arguments adaptor case: Check index against actual arguments + // limit found in the arguments adaptor frame. Use unsigned + // comparison to get negative check for free. __ bind(&adaptor); - if (type_ == READ_LENGTH) { - // Read the arguments length from the adaptor frame and return it. - __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); - __ ret(0); - } else if (type_ == READ_ELEMENT) { - // Check index against actual arguments limit found in the - // arguments adaptor frame. Use unsigned comparison to get - // negative check for free. - __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); - __ cmp(ebx, Operand(ecx)); - __ j(above_equal, &slow, not_taken); + __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ cmp(ebx, Operand(ecx)); + __ j(above_equal, &slow, not_taken); - // Read the argument from the stack and return it. - __ lea(edx, Operand(edx, ecx, times_2, 0)); - __ neg(ebx); - __ mov(eax, Operand(edx, ebx, times_2, kDisplacement)); - __ ret(0); - } else { - ASSERT(type_ == NEW_OBJECT); - // Patch the arguments.length and the parameters pointer. - __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); - __ mov(Operand(esp, 1 * kPointerSize), ecx); - __ lea(edx, Operand(edx, ecx, times_2, kDisplacement + 1 * kPointerSize)); - __ mov(Operand(esp, 2 * kPointerSize), edx); - __ bind(&slow); - __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); - } + // Read the argument from the stack and return it. + ASSERT(kSmiTagSize == 1 && kSmiTag == 0); // shifting code depends on this + __ lea(edx, Operand(edx, ecx, times_2, 0)); + __ neg(ebx); + __ mov(eax, Operand(edx, ebx, times_2, kDisplacement)); + __ ret(0); // Slow-case: Handle non-smi or out-of-bounds access to arguments // by calling the runtime system. - if (type_ == READ_ELEMENT) { - __ bind(&slow); - __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); - } + __ bind(&slow); + __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); +} + + +void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { + // The displacement is used for skipping the return address and the + // frame pointer on the stack. It is the offset of the last + // parameter (if any) relative to the frame pointer. + static const int kDisplacement = 2 * kPointerSize; + + // Check if the calling frame is an arguments adaptor frame. + Label runtime; + __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); + __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); + __ cmp(ecx, ArgumentsAdaptorFrame::SENTINEL); + __ j(not_equal, &runtime); + + // Patch the arguments.length and the parameters pointer. + __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ mov(Operand(esp, 1 * kPointerSize), ecx); + __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); + __ mov(Operand(esp, 2 * kPointerSize), edx); + + // Do the runtime call to allocate the arguments object. + __ bind(&runtime); + __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); } diff --git a/src/codegen.cc b/src/codegen.cc index 844d934b52..91d3686430 100644 --- a/src/codegen.cc +++ b/src/codegen.cc @@ -362,4 +362,13 @@ void RuntimeStub::Generate(MacroAssembler* masm) { } +void ArgumentsAccessStub::Generate(MacroAssembler* masm) { + switch (type_) { + case READ_LENGTH: GenerateReadLength(masm); break; + case READ_ELEMENT: GenerateReadElement(masm); break; + case NEW_OBJECT: GenerateNewObject(masm); break; + } +} + + } } // namespace v8::internal diff --git a/src/codegen.h b/src/codegen.h index 2367aefbcc..3e3c55c0d8 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -357,7 +357,11 @@ class ArgumentsAccessStub: public CodeStub { Major MajorKey() { return ArgumentsAccess; } int MinorKey() { return type_; } + void Generate(MacroAssembler* masm); + void GenerateReadLength(MacroAssembler* masm); + void GenerateReadElement(MacroAssembler* masm); + void GenerateNewObject(MacroAssembler* masm); const char* GetName() { return "ArgumentsAccessStub"; }