| Index: src/codegen-ia32.cc
|
| ===================================================================
|
| --- src/codegen-ia32.cc (revision 433)
|
| +++ src/codegen-ia32.cc (working copy)
|
| @@ -518,7 +518,6 @@
|
| // edi: caller's parameter pointer
|
| // esi: callee's context
|
|
|
| -
|
| void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) {
|
| // Record the position for debugging purposes.
|
| __ RecordPosition(fun->start_position());
|
| @@ -565,8 +564,12 @@
|
| if (scope->arguments() != NULL) {
|
| ASSERT(scope->arguments_shadow() != NULL);
|
| Comment cmnt(masm_, "[ allocate arguments object");
|
| + ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
|
| + __ lea(eax, ReceiverOperand());
|
| __ push(FunctionOperand());
|
| - __ CallRuntime(Runtime::kNewArguments, 1);
|
| + __ push(eax);
|
| + __ push(Immediate(Smi::FromInt(scope->num_parameters())));
|
| + __ CallStub(&stub);
|
| __ mov(ecx, Operand(eax));
|
| arguments_object_allocated = true;
|
| }
|
| @@ -1068,28 +1071,6 @@
|
| }
|
|
|
|
|
| -class ArgumentsAccessStub: public CodeStub {
|
| - public:
|
| - explicit ArgumentsAccessStub(bool is_length) : is_length_(is_length) { }
|
| -
|
| - private:
|
| - bool is_length_;
|
| -
|
| - Major MajorKey() { return ArgumentsAccess; }
|
| - int MinorKey() { return is_length_ ? 1 : 0; }
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - const char* GetName() { return "ArgumentsAccessStub"; }
|
| -
|
| -#ifdef DEBUG
|
| - void Print() {
|
| - PrintF("ArgumentsAccessStub (is_length %s)\n",
|
| - is_length_ ? "true" : "false");
|
| - }
|
| -#endif
|
| -};
|
| -
|
| -
|
| void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op,
|
| OverwriteMode overwrite_mode) {
|
| Comment cmnt(masm_, "[ BinaryOperation");
|
| @@ -3313,7 +3294,7 @@
|
| __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
|
|
|
| // Call the shared stub to get to the arguments.length.
|
| - ArgumentsAccessStub stub(true);
|
| + ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
|
| __ CallStub(&stub);
|
| __ push(eax);
|
| }
|
| @@ -3376,7 +3357,7 @@
|
| __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
|
|
|
| // Call the shared stub to get to arguments[key].
|
| - ArgumentsAccessStub stub(false);
|
| + ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
|
| __ CallStub(&stub);
|
| __ mov(TOS, eax);
|
| }
|
| @@ -4815,9 +4796,9 @@
|
|
|
|
|
| void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
|
| - // Check that the key is a smi for non-length access.
|
| + // If we're reading an element we need to check that the key is a smi.
|
| Label slow;
|
| - if (!is_length_) {
|
| + if (type_ == READ_ELEMENT) {
|
| __ mov(ebx, Operand(esp, 1 * kPointerSize)); // skip return address
|
| __ test(ebx, Immediate(kSmiTagMask));
|
| __ j(not_zero, &slow, not_taken);
|
| @@ -4828,7 +4809,11 @@
|
| __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
|
| __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
|
| __ cmp(ecx, ArgumentsAdaptorFrame::SENTINEL);
|
| - __ j(equal, &adaptor);
|
| + if (type_ == NEW_OBJECT) {
|
| + __ j(not_equal, &slow);
|
| + } else {
|
| + __ 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
|
| @@ -4836,31 +4821,35 @@
|
| static const int kDisplacement = 1 * kPointerSize;
|
| ASSERT(kSmiTagSize == 1 && kSmiTag == 0); // shifting code depends on this
|
|
|
| - if (is_length_) {
|
| - // Do nothing. The length is already in register eax.
|
| - } else {
|
| + 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.
|
| + // 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.
|
| }
|
|
|
| - // Return the length or the argument.
|
| - __ ret(0);
|
| -
|
| // Arguments adaptor case: Find the length or the actual argument in
|
| // the calling frame.
|
| __ bind(&adaptor);
|
| - if (is_length_) {
|
| - // Read the arguments length from the adaptor frame.
|
| + if (type_ == READ_LENGTH) {
|
| + // Read the arguments length from the adaptor frame and return it.
|
| __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
| - } else {
|
| + __ 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.
|
| @@ -4868,18 +4857,25 @@
|
| __ cmp(ebx, Operand(ecx));
|
| __ j(above_equal, &slow, not_taken);
|
|
|
| - // Read the argument from the stack.
|
| + // 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);
|
| }
|
|
|
| - // Return the length or the argument.
|
| - __ ret(0);
|
| -
|
| // Slow-case: Handle non-smi or out-of-bounds access to arguments
|
| // by calling the runtime system.
|
| - if (!is_length_) {
|
| + if (type_ == READ_ELEMENT) {
|
| __ bind(&slow);
|
| __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1);
|
| }
|
|
|