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