Chromium Code Reviews| Index: src/codegen-ia32.cc |
| =================================================================== |
| --- src/codegen-ia32.cc (revision 485) |
| +++ src/codegen-ia32.cc (working copy) |
| @@ -1179,7 +1179,11 @@ |
| __ mov(edx, Operand(eax)); |
| __ mov(Operand(eax), Immediate(Smi::FromInt(value_))); |
| __ CallStub(&stub); |
| - __ cmp(eax, 0); |
| + if (cc_ == equal) { |
| + __ test(eax, Operand(eax)); |
| + } else { |
| + __ cmp(eax, 0); |
| + } |
| // "result" is returned in the flags |
| } |
| @@ -1207,26 +1211,29 @@ |
| class CallFunctionStub: public CodeStub { |
| public: |
| - explicit CallFunctionStub(int argc) : argc_(argc) { } |
| + explicit CallFunctionStub(int argc, bool call_constructor) |
| + : argc_(argc), call_constructor_(call_constructor) { } |
| void Generate(MacroAssembler* masm); |
| private: |
| int argc_; |
| + bool call_constructor_; |
| #ifdef DEBUG |
| void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } |
| #endif |
| Major MajorKey() { return CallFunction; } |
| - int MinorKey() { return argc_; } |
| + int MinorKey() { return (argc_ << 1) | (call_constructor_ ? 1 : 0); } |
| }; |
| // Call the function just below TOS on the stack with the given |
| // arguments. The receiver is the TOS. |
| void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
| - int position) { |
| + bool call_constructor, |
|
iposva
2008/10/10 13:56:18
Please change the bool parameter to an enum {FUNCT
|
| + int position) { |
| // Push the arguments ("left-to-right") on the stack. |
| for (int i = 0; i < args->length(); i++) { |
| Load(args->at(i)); |
| @@ -1236,8 +1243,11 @@ |
| __ RecordPosition(position); |
| // Use the shared code stub to call the function. |
| - CallFunctionStub call_function(args->length()); |
| - __ CallStub(&call_function); |
| + CallFunctionStub call_function(args->length(), call_constructor); |
| + RelocInfo::Mode mode = call_constructor |
| + ? RelocInfo::CONSTRUCT_CALL |
| + : RelocInfo::CODE_TARGET; |
| + __ CallStub(&call_function, mode); |
| // Restore context and pop function from the stack. |
| __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| @@ -2597,7 +2607,7 @@ |
| __ push(edx); |
| // Call the function. |
| - CallWithArguments(args, node->position()); |
| + CallWithArguments(args, false, node->position()); |
| } else if (property != NULL) { |
| // Check if the key is a literal string. |
| @@ -2638,7 +2648,7 @@ |
| __ push(Operand(esp, ref.size() * kPointerSize)); |
| // Call the function. |
| - CallWithArguments(args, node->position()); |
| + CallWithArguments(args, false, node->position()); |
| } |
| } else { |
| @@ -2653,7 +2663,7 @@ |
| LoadGlobal(); |
| // Call the function. |
| - CallWithArguments(args, node->position()); |
| + CallWithArguments(args, false, node->position()); |
| } |
| } |
| @@ -2672,25 +2682,7 @@ |
| Load(node->expression()); |
| LoadGlobal(); |
| - // Push the arguments ("left-to-right") on the stack. |
| - ZoneList<Expression*>* args = node->arguments(); |
| - for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
| - |
| - // Constructors are called with the number of arguments in register |
| - // eax for now. Another option would be to have separate construct |
| - // call trampolines per different arguments counts encountered. |
| - __ Set(eax, Immediate(args->length())); |
| - |
| - // Load the function into temporary function slot as per calling |
| - // convention. |
| - __ mov(edi, Operand(esp, (args->length() + 1) * kPointerSize)); |
| - |
| - // Call the construct call builtin that handles allocation and |
| - // constructor invocation. |
| - __ RecordPosition(node->position()); |
| - __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), |
| - RelocInfo::CONSTRUCT_CALL); |
| - __ mov(TOS, eax); // discard the function and "push" the newly created object |
| + CallWithArguments(node->arguments(), true, node->position()); |
|
iposva
2008/10/10 13:56:18
Nice refactoring!
|
| } |
| @@ -4653,16 +4645,34 @@ |
| __ j(not_equal, &slow, not_taken); |
| // Fast-case: Just invoke the function. |
| - ParameterCount actual(argc_); |
| - __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
| + if (call_constructor_) { |
| + __ Set(eax, Immediate(argc_)); |
| + __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| + __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| + __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kConstructorOffset)); |
| + __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); |
| + __ jmp(Operand(edx)); |
| + } else { |
| + ParameterCount actual(argc_); |
| + __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
| + } |
| // Slow-case: Non-function called. |
| __ bind(&slow); |
| - __ Set(eax, Immediate(argc_)); |
| - __ Set(ebx, Immediate(0)); |
| - __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
| - Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
| - __ jmp(adaptor, RelocInfo::CODE_TARGET); |
| + if (call_constructor_) { |
| + // Get rid of the arguments and the receiver and call the NewObject |
| + // runtime function to generate and throw an exception. |
| + __ pop(ecx); |
| + __ add(Operand(esp), Immediate((argc_ + 1) * kPointerSize)); |
| + __ push(ecx); |
| + __ TailCallRuntime(ExternalReference(Runtime::kNewObject), 1); |
| + } else { |
| + __ Set(eax, Immediate(argc_)); |
| + __ Set(ebx, Immediate(0)); |
| + __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
| + Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
| + __ jmp(adaptor, RelocInfo::CODE_TARGET); |
| + } |
| } |