OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2282 left_side.Unuse(); | 2282 left_side.Unuse(); |
2283 dest->Split(cc); | 2283 dest->Split(cc); |
2284 } | 2284 } |
2285 } | 2285 } |
2286 } | 2286 } |
2287 | 2287 |
2288 | 2288 |
2289 // Call the function just below TOS on the stack with the given | 2289 // Call the function just below TOS on the stack with the given |
2290 // arguments. The receiver is the TOS. | 2290 // arguments. The receiver is the TOS. |
2291 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, | 2291 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
| 2292 CallFunctionFlags flags, |
2292 int position) { | 2293 int position) { |
2293 // Push the arguments ("left-to-right") on the stack. | 2294 // Push the arguments ("left-to-right") on the stack. |
2294 int arg_count = args->length(); | 2295 int arg_count = args->length(); |
2295 for (int i = 0; i < arg_count; i++) { | 2296 for (int i = 0; i < arg_count; i++) { |
2296 Load(args->at(i)); | 2297 Load(args->at(i)); |
2297 } | 2298 } |
2298 | 2299 |
2299 // Record the position for debugging purposes. | 2300 // Record the position for debugging purposes. |
2300 CodeForSourcePosition(position); | 2301 CodeForSourcePosition(position); |
2301 | 2302 |
2302 // Use the shared code stub to call the function. | 2303 // Use the shared code stub to call the function. |
2303 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 2304 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
2304 CallFunctionStub call_function(arg_count, in_loop); | 2305 CallFunctionStub call_function(arg_count, in_loop, flags); |
2305 Result answer = frame_->CallStub(&call_function, arg_count + 1); | 2306 Result answer = frame_->CallStub(&call_function, arg_count + 1); |
2306 // Restore context and replace function on the stack with the | 2307 // Restore context and replace function on the stack with the |
2307 // result of the stub invocation. | 2308 // result of the stub invocation. |
2308 frame_->RestoreContextRegister(); | 2309 frame_->RestoreContextRegister(); |
2309 frame_->SetElementAt(0, &answer); | 2310 frame_->SetElementAt(0, &answer); |
2310 } | 2311 } |
2311 | 2312 |
2312 | 2313 |
2313 void CodeGenerator::CallApplyLazy(Property* apply, | 2314 void CodeGenerator::CallApplyLazy(Property* apply, |
2314 Expression* receiver, | 2315 Expression* receiver, |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2464 // the generic Function.prototype.apply implementation can deal with | 2465 // the generic Function.prototype.apply implementation can deal with |
2465 // the call like it usually does. | 2466 // the call like it usually does. |
2466 Result a2 = frame_->Pop(); | 2467 Result a2 = frame_->Pop(); |
2467 Result a1 = frame_->Pop(); | 2468 Result a1 = frame_->Pop(); |
2468 Result ap = frame_->Pop(); | 2469 Result ap = frame_->Pop(); |
2469 Result fn = frame_->Pop(); | 2470 Result fn = frame_->Pop(); |
2470 frame_->Push(&ap); | 2471 frame_->Push(&ap); |
2471 frame_->Push(&fn); | 2472 frame_->Push(&fn); |
2472 frame_->Push(&a1); | 2473 frame_->Push(&a1); |
2473 frame_->Push(&a2); | 2474 frame_->Push(&a2); |
2474 CallFunctionStub call_function(2, NOT_IN_LOOP); | 2475 CallFunctionStub call_function(2, NOT_IN_LOOP, NO_CALL_FUNCTION_FLAGS); |
2475 Result res = frame_->CallStub(&call_function, 3); | 2476 Result res = frame_->CallStub(&call_function, 3); |
2476 frame_->Push(&res); | 2477 frame_->Push(&res); |
2477 | 2478 |
2478 // All done. Restore context register after call. | 2479 // All done. Restore context register after call. |
2479 if (try_lazy) done.Bind(); | 2480 if (try_lazy) done.Bind(); |
2480 frame_->RestoreContextRegister(); | 2481 frame_->RestoreContextRegister(); |
2481 } | 2482 } |
2482 | 2483 |
2483 | 2484 |
2484 class DeferredStackCheck: public DeferredCode { | 2485 class DeferredStackCheck: public DeferredCode { |
(...skipping 2254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4739 // The runtime call returns a pair of values in eax (function) and | 4740 // The runtime call returns a pair of values in eax (function) and |
4740 // edx (receiver). Touch up the stack with the right values. | 4741 // edx (receiver). Touch up the stack with the right values. |
4741 Result receiver = allocator_->Allocate(edx); | 4742 Result receiver = allocator_->Allocate(edx); |
4742 frame_->SetElementAt(arg_count + 1, &result); | 4743 frame_->SetElementAt(arg_count + 1, &result); |
4743 frame_->SetElementAt(arg_count, &receiver); | 4744 frame_->SetElementAt(arg_count, &receiver); |
4744 receiver.Unuse(); | 4745 receiver.Unuse(); |
4745 | 4746 |
4746 // Call the function. | 4747 // Call the function. |
4747 CodeForSourcePosition(node->position()); | 4748 CodeForSourcePosition(node->position()); |
4748 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 4749 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
4749 CallFunctionStub call_function(arg_count, in_loop); | 4750 CallFunctionStub call_function(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
4750 result = frame_->CallStub(&call_function, arg_count + 1); | 4751 result = frame_->CallStub(&call_function, arg_count + 1); |
4751 | 4752 |
4752 // Restore the context and overwrite the function on the stack with | 4753 // Restore the context and overwrite the function on the stack with |
4753 // the result. | 4754 // the result. |
4754 frame_->RestoreContextRegister(); | 4755 frame_->RestoreContextRegister(); |
4755 frame_->SetElementAt(0, &result); | 4756 frame_->SetElementAt(0, &result); |
4756 | 4757 |
4757 } else if (var != NULL && !var->is_this() && var->is_global()) { | 4758 } else if (var != NULL && !var->is_this() && var->is_global()) { |
4758 // ---------------------------------- | 4759 // ---------------------------------- |
4759 // JavaScript example: 'foo(1, 2, 3)' // foo is global | 4760 // JavaScript example: 'foo(1, 2, 3)' // foo is global |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4799 // eagerly since they are arguments to an inevitable call (and are | 4800 // eagerly since they are arguments to an inevitable call (and are |
4800 // not sharable by the arguments). | 4801 // not sharable by the arguments). |
4801 ASSERT(!allocator()->is_used(eax)); | 4802 ASSERT(!allocator()->is_used(eax)); |
4802 frame_->EmitPush(eax); | 4803 frame_->EmitPush(eax); |
4803 | 4804 |
4804 // Load the receiver. | 4805 // Load the receiver. |
4805 ASSERT(!allocator()->is_used(edx)); | 4806 ASSERT(!allocator()->is_used(edx)); |
4806 frame_->EmitPush(edx); | 4807 frame_->EmitPush(edx); |
4807 | 4808 |
4808 // Call the function. | 4809 // Call the function. |
4809 CallWithArguments(args, node->position()); | 4810 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
4810 | 4811 |
4811 } else if (property != NULL) { | 4812 } else if (property != NULL) { |
4812 // Check if the key is a literal string. | 4813 // Check if the key is a literal string. |
4813 Literal* literal = property->key()->AsLiteral(); | 4814 Literal* literal = property->key()->AsLiteral(); |
4814 | 4815 |
4815 if (literal != NULL && literal->handle()->IsSymbol()) { | 4816 if (literal != NULL && literal->handle()->IsSymbol()) { |
4816 // ------------------------------------------------------------------ | 4817 // ------------------------------------------------------------------ |
4817 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' | 4818 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' |
4818 // ------------------------------------------------------------------ | 4819 // ------------------------------------------------------------------ |
4819 | 4820 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4865 // Pass receiver to called function. | 4866 // Pass receiver to called function. |
4866 if (property->is_synthetic()) { | 4867 if (property->is_synthetic()) { |
4867 // Use global object as receiver. | 4868 // Use global object as receiver. |
4868 LoadGlobalReceiver(); | 4869 LoadGlobalReceiver(); |
4869 } else { | 4870 } else { |
4870 // The reference's size is non-negative. | 4871 // The reference's size is non-negative. |
4871 frame_->PushElementAt(ref.size()); | 4872 frame_->PushElementAt(ref.size()); |
4872 } | 4873 } |
4873 | 4874 |
4874 // Call the function. | 4875 // Call the function. |
4875 CallWithArguments(args, node->position()); | 4876 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); |
4876 } | 4877 } |
4877 | 4878 |
4878 } else { | 4879 } else { |
4879 // ---------------------------------- | 4880 // ---------------------------------- |
4880 // JavaScript example: 'foo(1, 2, 3)' // foo is not global | 4881 // JavaScript example: 'foo(1, 2, 3)' // foo is not global |
4881 // ---------------------------------- | 4882 // ---------------------------------- |
4882 | 4883 |
4883 // Load the function. | 4884 // Load the function. |
4884 Load(function); | 4885 Load(function); |
4885 | 4886 |
4886 // Pass the global proxy as the receiver. | 4887 // Pass the global proxy as the receiver. |
4887 LoadGlobalReceiver(); | 4888 LoadGlobalReceiver(); |
4888 | 4889 |
4889 // Call the function. | 4890 // Call the function. |
4890 CallWithArguments(args, node->position()); | 4891 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
4891 } | 4892 } |
4892 } | 4893 } |
4893 | 4894 |
4894 | 4895 |
4895 void CodeGenerator::VisitCallNew(CallNew* node) { | 4896 void CodeGenerator::VisitCallNew(CallNew* node) { |
4896 Comment cmnt(masm_, "[ CallNew"); | 4897 Comment cmnt(masm_, "[ CallNew"); |
4897 | 4898 |
4898 // According to ECMA-262, section 11.2.2, page 44, the function | 4899 // According to ECMA-262, section 11.2.2, page 44, the function |
4899 // expression in new calls must be evaluated before the | 4900 // expression in new calls must be evaluated before the |
4900 // arguments. This is different from ordinary calls, where the | 4901 // arguments. This is different from ordinary calls, where the |
(...skipping 3773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8674 __ push(eax); | 8675 __ push(eax); |
8675 | 8676 |
8676 // Do tail-call to runtime routine. | 8677 // Do tail-call to runtime routine. |
8677 __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1, 1); | 8678 __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1, 1); |
8678 } | 8679 } |
8679 | 8680 |
8680 | 8681 |
8681 void CallFunctionStub::Generate(MacroAssembler* masm) { | 8682 void CallFunctionStub::Generate(MacroAssembler* masm) { |
8682 Label slow; | 8683 Label slow; |
8683 | 8684 |
| 8685 // If the receiver might be a value (string, number or boolean) check for this |
| 8686 // and box it if it is. |
| 8687 if (ReceiverMightBeValue()) { |
| 8688 // Get the receiver from the stack. |
| 8689 // +1 ~ return address |
| 8690 Label receiver_is_value, receiver_is_js_object; |
| 8691 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize)); |
| 8692 |
| 8693 // Check if receiver is a smi (which is a number value). |
| 8694 __ test(eax, Immediate(kSmiTagMask)); |
| 8695 __ j(zero, &receiver_is_value, not_taken); |
| 8696 |
| 8697 // Check if the receiver is a valid JS object. |
| 8698 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edi); |
| 8699 __ j(above_equal, &receiver_is_js_object); |
| 8700 |
| 8701 // Call the runtime to box the value. |
| 8702 __ bind(&receiver_is_value); |
| 8703 __ EnterInternalFrame(); |
| 8704 __ push(eax); |
| 8705 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 8706 __ LeaveInternalFrame(); |
| 8707 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), eax); |
| 8708 |
| 8709 __ bind(&receiver_is_js_object); |
| 8710 } |
| 8711 |
8684 // Get the function to call from the stack. | 8712 // Get the function to call from the stack. |
8685 // +2 ~ receiver, return address | 8713 // +2 ~ receiver, return address |
8686 __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize)); | 8714 __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize)); |
8687 | 8715 |
8688 // Check that the function really is a JavaScript function. | 8716 // Check that the function really is a JavaScript function. |
8689 __ test(edi, Immediate(kSmiTagMask)); | 8717 __ test(edi, Immediate(kSmiTagMask)); |
8690 __ j(zero, &slow, not_taken); | 8718 __ j(zero, &slow, not_taken); |
8691 // Goto slow case if we do not have a function. | 8719 // Goto slow case if we do not have a function. |
8692 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 8720 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
8693 __ j(not_equal, &slow, not_taken); | 8721 __ j(not_equal, &slow, not_taken); |
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9761 | 9789 |
9762 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 9790 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
9763 // tagged as a small integer. | 9791 // tagged as a small integer. |
9764 __ bind(&runtime); | 9792 __ bind(&runtime); |
9765 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); | 9793 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); |
9766 } | 9794 } |
9767 | 9795 |
9768 #undef __ | 9796 #undef __ |
9769 | 9797 |
9770 } } // namespace v8::internal | 9798 } } // namespace v8::internal |
OLD | NEW |