| 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 |