Refactor the arguments access code to make it easier to read.
authorkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 6 Oct 2008 11:04:03 +0000 (11:04 +0000)
committerkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 6 Oct 2008 11:04:03 +0000 (11:04 +0000)
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
src/codegen-ia32.cc
src/codegen.cc
src/codegen.h

index 89fc0db..5eb11be 100644 (file)
@@ -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);
+
+  // 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);
+}
 
-  static const int kParamDisplacement =
+
+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);
-
-    // 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 that the key is a smi.
+  Label slow;
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(ne, &slow);
+
+  // 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);
+
+  // 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);
 
-  // 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
+  // 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, 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);
-  }
+  // 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);
 
-  // Return to the calling function.
-  if (type_ == READ_ELEMENT) {
-    __ bind(&slow);
-    __ push(r1);
-    __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1);
-  }
+  // 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);
+}
+
+
+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);
 }
 
 
index 9f97626..4332d41 100644 (file)
@@ -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.
-  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);
-  }
-
+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);
-  if (type_ == NEW_OBJECT) {
-    __ j(not_equal, &slow);
-  } else {
-    __ j(equal, &adaptor);
-  }
+  __ 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);
+}
 
-  // The displacement is used for skipping the return address on the
+
+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;
-  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);  // shifting code depends on this
 
-  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.
-  }
+  // Check that the key is a smi.
+  Label slow;
+  __ 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);
+  __ j(equal, &adaptor);
 
-  // Arguments adaptor case: Find the length or the actual argument in
-  // the calling frame.
+  // 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);
+
+  // 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);
-
-    // 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);
-  }
+  __ 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.
+  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);
 }
 
 
index 844d934..91d3686 100644 (file)
@@ -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
index 2367aef..3e3c55c 100644 (file)
@@ -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"; }