OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 493 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
494 Generate_JSConstructStubHelper(masm, true, false, false); | 494 Generate_JSConstructStubHelper(masm, true, false, false); |
495 } | 495 } |
496 | 496 |
497 | 497 |
498 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 498 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
499 bool is_construct) { | 499 bool is_construct) { |
500 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 500 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
501 | 501 |
502 // Clear the context before we push it when entering the internal frame. | 502 // Clear the context before we push it when entering the internal frame. |
503 __ Set(esi, Immediate(0)); | 503 __ Move(esi, Immediate(0)); |
504 | 504 |
505 { | 505 { |
506 FrameScope scope(masm, StackFrame::INTERNAL); | 506 FrameScope scope(masm, StackFrame::INTERNAL); |
507 | 507 |
508 // Load the previous frame pointer (ebx) to access C arguments | 508 // Load the previous frame pointer (ebx) to access C arguments |
509 __ mov(ebx, Operand(ebp, 0)); | 509 __ mov(ebx, Operand(ebp, 0)); |
510 | 510 |
511 // Get the function from the frame and setup the context. | 511 // Get the function from the frame and setup the context. |
512 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); | 512 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); |
513 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); | 513 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); |
514 | 514 |
515 // Push the function and the receiver onto the stack. | 515 // Push the function and the receiver onto the stack. |
516 __ push(ecx); | 516 __ push(ecx); |
517 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); | 517 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); |
518 | 518 |
519 // Load the number of arguments and setup pointer to the arguments. | 519 // Load the number of arguments and setup pointer to the arguments. |
520 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); | 520 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); |
521 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); | 521 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); |
522 | 522 |
523 // Copy arguments to the stack in a loop. | 523 // Copy arguments to the stack in a loop. |
524 Label loop, entry; | 524 Label loop, entry; |
525 __ Set(ecx, Immediate(0)); | 525 __ Move(ecx, Immediate(0)); |
526 __ jmp(&entry); | 526 __ jmp(&entry); |
527 __ bind(&loop); | 527 __ bind(&loop); |
528 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv | 528 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv |
529 __ push(Operand(edx, 0)); // dereference handle | 529 __ push(Operand(edx, 0)); // dereference handle |
530 __ inc(ecx); | 530 __ inc(ecx); |
531 __ bind(&entry); | 531 __ bind(&entry); |
532 __ cmp(ecx, eax); | 532 __ cmp(ecx, eax); |
533 __ j(not_equal, &loop); | 533 __ j(not_equal, &loop); |
534 | 534 |
535 // Get the function from the stack and call it. | 535 // Get the function from the stack and call it. |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 Label slow, non_function; | 778 Label slow, non_function; |
779 // 1 ~ return address. | 779 // 1 ~ return address. |
780 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); | 780 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); |
781 __ JumpIfSmi(edi, &non_function); | 781 __ JumpIfSmi(edi, &non_function); |
782 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 782 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
783 __ j(not_equal, &slow); | 783 __ j(not_equal, &slow); |
784 | 784 |
785 | 785 |
786 // 3a. Patch the first argument if necessary when calling a function. | 786 // 3a. Patch the first argument if necessary when calling a function. |
787 Label shift_arguments; | 787 Label shift_arguments; |
788 __ Set(edx, Immediate(0)); // indicate regular JS_FUNCTION | 788 __ Move(edx, Immediate(0)); // indicate regular JS_FUNCTION |
789 { Label convert_to_object, use_global_receiver, patch_receiver; | 789 { Label convert_to_object, use_global_receiver, patch_receiver; |
790 // Change context eagerly in case we need the global receiver. | 790 // Change context eagerly in case we need the global receiver. |
791 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 791 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
792 | 792 |
793 // Do not transform the receiver for strict mode functions. | 793 // Do not transform the receiver for strict mode functions. |
794 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 794 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
795 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), | 795 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), |
796 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 796 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
797 __ j(not_equal, &shift_arguments); | 797 __ j(not_equal, &shift_arguments); |
798 | 798 |
(...skipping 19 matching lines...) Expand all Loading... |
818 __ bind(&convert_to_object); | 818 __ bind(&convert_to_object); |
819 | 819 |
820 { // In order to preserve argument count. | 820 { // In order to preserve argument count. |
821 FrameScope scope(masm, StackFrame::INTERNAL); | 821 FrameScope scope(masm, StackFrame::INTERNAL); |
822 __ SmiTag(eax); | 822 __ SmiTag(eax); |
823 __ push(eax); | 823 __ push(eax); |
824 | 824 |
825 __ push(ebx); | 825 __ push(ebx); |
826 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 826 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
827 __ mov(ebx, eax); | 827 __ mov(ebx, eax); |
828 __ Set(edx, Immediate(0)); // restore | 828 __ Move(edx, Immediate(0)); // restore |
829 | 829 |
830 __ pop(eax); | 830 __ pop(eax); |
831 __ SmiUntag(eax); | 831 __ SmiUntag(eax); |
832 } | 832 } |
833 | 833 |
834 // Restore the function to edi. | 834 // Restore the function to edi. |
835 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); | 835 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); |
836 __ jmp(&patch_receiver); | 836 __ jmp(&patch_receiver); |
837 | 837 |
838 __ bind(&use_global_receiver); | 838 __ bind(&use_global_receiver); |
839 __ mov(ebx, | 839 __ mov(ebx, |
840 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 840 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
841 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 841 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
842 | 842 |
843 __ bind(&patch_receiver); | 843 __ bind(&patch_receiver); |
844 __ mov(Operand(esp, eax, times_4, 0), ebx); | 844 __ mov(Operand(esp, eax, times_4, 0), ebx); |
845 | 845 |
846 __ jmp(&shift_arguments); | 846 __ jmp(&shift_arguments); |
847 } | 847 } |
848 | 848 |
849 // 3b. Check for function proxy. | 849 // 3b. Check for function proxy. |
850 __ bind(&slow); | 850 __ bind(&slow); |
851 __ Set(edx, Immediate(1)); // indicate function proxy | 851 __ Move(edx, Immediate(1)); // indicate function proxy |
852 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); | 852 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); |
853 __ j(equal, &shift_arguments); | 853 __ j(equal, &shift_arguments); |
854 __ bind(&non_function); | 854 __ bind(&non_function); |
855 __ Set(edx, Immediate(2)); // indicate non-function | 855 __ Move(edx, Immediate(2)); // indicate non-function |
856 | 856 |
857 // 3c. Patch the first argument when calling a non-function. The | 857 // 3c. Patch the first argument when calling a non-function. The |
858 // CALL_NON_FUNCTION builtin expects the non-function callee as | 858 // CALL_NON_FUNCTION builtin expects the non-function callee as |
859 // receiver, so overwrite the first argument which will ultimately | 859 // receiver, so overwrite the first argument which will ultimately |
860 // become the receiver. | 860 // become the receiver. |
861 __ mov(Operand(esp, eax, times_4, 0), edi); | 861 __ mov(Operand(esp, eax, times_4, 0), edi); |
862 | 862 |
863 // 4. Shift arguments and return address one slot down on the stack | 863 // 4. Shift arguments and return address one slot down on the stack |
864 // (overwriting the original receiver). Adjust argument count to make | 864 // (overwriting the original receiver). Adjust argument count to make |
865 // the original first argument the new receiver. | 865 // the original first argument the new receiver. |
866 __ bind(&shift_arguments); | 866 __ bind(&shift_arguments); |
867 { Label loop; | 867 { Label loop; |
868 __ mov(ecx, eax); | 868 __ mov(ecx, eax); |
869 __ bind(&loop); | 869 __ bind(&loop); |
870 __ mov(ebx, Operand(esp, ecx, times_4, 0)); | 870 __ mov(ebx, Operand(esp, ecx, times_4, 0)); |
871 __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx); | 871 __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx); |
872 __ dec(ecx); | 872 __ dec(ecx); |
873 __ j(not_sign, &loop); // While non-negative (to copy return address). | 873 __ j(not_sign, &loop); // While non-negative (to copy return address). |
874 __ pop(ebx); // Discard copy of return address. | 874 __ pop(ebx); // Discard copy of return address. |
875 __ dec(eax); // One fewer argument (first argument is new receiver). | 875 __ dec(eax); // One fewer argument (first argument is new receiver). |
876 } | 876 } |
877 | 877 |
878 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, | 878 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, |
879 // or a function proxy via CALL_FUNCTION_PROXY. | 879 // or a function proxy via CALL_FUNCTION_PROXY. |
880 { Label function, non_proxy; | 880 { Label function, non_proxy; |
881 __ test(edx, edx); | 881 __ test(edx, edx); |
882 __ j(zero, &function); | 882 __ j(zero, &function); |
883 __ Set(ebx, Immediate(0)); | 883 __ Move(ebx, Immediate(0)); |
884 __ cmp(edx, Immediate(1)); | 884 __ cmp(edx, Immediate(1)); |
885 __ j(not_equal, &non_proxy); | 885 __ j(not_equal, &non_proxy); |
886 | 886 |
887 __ pop(edx); // return address | 887 __ pop(edx); // return address |
888 __ push(edi); // re-add proxy object as additional argument | 888 __ push(edi); // re-add proxy object as additional argument |
889 __ push(edx); | 889 __ push(edx); |
890 __ inc(eax); | 890 __ inc(eax); |
891 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); | 891 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); |
892 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 892 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
893 RelocInfo::CODE_TARGET); | 893 RelocInfo::CODE_TARGET); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1051 __ j(not_equal, &call_proxy); | 1051 __ j(not_equal, &call_proxy); |
1052 __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper()); | 1052 __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper()); |
1053 | 1053 |
1054 frame_scope.GenerateLeaveFrame(); | 1054 frame_scope.GenerateLeaveFrame(); |
1055 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1055 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
1056 | 1056 |
1057 // Call the function proxy. | 1057 // Call the function proxy. |
1058 __ bind(&call_proxy); | 1058 __ bind(&call_proxy); |
1059 __ push(edi); // add function proxy as last argument | 1059 __ push(edi); // add function proxy as last argument |
1060 __ inc(eax); | 1060 __ inc(eax); |
1061 __ Set(ebx, Immediate(0)); | 1061 __ Move(ebx, Immediate(0)); |
1062 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); | 1062 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); |
1063 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1063 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1064 RelocInfo::CODE_TARGET); | 1064 RelocInfo::CODE_TARGET); |
1065 | 1065 |
1066 // Leave internal frame. | 1066 // Leave internal frame. |
1067 } | 1067 } |
1068 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1068 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
1069 } | 1069 } |
1070 | 1070 |
1071 | 1071 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1185 __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset), | 1185 __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset), |
1186 JSValue::kSize >> kPointerSizeLog2); | 1186 JSValue::kSize >> kPointerSizeLog2); |
1187 __ Assert(equal, kUnexpectedStringWrapperInstanceSize); | 1187 __ Assert(equal, kUnexpectedStringWrapperInstanceSize); |
1188 __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0); | 1188 __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0); |
1189 __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper); | 1189 __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper); |
1190 } | 1190 } |
1191 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); | 1191 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); |
1192 | 1192 |
1193 // Set properties and elements. | 1193 // Set properties and elements. |
1194 Factory* factory = masm->isolate()->factory(); | 1194 Factory* factory = masm->isolate()->factory(); |
1195 __ Set(ecx, Immediate(factory->empty_fixed_array())); | 1195 __ Move(ecx, Immediate(factory->empty_fixed_array())); |
1196 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); | 1196 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); |
1197 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx); | 1197 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx); |
1198 | 1198 |
1199 // Set the value. | 1199 // Set the value. |
1200 __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); | 1200 __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); |
1201 | 1201 |
1202 // Ensure the object is fully initialized. | 1202 // Ensure the object is fully initialized. |
1203 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); | 1203 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
1204 | 1204 |
1205 // We're done. Return. | 1205 // We're done. Return. |
(...skipping 20 matching lines...) Expand all Loading... |
1226 __ push(eax); | 1226 __ push(eax); |
1227 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); | 1227 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); |
1228 __ pop(edi); | 1228 __ pop(edi); |
1229 } | 1229 } |
1230 __ mov(ebx, eax); | 1230 __ mov(ebx, eax); |
1231 __ jmp(&argument_is_string); | 1231 __ jmp(&argument_is_string); |
1232 | 1232 |
1233 // Load the empty string into ebx, remove the receiver from the | 1233 // Load the empty string into ebx, remove the receiver from the |
1234 // stack, and jump back to the case where the argument is a string. | 1234 // stack, and jump back to the case where the argument is a string. |
1235 __ bind(&no_arguments); | 1235 __ bind(&no_arguments); |
1236 __ Set(ebx, Immediate(factory->empty_string())); | 1236 __ Move(ebx, Immediate(factory->empty_string())); |
1237 __ pop(ecx); | 1237 __ pop(ecx); |
1238 __ lea(esp, Operand(esp, kPointerSize)); | 1238 __ lea(esp, Operand(esp, kPointerSize)); |
1239 __ push(ecx); | 1239 __ push(ecx); |
1240 __ jmp(&argument_is_string); | 1240 __ jmp(&argument_is_string); |
1241 | 1241 |
1242 // At this point the argument is already a string. Call runtime to | 1242 // At this point the argument is already a string. Call runtime to |
1243 // create a string wrapper. | 1243 // create a string wrapper. |
1244 __ bind(&gc_required); | 1244 __ bind(&gc_required); |
1245 __ IncrementCounter(counters->string_ctor_gc_required(), 1); | 1245 __ IncrementCounter(counters->string_ctor_gc_required(), 1); |
1246 { | 1246 { |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1426 | 1426 |
1427 __ bind(&ok); | 1427 __ bind(&ok); |
1428 __ ret(0); | 1428 __ ret(0); |
1429 } | 1429 } |
1430 | 1430 |
1431 #undef __ | 1431 #undef __ |
1432 } | 1432 } |
1433 } // namespace v8::internal | 1433 } // namespace v8::internal |
1434 | 1434 |
1435 #endif // V8_TARGET_ARCH_IA32 | 1435 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |