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

Side by Side Diff: src/x64/codegen-x64.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 2009 the V8 project authors. All rights reserved. 1 // Copyright 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 797 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 // the generic Function.prototype.apply implementation can deal with 808 // the generic Function.prototype.apply implementation can deal with
809 // the call like it usually does. 809 // the call like it usually does.
810 Result a2 = frame_->Pop(); 810 Result a2 = frame_->Pop();
811 Result a1 = frame_->Pop(); 811 Result a1 = frame_->Pop();
812 Result ap = frame_->Pop(); 812 Result ap = frame_->Pop();
813 Result fn = frame_->Pop(); 813 Result fn = frame_->Pop();
814 frame_->Push(&ap); 814 frame_->Push(&ap);
815 frame_->Push(&fn); 815 frame_->Push(&fn);
816 frame_->Push(&a1); 816 frame_->Push(&a1);
817 frame_->Push(&a2); 817 frame_->Push(&a2);
818 CallFunctionStub call_function(2, NOT_IN_LOOP); 818 CallFunctionStub call_function(2, NOT_IN_LOOP, NO_CALL_FUNCTION_FLAGS);
819 Result res = frame_->CallStub(&call_function, 3); 819 Result res = frame_->CallStub(&call_function, 3);
820 frame_->Push(&res); 820 frame_->Push(&res);
821 821
822 // All done. Restore context register after call. 822 // All done. Restore context register after call.
823 if (try_lazy) done.Bind(); 823 if (try_lazy) done.Bind();
824 frame_->RestoreContextRegister(); 824 frame_->RestoreContextRegister();
825 } 825 }
826 826
827 827
828 class DeferredStackCheck: public DeferredCode { 828 class DeferredStackCheck: public DeferredCode {
(...skipping 1870 matching lines...) Expand 10 before | Expand all | Expand 10 after
2699 // The runtime call returns a pair of values in rax (function) and 2699 // The runtime call returns a pair of values in rax (function) and
2700 // rdx (receiver). Touch up the stack with the right values. 2700 // rdx (receiver). Touch up the stack with the right values.
2701 Result receiver = allocator_->Allocate(rdx); 2701 Result receiver = allocator_->Allocate(rdx);
2702 frame_->SetElementAt(arg_count + 1, &result); 2702 frame_->SetElementAt(arg_count + 1, &result);
2703 frame_->SetElementAt(arg_count, &receiver); 2703 frame_->SetElementAt(arg_count, &receiver);
2704 receiver.Unuse(); 2704 receiver.Unuse();
2705 2705
2706 // Call the function. 2706 // Call the function.
2707 CodeForSourcePosition(node->position()); 2707 CodeForSourcePosition(node->position());
2708 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; 2708 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
2709 CallFunctionStub call_function(arg_count, in_loop); 2709 CallFunctionStub call_function(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
2710 result = frame_->CallStub(&call_function, arg_count + 1); 2710 result = frame_->CallStub(&call_function, arg_count + 1);
2711 2711
2712 // Restore the context and overwrite the function on the stack with 2712 // Restore the context and overwrite the function on the stack with
2713 // the result. 2713 // the result.
2714 frame_->RestoreContextRegister(); 2714 frame_->RestoreContextRegister();
2715 frame_->SetElementAt(0, &result); 2715 frame_->SetElementAt(0, &result);
2716 2716
2717 } else if (var != NULL && !var->is_this() && var->is_global()) { 2717 } else if (var != NULL && !var->is_this() && var->is_global()) {
2718 // ---------------------------------- 2718 // ----------------------------------
2719 // JavaScript example: 'foo(1, 2, 3)' // foo is global 2719 // JavaScript example: 'foo(1, 2, 3)' // foo is global
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2760 // eagerly since they are arguments to an inevitable call (and are 2760 // eagerly since they are arguments to an inevitable call (and are
2761 // not sharable by the arguments). 2761 // not sharable by the arguments).
2762 ASSERT(!allocator()->is_used(rax)); 2762 ASSERT(!allocator()->is_used(rax));
2763 frame_->EmitPush(rax); 2763 frame_->EmitPush(rax);
2764 2764
2765 // Load the receiver. 2765 // Load the receiver.
2766 ASSERT(!allocator()->is_used(rdx)); 2766 ASSERT(!allocator()->is_used(rdx));
2767 frame_->EmitPush(rdx); 2767 frame_->EmitPush(rdx);
2768 2768
2769 // Call the function. 2769 // Call the function.
2770 CallWithArguments(args, node->position()); 2770 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
2771 2771
2772 } else if (property != NULL) { 2772 } else if (property != NULL) {
2773 // Check if the key is a literal string. 2773 // Check if the key is a literal string.
2774 Literal* literal = property->key()->AsLiteral(); 2774 Literal* literal = property->key()->AsLiteral();
2775 2775
2776 if (literal != NULL && literal->handle()->IsSymbol()) { 2776 if (literal != NULL && literal->handle()->IsSymbol()) {
2777 // ------------------------------------------------------------------ 2777 // ------------------------------------------------------------------
2778 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 2778 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
2779 // ------------------------------------------------------------------ 2779 // ------------------------------------------------------------------
2780 2780
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2825 // Pass receiver to called function. 2825 // Pass receiver to called function.
2826 if (property->is_synthetic()) { 2826 if (property->is_synthetic()) {
2827 // Use global object as receiver. 2827 // Use global object as receiver.
2828 LoadGlobalReceiver(); 2828 LoadGlobalReceiver();
2829 } else { 2829 } else {
2830 // The reference's size is non-negative. 2830 // The reference's size is non-negative.
2831 frame_->PushElementAt(ref.size()); 2831 frame_->PushElementAt(ref.size());
2832 } 2832 }
2833 2833
2834 // Call the function. 2834 // Call the function.
2835 CallWithArguments(args, node->position()); 2835 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position());
2836 } 2836 }
2837 2837
2838 } else { 2838 } else {
2839 // ---------------------------------- 2839 // ----------------------------------
2840 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 2840 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
2841 // ---------------------------------- 2841 // ----------------------------------
2842 2842
2843 // Load the function. 2843 // Load the function.
2844 Load(function); 2844 Load(function);
2845 2845
2846 // Pass the global proxy as the receiver. 2846 // Pass the global proxy as the receiver.
2847 LoadGlobalReceiver(); 2847 LoadGlobalReceiver();
2848 2848
2849 // Call the function. 2849 // Call the function.
2850 CallWithArguments(args, node->position()); 2850 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
2851 } 2851 }
2852 } 2852 }
2853 2853
2854 2854
2855 void CodeGenerator::VisitCallNew(CallNew* node) { 2855 void CodeGenerator::VisitCallNew(CallNew* node) {
2856 Comment cmnt(masm_, "[ CallNew"); 2856 Comment cmnt(masm_, "[ CallNew");
2857 2857
2858 // According to ECMA-262, section 11.2.2, page 44, the function 2858 // According to ECMA-262, section 11.2.2, page 44, the function
2859 // expression in new calls must be evaluated before the 2859 // expression in new calls must be evaluated before the
2860 // arguments. This is different from ordinary calls, where the 2860 // arguments. This is different from ordinary calls, where the
(...skipping 3690 matching lines...) Expand 10 before | Expand all | Expand 10 after
6551 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE); 6551 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
6552 ASSERT(kSymbolTag != 0); 6552 ASSERT(kSymbolTag != 0);
6553 __ testb(scratch, Immediate(kIsSymbolMask)); 6553 __ testb(scratch, Immediate(kIsSymbolMask));
6554 __ j(zero, label); 6554 __ j(zero, label);
6555 } 6555 }
6556 6556
6557 6557
6558 // Call the function just below TOS on the stack with the given 6558 // Call the function just below TOS on the stack with the given
6559 // arguments. The receiver is the TOS. 6559 // arguments. The receiver is the TOS.
6560 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 6560 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
6561 CallFunctionFlags flags,
6561 int position) { 6562 int position) {
6562 // Push the arguments ("left-to-right") on the stack. 6563 // Push the arguments ("left-to-right") on the stack.
6563 int arg_count = args->length(); 6564 int arg_count = args->length();
6564 for (int i = 0; i < arg_count; i++) { 6565 for (int i = 0; i < arg_count; i++) {
6565 Load(args->at(i)); 6566 Load(args->at(i));
6566 } 6567 }
6567 6568
6568 // Record the position for debugging purposes. 6569 // Record the position for debugging purposes.
6569 CodeForSourcePosition(position); 6570 CodeForSourcePosition(position);
6570 6571
6571 // Use the shared code stub to call the function. 6572 // Use the shared code stub to call the function.
6572 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; 6573 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
6573 CallFunctionStub call_function(arg_count, in_loop); 6574 CallFunctionStub call_function(arg_count, in_loop, flags);
6574 Result answer = frame_->CallStub(&call_function, arg_count + 1); 6575 Result answer = frame_->CallStub(&call_function, arg_count + 1);
6575 // Restore context and replace function on the stack with the 6576 // Restore context and replace function on the stack with the
6576 // result of the stub invocation. 6577 // result of the stub invocation.
6577 frame_->RestoreContextRegister(); 6578 frame_->RestoreContextRegister();
6578 frame_->SetElementAt(0, &answer); 6579 frame_->SetElementAt(0, &answer);
6579 } 6580 }
6580 6581
6581 6582
6582 void InstanceofStub::Generate(MacroAssembler* masm) { 6583 void InstanceofStub::Generate(MacroAssembler* masm) {
6583 // Implements "value instanceof function" operator. 6584 // Implements "value instanceof function" operator.
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
6961 6962
6962 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize, 6963 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize,
6963 StackHandlerConstants::kPCOffset); 6964 StackHandlerConstants::kPCOffset);
6964 __ ret(0); 6965 __ ret(0);
6965 } 6966 }
6966 6967
6967 6968
6968 void CallFunctionStub::Generate(MacroAssembler* masm) { 6969 void CallFunctionStub::Generate(MacroAssembler* masm) {
6969 Label slow; 6970 Label slow;
6970 6971
6972 // If the receiver might be a value (string, number or boolean) check for this
6973 // and box it if it is.
6974 if (ReceiverMightBeValue()) {
6975 // Get the receiver from the stack.
6976 // +1 ~ return address
6977 Label receiver_is_value, receiver_is_js_object;
6978 __ movq(rax, Operand(rsp, (argc_ + 1) * kPointerSize));
6979
6980 // Check if receiver is a smi (which is a number value).
6981 __ JumpIfSmi(rax, &receiver_is_value);
6982
6983 // Check if the receiver is a valid JS object.
6984 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rdi);
6985 __ j(above_equal, &receiver_is_js_object);
6986
6987 // Call the runtime to box the value.
6988 __ bind(&receiver_is_value);
6989 __ EnterInternalFrame();
6990 __ push(rax);
6991 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
6992 __ LeaveInternalFrame();
6993 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rax);
6994
6995 __ bind(&receiver_is_js_object);
6996 }
6997
6971 // Get the function to call from the stack. 6998 // Get the function to call from the stack.
6972 // +2 ~ receiver, return address 6999 // +2 ~ receiver, return address
6973 __ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize)); 7000 __ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize));
6974 7001
6975 // Check that the function really is a JavaScript function. 7002 // Check that the function really is a JavaScript function.
6976 __ JumpIfSmi(rdi, &slow); 7003 __ JumpIfSmi(rdi, &slow);
6977 // Goto slow case if we do not have a function. 7004 // Goto slow case if we do not have a function.
6978 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 7005 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
6979 __ j(not_equal, &slow); 7006 __ j(not_equal, &slow);
6980 7007
(...skipping 1235 matching lines...) Expand 10 before | Expand all | Expand 10 after
8216 masm.GetCode(&desc); 8243 masm.GetCode(&desc);
8217 // Call the function from C++. 8244 // Call the function from C++.
8218 return FUNCTION_CAST<ModuloFunction>(buffer); 8245 return FUNCTION_CAST<ModuloFunction>(buffer);
8219 } 8246 }
8220 8247
8221 #endif 8248 #endif
8222 8249
8223 #undef __ 8250 #undef __
8224 8251
8225 } } // namespace v8::internal 8252 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698