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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 __ add(eax, Immediate(num_extra_args + 1)); | 73 __ add(eax, Immediate(num_extra_args + 1)); |
74 __ JumpToExternalReference(ExternalReference(id, masm->isolate())); | 74 __ JumpToExternalReference(ExternalReference(id, masm->isolate())); |
75 } | 75 } |
76 | 76 |
77 | 77 |
78 static void CallRuntimePassFunction( | 78 static void CallRuntimePassFunction( |
79 MacroAssembler* masm, Runtime::FunctionId function_id) { | 79 MacroAssembler* masm, Runtime::FunctionId function_id) { |
80 FrameScope scope(masm, StackFrame::INTERNAL); | 80 FrameScope scope(masm, StackFrame::INTERNAL); |
81 // Push a copy of the function. | 81 // Push a copy of the function. |
82 __ push(edi); | 82 __ push(edi); |
83 // Push call kind information. | |
84 __ push(ecx); | |
85 // Function is also the parameter to the runtime call. | 83 // Function is also the parameter to the runtime call. |
86 __ push(edi); | 84 __ push(edi); |
87 | 85 |
88 __ CallRuntime(function_id, 1); | 86 __ CallRuntime(function_id, 1); |
89 // Restore call kind information. | |
90 __ pop(ecx); | |
91 // Restore receiver. | 87 // Restore receiver. |
92 __ pop(edi); | 88 __ pop(edi); |
93 } | 89 } |
94 | 90 |
95 | 91 |
96 static void GenerateTailCallToSharedCode(MacroAssembler* masm) { | 92 static void GenerateTailCallToSharedCode(MacroAssembler* masm) { |
97 __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 93 __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
98 __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kCodeOffset)); | 94 __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kCodeOffset)); |
99 __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); | 95 __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); |
100 __ jmp(eax); | 96 __ jmp(eax); |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 __ dec(ecx); | 359 __ dec(ecx); |
364 __ j(greater_equal, &loop); | 360 __ j(greater_equal, &loop); |
365 | 361 |
366 // Call the function. | 362 // Call the function. |
367 if (is_api_function) { | 363 if (is_api_function) { |
368 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 364 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
369 Handle<Code> code = | 365 Handle<Code> code = |
370 masm->isolate()->builtins()->HandleApiCallConstruct(); | 366 masm->isolate()->builtins()->HandleApiCallConstruct(); |
371 ParameterCount expected(0); | 367 ParameterCount expected(0); |
372 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET, | 368 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET, |
373 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 369 CALL_FUNCTION, NullCallWrapper()); |
374 } else { | 370 } else { |
375 ParameterCount actual(eax); | 371 ParameterCount actual(eax); |
376 __ InvokeFunction(edi, actual, CALL_FUNCTION, | 372 __ InvokeFunction(edi, actual, CALL_FUNCTION, |
377 NullCallWrapper(), CALL_AS_METHOD); | 373 NullCallWrapper()); |
378 } | 374 } |
379 | 375 |
380 // Store offset of return address for deoptimizer. | 376 // Store offset of return address for deoptimizer. |
381 if (!is_api_function && !count_constructions) { | 377 if (!is_api_function && !count_constructions) { |
382 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 378 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
383 } | 379 } |
384 | 380 |
385 // Restore context from the frame. | 381 // Restore context from the frame. |
386 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 382 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
387 | 383 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 if (is_construct) { | 476 if (is_construct) { |
481 // No type feedback cell is available | 477 // No type feedback cell is available |
482 Handle<Object> undefined_sentinel( | 478 Handle<Object> undefined_sentinel( |
483 masm->isolate()->heap()->undefined_value(), masm->isolate()); | 479 masm->isolate()->heap()->undefined_value(), masm->isolate()); |
484 __ mov(ebx, Immediate(undefined_sentinel)); | 480 __ mov(ebx, Immediate(undefined_sentinel)); |
485 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 481 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
486 __ CallStub(&stub); | 482 __ CallStub(&stub); |
487 } else { | 483 } else { |
488 ParameterCount actual(eax); | 484 ParameterCount actual(eax); |
489 __ InvokeFunction(edi, actual, CALL_FUNCTION, | 485 __ InvokeFunction(edi, actual, CALL_FUNCTION, |
490 NullCallWrapper(), CALL_AS_METHOD); | 486 NullCallWrapper()); |
491 } | 487 } |
492 | 488 |
493 // Exit the internal frame. Notice that this also removes the empty. | 489 // Exit the internal frame. Notice that this also removes the empty. |
494 // context and the function left on the stack by the code | 490 // context and the function left on the stack by the code |
495 // invocation. | 491 // invocation. |
496 } | 492 } |
497 __ ret(kPointerSize); // Remove receiver. | 493 __ ret(kPointerSize); // Remove receiver. |
498 } | 494 } |
499 | 495 |
500 | 496 |
(...skipping 11 matching lines...) Expand all Loading... |
512 CallRuntimePassFunction(masm, Runtime::kCompileUnoptimized); | 508 CallRuntimePassFunction(masm, Runtime::kCompileUnoptimized); |
513 GenerateTailCallToReturnedCode(masm); | 509 GenerateTailCallToReturnedCode(masm); |
514 } | 510 } |
515 | 511 |
516 | 512 |
517 | 513 |
518 static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) { | 514 static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) { |
519 FrameScope scope(masm, StackFrame::INTERNAL); | 515 FrameScope scope(masm, StackFrame::INTERNAL); |
520 // Push a copy of the function. | 516 // Push a copy of the function. |
521 __ push(edi); | 517 __ push(edi); |
522 // Push call kind information. | |
523 __ push(ecx); | |
524 // Function is also the parameter to the runtime call. | 518 // Function is also the parameter to the runtime call. |
525 __ push(edi); | 519 __ push(edi); |
526 // Whether to compile in a background thread. | 520 // Whether to compile in a background thread. |
527 __ Push(masm->isolate()->factory()->ToBoolean(concurrent)); | 521 __ Push(masm->isolate()->factory()->ToBoolean(concurrent)); |
528 | 522 |
529 __ CallRuntime(Runtime::kCompileOptimized, 2); | 523 __ CallRuntime(Runtime::kCompileOptimized, 2); |
530 // Restore call kind information. | |
531 __ pop(ecx); | |
532 // Restore receiver. | 524 // Restore receiver. |
533 __ pop(edi); | 525 __ pop(edi); |
534 } | 526 } |
535 | 527 |
536 | 528 |
537 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) { | 529 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) { |
538 CallCompileOptimized(masm, false); | 530 CallCompileOptimized(masm, false); |
539 GenerateTailCallToReturnedCode(masm); | 531 GenerateTailCallToReturnedCode(masm); |
540 } | 532 } |
541 | 533 |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 __ test(edx, edx); | 819 __ test(edx, edx); |
828 __ j(zero, &function); | 820 __ j(zero, &function); |
829 __ Set(ebx, Immediate(0)); | 821 __ Set(ebx, Immediate(0)); |
830 __ cmp(edx, Immediate(1)); | 822 __ cmp(edx, Immediate(1)); |
831 __ j(not_equal, &non_proxy); | 823 __ j(not_equal, &non_proxy); |
832 | 824 |
833 __ pop(edx); // return address | 825 __ pop(edx); // return address |
834 __ push(edi); // re-add proxy object as additional argument | 826 __ push(edi); // re-add proxy object as additional argument |
835 __ push(edx); | 827 __ push(edx); |
836 __ inc(eax); | 828 __ inc(eax); |
837 __ SetCallKind(ecx, CALL_AS_FUNCTION); | |
838 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); | 829 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); |
839 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 830 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
840 RelocInfo::CODE_TARGET); | 831 RelocInfo::CODE_TARGET); |
841 | 832 |
842 __ bind(&non_proxy); | 833 __ bind(&non_proxy); |
843 __ SetCallKind(ecx, CALL_AS_METHOD); | |
844 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 834 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
845 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 835 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
846 RelocInfo::CODE_TARGET); | 836 RelocInfo::CODE_TARGET); |
847 __ bind(&function); | 837 __ bind(&function); |
848 } | 838 } |
849 | 839 |
850 // 5b. Get the code to call from the function and check that the number of | 840 // 5b. Get the code to call from the function and check that the number of |
851 // expected arguments matches what we're providing. If so, jump | 841 // expected arguments matches what we're providing. If so, jump |
852 // (tail-call) to the code in register edx without checking arguments. | 842 // (tail-call) to the code in register edx without checking arguments. |
853 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 843 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
854 __ mov(ebx, | 844 __ mov(ebx, |
855 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); | 845 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); |
856 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); | 846 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); |
857 __ SmiUntag(ebx); | 847 __ SmiUntag(ebx); |
858 __ SetCallKind(ecx, CALL_AS_FUNCTION); | |
859 __ cmp(eax, ebx); | 848 __ cmp(eax, ebx); |
860 __ j(not_equal, | 849 __ j(not_equal, |
861 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); | 850 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); |
862 | 851 |
863 ParameterCount expected(0); | 852 ParameterCount expected(0); |
864 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper(), | 853 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); |
865 CALL_AS_FUNCTION); | |
866 } | 854 } |
867 | 855 |
868 | 856 |
869 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 857 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
870 static const int kArgumentsOffset = 2 * kPointerSize; | 858 static const int kArgumentsOffset = 2 * kPointerSize; |
871 static const int kReceiverOffset = 3 * kPointerSize; | 859 static const int kReceiverOffset = 3 * kPointerSize; |
872 static const int kFunctionOffset = 4 * kPointerSize; | 860 static const int kFunctionOffset = 4 * kPointerSize; |
873 { | 861 { |
874 FrameScope frame_scope(masm, StackFrame::INTERNAL); | 862 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
875 | 863 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 __ j(not_equal, &loop); | 980 __ j(not_equal, &loop); |
993 | 981 |
994 // Call the function. | 982 // Call the function. |
995 Label call_proxy; | 983 Label call_proxy; |
996 __ mov(eax, ecx); | 984 __ mov(eax, ecx); |
997 ParameterCount actual(eax); | 985 ParameterCount actual(eax); |
998 __ SmiUntag(eax); | 986 __ SmiUntag(eax); |
999 __ mov(edi, Operand(ebp, kFunctionOffset)); | 987 __ mov(edi, Operand(ebp, kFunctionOffset)); |
1000 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 988 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
1001 __ j(not_equal, &call_proxy); | 989 __ j(not_equal, &call_proxy); |
1002 __ InvokeFunction(edi, actual, CALL_FUNCTION, | 990 __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper()); |
1003 NullCallWrapper(), CALL_AS_FUNCTION); | |
1004 | 991 |
1005 frame_scope.GenerateLeaveFrame(); | 992 frame_scope.GenerateLeaveFrame(); |
1006 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 993 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
1007 | 994 |
1008 // Call the function proxy. | 995 // Call the function proxy. |
1009 __ bind(&call_proxy); | 996 __ bind(&call_proxy); |
1010 __ push(edi); // add function proxy as last argument | 997 __ push(edi); // add function proxy as last argument |
1011 __ inc(eax); | 998 __ inc(eax); |
1012 __ Set(ebx, Immediate(0)); | 999 __ Set(ebx, Immediate(0)); |
1013 __ SetCallKind(ecx, CALL_AS_FUNCTION); | |
1014 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); | 1000 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); |
1015 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1001 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1016 RelocInfo::CODE_TARGET); | 1002 RelocInfo::CODE_TARGET); |
1017 | 1003 |
1018 // Leave internal frame. | 1004 // Leave internal frame. |
1019 } | 1005 } |
1020 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1006 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
1021 } | 1007 } |
1022 | 1008 |
1023 | 1009 |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1238 __ pop(ecx); | 1224 __ pop(ecx); |
1239 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver | 1225 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver |
1240 __ push(ecx); | 1226 __ push(ecx); |
1241 } | 1227 } |
1242 | 1228 |
1243 | 1229 |
1244 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { | 1230 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
1245 // ----------- S t a t e ------------- | 1231 // ----------- S t a t e ------------- |
1246 // -- eax : actual number of arguments | 1232 // -- eax : actual number of arguments |
1247 // -- ebx : expected number of arguments | 1233 // -- ebx : expected number of arguments |
1248 // -- ecx : call kind information | |
1249 // -- edx : code entry to call | 1234 // -- edx : code entry to call |
1250 // ----------------------------------- | 1235 // ----------------------------------- |
1251 | 1236 |
1252 Label invoke, dont_adapt_arguments; | 1237 Label invoke, dont_adapt_arguments; |
1253 __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1); | 1238 __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1); |
1254 | 1239 |
1255 Label enough, too_few; | 1240 Label enough, too_few; |
1256 __ cmp(eax, ebx); | 1241 __ cmp(eax, ebx); |
1257 __ j(less, &too_few); | 1242 __ j(less, &too_few); |
1258 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); | 1243 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1381 | 1366 |
1382 __ bind(&ok); | 1367 __ bind(&ok); |
1383 __ ret(0); | 1368 __ ret(0); |
1384 } | 1369 } |
1385 | 1370 |
1386 #undef __ | 1371 #undef __ |
1387 } | 1372 } |
1388 } // namespace v8::internal | 1373 } // namespace v8::internal |
1389 | 1374 |
1390 #endif // V8_TARGET_ARCH_IA32 | 1375 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |