| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 __ addq(rax, Immediate(num_extra_args + 1)); | 72 __ addq(rax, Immediate(num_extra_args + 1)); |
| 73 __ JumpToExternalReference(ExternalReference(id, masm->isolate()), 1); | 73 __ JumpToExternalReference(ExternalReference(id, masm->isolate()), 1); |
| 74 } | 74 } |
| 75 | 75 |
| 76 | 76 |
| 77 static void CallRuntimePassFunction( | 77 static void CallRuntimePassFunction( |
| 78 MacroAssembler* masm, Runtime::FunctionId function_id) { | 78 MacroAssembler* masm, Runtime::FunctionId function_id) { |
| 79 FrameScope scope(masm, StackFrame::INTERNAL); | 79 FrameScope scope(masm, StackFrame::INTERNAL); |
| 80 // Push a copy of the function onto the stack. | 80 // Push a copy of the function onto the stack. |
| 81 __ push(rdi); | 81 __ push(rdi); |
| 82 // Push call kind information. | |
| 83 __ push(rcx); | |
| 84 // Function is also the parameter to the runtime call. | 82 // Function is also the parameter to the runtime call. |
| 85 __ push(rdi); | 83 __ push(rdi); |
| 86 | 84 |
| 87 __ CallRuntime(function_id, 1); | 85 __ CallRuntime(function_id, 1); |
| 88 // Restore call kind information. | |
| 89 __ pop(rcx); | |
| 90 // Restore receiver. | 86 // Restore receiver. |
| 91 __ pop(rdi); | 87 __ pop(rdi); |
| 92 } | 88 } |
| 93 | 89 |
| 94 | 90 |
| 95 static void GenerateTailCallToSharedCode(MacroAssembler* masm) { | 91 static void GenerateTailCallToSharedCode(MacroAssembler* masm) { |
| 96 __ movq(kScratchRegister, | 92 __ movq(kScratchRegister, |
| 97 FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 93 FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 98 __ movq(kScratchRegister, | 94 __ movq(kScratchRegister, |
| 99 FieldOperand(kScratchRegister, SharedFunctionInfo::kCodeOffset)); | 95 FieldOperand(kScratchRegister, SharedFunctionInfo::kCodeOffset)); |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 __ push(Operand(rbx, rcx, times_pointer_size, 0)); | 362 __ push(Operand(rbx, rcx, times_pointer_size, 0)); |
| 367 __ bind(&entry); | 363 __ bind(&entry); |
| 368 __ decq(rcx); | 364 __ decq(rcx); |
| 369 __ j(greater_equal, &loop); | 365 __ j(greater_equal, &loop); |
| 370 | 366 |
| 371 // Call the function. | 367 // Call the function. |
| 372 if (is_api_function) { | 368 if (is_api_function) { |
| 373 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 369 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 374 Handle<Code> code = | 370 Handle<Code> code = |
| 375 masm->isolate()->builtins()->HandleApiCallConstruct(); | 371 masm->isolate()->builtins()->HandleApiCallConstruct(); |
| 376 ParameterCount expected(0); | 372 __ Call(code, RelocInfo::CODE_TARGET); |
| 377 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET, | |
| 378 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | |
| 379 } else { | 373 } else { |
| 380 ParameterCount actual(rax); | 374 ParameterCount actual(rax); |
| 381 __ InvokeFunction(rdi, actual, CALL_FUNCTION, | 375 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); |
| 382 NullCallWrapper(), CALL_AS_METHOD); | |
| 383 } | 376 } |
| 384 | 377 |
| 385 // Store offset of return address for deoptimizer. | 378 // Store offset of return address for deoptimizer. |
| 386 if (!is_api_function && !count_constructions) { | 379 if (!is_api_function && !count_constructions) { |
| 387 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 380 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
| 388 } | 381 } |
| 389 | 382 |
| 390 // Restore context from the frame. | 383 // Restore context from the frame. |
| 391 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 384 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 392 | 385 |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 // No type feedback cell is available | 535 // No type feedback cell is available |
| 543 Handle<Object> undefined_sentinel( | 536 Handle<Object> undefined_sentinel( |
| 544 masm->isolate()->factory()->undefined_value()); | 537 masm->isolate()->factory()->undefined_value()); |
| 545 __ Move(rbx, undefined_sentinel); | 538 __ Move(rbx, undefined_sentinel); |
| 546 // Expects rdi to hold function pointer. | 539 // Expects rdi to hold function pointer. |
| 547 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 540 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 548 __ CallStub(&stub); | 541 __ CallStub(&stub); |
| 549 } else { | 542 } else { |
| 550 ParameterCount actual(rax); | 543 ParameterCount actual(rax); |
| 551 // Function must be in rdi. | 544 // Function must be in rdi. |
| 552 __ InvokeFunction(rdi, actual, CALL_FUNCTION, | 545 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); |
| 553 NullCallWrapper(), CALL_AS_METHOD); | |
| 554 } | 546 } |
| 555 // Exit the internal frame. Notice that this also removes the empty | 547 // Exit the internal frame. Notice that this also removes the empty |
| 556 // context and the function left on the stack by the code | 548 // context and the function left on the stack by the code |
| 557 // invocation. | 549 // invocation. |
| 558 } | 550 } |
| 559 | 551 |
| 560 // TODO(X64): Is argument correct? Is there a receiver to remove? | 552 // TODO(X64): Is argument correct? Is there a receiver to remove? |
| 561 __ ret(1 * kPointerSize); // Remove receiver. | 553 __ ret(1 * kPointerSize); // Remove receiver. |
| 562 } | 554 } |
| 563 | 555 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 576 CallRuntimePassFunction(masm, Runtime::kCompileUnoptimized); | 568 CallRuntimePassFunction(masm, Runtime::kCompileUnoptimized); |
| 577 GenerateTailCallToReturnedCode(masm); | 569 GenerateTailCallToReturnedCode(masm); |
| 578 } | 570 } |
| 579 | 571 |
| 580 | 572 |
| 581 static void CallCompileOptimized(MacroAssembler* masm, | 573 static void CallCompileOptimized(MacroAssembler* masm, |
| 582 bool concurrent) { | 574 bool concurrent) { |
| 583 FrameScope scope(masm, StackFrame::INTERNAL); | 575 FrameScope scope(masm, StackFrame::INTERNAL); |
| 584 // Push a copy of the function onto the stack. | 576 // Push a copy of the function onto the stack. |
| 585 __ push(rdi); | 577 __ push(rdi); |
| 586 // Push call kind information. | |
| 587 __ push(rcx); | |
| 588 // Function is also the parameter to the runtime call. | 578 // Function is also the parameter to the runtime call. |
| 589 __ push(rdi); | 579 __ push(rdi); |
| 590 // Whether to compile in a background thread. | 580 // Whether to compile in a background thread. |
| 591 __ Push(masm->isolate()->factory()->ToBoolean(concurrent)); | 581 __ Push(masm->isolate()->factory()->ToBoolean(concurrent)); |
| 592 | 582 |
| 593 __ CallRuntime(Runtime::kCompileOptimized, 2); | 583 __ CallRuntime(Runtime::kCompileOptimized, 2); |
| 594 // Restore call kind information. | |
| 595 __ pop(rcx); | |
| 596 // Restore receiver. | 584 // Restore receiver. |
| 597 __ pop(rdi); | 585 __ pop(rdi); |
| 598 } | 586 } |
| 599 | 587 |
| 600 | 588 |
| 601 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) { | 589 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) { |
| 602 CallCompileOptimized(masm, false); | 590 CallCompileOptimized(masm, false); |
| 603 GenerateTailCallToReturnedCode(masm); | 591 GenerateTailCallToReturnedCode(masm); |
| 604 } | 592 } |
| 605 | 593 |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 __ pop(rbx); // Discard copy of return address. | 871 __ pop(rbx); // Discard copy of return address. |
| 884 __ decq(rax); // One fewer argument (first argument is new receiver). | 872 __ decq(rax); // One fewer argument (first argument is new receiver). |
| 885 } | 873 } |
| 886 | 874 |
| 887 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, | 875 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, |
| 888 // or a function proxy via CALL_FUNCTION_PROXY. | 876 // or a function proxy via CALL_FUNCTION_PROXY. |
| 889 { Label function, non_proxy; | 877 { Label function, non_proxy; |
| 890 __ testq(rdx, rdx); | 878 __ testq(rdx, rdx); |
| 891 __ j(zero, &function); | 879 __ j(zero, &function); |
| 892 __ Set(rbx, 0); | 880 __ Set(rbx, 0); |
| 893 __ SetCallKind(rcx, CALL_AS_METHOD); | |
| 894 __ cmpq(rdx, Immediate(1)); | 881 __ cmpq(rdx, Immediate(1)); |
| 895 __ j(not_equal, &non_proxy); | 882 __ j(not_equal, &non_proxy); |
| 896 | 883 |
| 897 __ PopReturnAddressTo(rdx); | 884 __ PopReturnAddressTo(rdx); |
| 898 __ push(rdi); // re-add proxy object as additional argument | 885 __ push(rdi); // re-add proxy object as additional argument |
| 899 __ PushReturnAddressFrom(rdx); | 886 __ PushReturnAddressFrom(rdx); |
| 900 __ incq(rax); | 887 __ incq(rax); |
| 901 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 888 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); |
| 902 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 889 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 903 RelocInfo::CODE_TARGET); | 890 RelocInfo::CODE_TARGET); |
| 904 | 891 |
| 905 __ bind(&non_proxy); | 892 __ bind(&non_proxy); |
| 906 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 893 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); |
| 907 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 894 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 908 RelocInfo::CODE_TARGET); | 895 RelocInfo::CODE_TARGET); |
| 909 __ bind(&function); | 896 __ bind(&function); |
| 910 } | 897 } |
| 911 | 898 |
| 912 // 5b. Get the code to call from the function and check that the number of | 899 // 5b. Get the code to call from the function and check that the number of |
| 913 // expected arguments matches what we're providing. If so, jump | 900 // expected arguments matches what we're providing. If so, jump |
| 914 // (tail-call) to the code in register edx without checking arguments. | 901 // (tail-call) to the code in register edx without checking arguments. |
| 915 __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 902 __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 916 __ movsxlq(rbx, | 903 __ movsxlq(rbx, |
| 917 FieldOperand(rdx, | 904 FieldOperand(rdx, |
| 918 SharedFunctionInfo::kFormalParameterCountOffset)); | 905 SharedFunctionInfo::kFormalParameterCountOffset)); |
| 919 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 906 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 920 __ SetCallKind(rcx, CALL_AS_FUNCTION); | |
| 921 __ cmpq(rax, rbx); | 907 __ cmpq(rax, rbx); |
| 922 __ j(not_equal, | 908 __ j(not_equal, |
| 923 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 909 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 924 RelocInfo::CODE_TARGET); | 910 RelocInfo::CODE_TARGET); |
| 925 | 911 |
| 926 ParameterCount expected(0); | 912 ParameterCount expected(0); |
| 927 __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, | 913 __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); |
| 928 NullCallWrapper(), CALL_AS_FUNCTION); | |
| 929 } | 914 } |
| 930 | 915 |
| 931 | 916 |
| 932 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 917 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| 933 // Stack at entry: | 918 // Stack at entry: |
| 934 // rsp : return address | 919 // rsp : return address |
| 935 // rsp[8] : arguments | 920 // rsp[8] : arguments |
| 936 // rsp[16] : receiver ("this") | 921 // rsp[16] : receiver ("this") |
| 937 // rsp[24] : function | 922 // rsp[24] : function |
| 938 { | 923 { |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 __ cmpq(rax, Operand(rbp, kLimitOffset)); | 1047 __ cmpq(rax, Operand(rbp, kLimitOffset)); |
| 1063 __ j(not_equal, &loop); | 1048 __ j(not_equal, &loop); |
| 1064 | 1049 |
| 1065 // Call the function. | 1050 // Call the function. |
| 1066 Label call_proxy; | 1051 Label call_proxy; |
| 1067 ParameterCount actual(rax); | 1052 ParameterCount actual(rax); |
| 1068 __ SmiToInteger32(rax, rax); | 1053 __ SmiToInteger32(rax, rax); |
| 1069 __ movq(rdi, Operand(rbp, kFunctionOffset)); | 1054 __ movq(rdi, Operand(rbp, kFunctionOffset)); |
| 1070 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 1055 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
| 1071 __ j(not_equal, &call_proxy); | 1056 __ j(not_equal, &call_proxy); |
| 1072 __ InvokeFunction(rdi, actual, CALL_FUNCTION, | 1057 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); |
| 1073 NullCallWrapper(), CALL_AS_FUNCTION); | |
| 1074 | 1058 |
| 1075 frame_scope.GenerateLeaveFrame(); | 1059 frame_scope.GenerateLeaveFrame(); |
| 1076 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1060 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
| 1077 | 1061 |
| 1078 // Call the function proxy. | 1062 // Call the function proxy. |
| 1079 __ bind(&call_proxy); | 1063 __ bind(&call_proxy); |
| 1080 __ push(rdi); // add function proxy as last argument | 1064 __ push(rdi); // add function proxy as last argument |
| 1081 __ incq(rax); | 1065 __ incq(rax); |
| 1082 __ Set(rbx, 0); | 1066 __ Set(rbx, 0); |
| 1083 __ SetCallKind(rcx, CALL_AS_FUNCTION); | |
| 1084 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 1067 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); |
| 1085 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1068 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 1086 RelocInfo::CODE_TARGET); | 1069 RelocInfo::CODE_TARGET); |
| 1087 | 1070 |
| 1088 // Leave internal frame. | 1071 // Leave internal frame. |
| 1089 } | 1072 } |
| 1090 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1073 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
| 1091 } | 1074 } |
| 1092 | 1075 |
| 1093 | 1076 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); | 1294 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); |
| 1312 __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); | 1295 __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); |
| 1313 __ PushReturnAddressFrom(rcx); | 1296 __ PushReturnAddressFrom(rcx); |
| 1314 } | 1297 } |
| 1315 | 1298 |
| 1316 | 1299 |
| 1317 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { | 1300 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
| 1318 // ----------- S t a t e ------------- | 1301 // ----------- S t a t e ------------- |
| 1319 // -- rax : actual number of arguments | 1302 // -- rax : actual number of arguments |
| 1320 // -- rbx : expected number of arguments | 1303 // -- rbx : expected number of arguments |
| 1321 // -- rcx : call kind information | 1304 // -- rdi: function (passed through to callee) |
| 1322 // -- rdx : code entry to call | |
| 1323 // ----------------------------------- | 1305 // ----------------------------------- |
| 1324 | 1306 |
| 1325 Label invoke, dont_adapt_arguments; | 1307 Label invoke, dont_adapt_arguments; |
| 1326 Counters* counters = masm->isolate()->counters(); | 1308 Counters* counters = masm->isolate()->counters(); |
| 1327 __ IncrementCounter(counters->arguments_adaptors(), 1); | 1309 __ IncrementCounter(counters->arguments_adaptors(), 1); |
| 1328 | 1310 |
| 1329 Label enough, too_few; | 1311 Label enough, too_few; |
| 1312 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 1330 __ cmpq(rax, rbx); | 1313 __ cmpq(rax, rbx); |
| 1331 __ j(less, &too_few); | 1314 __ j(less, &too_few); |
| 1332 __ cmpq(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); | 1315 __ cmpq(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); |
| 1333 __ j(equal, &dont_adapt_arguments); | 1316 __ j(equal, &dont_adapt_arguments); |
| 1334 | 1317 |
| 1335 { // Enough parameters: Actual >= expected. | 1318 { // Enough parameters: Actual >= expected. |
| 1336 __ bind(&enough); | 1319 __ bind(&enough); |
| 1337 EnterArgumentsAdaptorFrame(masm); | 1320 EnterArgumentsAdaptorFrame(masm); |
| 1338 | 1321 |
| 1339 // Copy receiver and all expected arguments. | 1322 // Copy receiver and all expected arguments. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 __ bind(&ok); | 1434 __ bind(&ok); |
| 1452 __ ret(0); | 1435 __ ret(0); |
| 1453 } | 1436 } |
| 1454 | 1437 |
| 1455 | 1438 |
| 1456 #undef __ | 1439 #undef __ |
| 1457 | 1440 |
| 1458 } } // namespace v8::internal | 1441 } } // namespace v8::internal |
| 1459 | 1442 |
| 1460 #endif // V8_TARGET_ARCH_X64 | 1443 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |