Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 542087: Ensure correct boxing of values when calling functions on them... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698