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

Side by Side Diff: src/x64/builtins-x64.cc

Issue 1311013008: [builtins] Unify the various versions of [[Call]] with a Call builtin. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: AssertFunction was wrong Created 5 years, 3 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
« no previous file with comments | « src/runtime/runtime-function.cc ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_X64 5 #if V8_TARGET_ARCH_X64
6 6
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/codegen.h" 8 #include "src/codegen.h"
9 #include "src/deoptimizer.h" 9 #include "src/deoptimizer.h"
10 #include "src/full-codegen/full-codegen.h" 10 #include "src/full-codegen/full-codegen.h"
(...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) { 996 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
997 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); 997 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
998 } 998 }
999 999
1000 1000
1001 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 1001 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1002 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 1002 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1003 } 1003 }
1004 1004
1005 1005
1006 // static
1006 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { 1007 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1007 // Stack Layout: 1008 // Stack Layout:
1008 // rsp[0] : Return address 1009 // rsp[0] : Return address
1009 // rsp[8] : Argument n 1010 // rsp[8] : Argument n
1010 // rsp[16] : Argument n-1 1011 // rsp[16] : Argument n-1
1011 // ... 1012 // ...
1012 // rsp[8 * n] : Argument 1 1013 // rsp[8 * n] : Argument 1
1013 // rsp[8 * (n + 1)] : Receiver (function to call) 1014 // rsp[8 * (n + 1)] : Receiver (callable to call)
1014 // 1015 //
1015 // rax contains the number of arguments, n, not counting the receiver. 1016 // rax contains the number of arguments, n, not counting the receiver.
1016 // 1017 //
1017 // 1. Make sure we have at least one argument. 1018 // 1. Make sure we have at least one argument.
1018 { Label done; 1019 {
1020 Label done;
1019 __ testp(rax, rax); 1021 __ testp(rax, rax);
1020 __ j(not_zero, &done); 1022 __ j(not_zero, &done, Label::kNear);
1021 __ PopReturnAddressTo(rbx); 1023 __ PopReturnAddressTo(rbx);
1022 __ Push(masm->isolate()->factory()->undefined_value()); 1024 __ PushRoot(Heap::kUndefinedValueRootIndex);
1023 __ PushReturnAddressFrom(rbx); 1025 __ PushReturnAddressFrom(rbx);
1024 __ incp(rax); 1026 __ incp(rax);
1025 __ bind(&done); 1027 __ bind(&done);
1026 } 1028 }
1027 1029
1028 // 2. Get the function to call (passed as receiver) from the stack, check 1030 // 2. Get the callable to call (passed as receiver) from the stack.
1029 // if it is a function. 1031 {
1030 Label slow, non_function; 1032 StackArgumentsAccessor args(rsp, rax);
1031 StackArgumentsAccessor args(rsp, rax);
1032 __ movp(rdi, args.GetReceiverOperand());
1033 __ JumpIfSmi(rdi, &non_function);
1034 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1035 __ j(not_equal, &slow);
1036
1037 // 3a. Patch the first argument if necessary when calling a function.
1038 Label shift_arguments;
1039 __ Set(rdx, 0); // indicate regular JS_FUNCTION
1040 { Label convert_to_object, use_global_proxy, patch_receiver;
1041 // Change context eagerly in case we need the global receiver.
1042 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
1043
1044 // Do not transform the receiver for strict mode functions.
1045 __ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1046 __ testb(FieldOperand(rbx, SharedFunctionInfo::kStrictModeByteOffset),
1047 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1048 __ j(not_equal, &shift_arguments);
1049
1050 // Do not transform the receiver for natives.
1051 // SharedFunctionInfo is already loaded into rbx.
1052 __ testb(FieldOperand(rbx, SharedFunctionInfo::kNativeByteOffset),
1053 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
1054 __ j(not_zero, &shift_arguments);
1055
1056 // Compute the receiver in sloppy mode.
1057 __ movp(rbx, args.GetArgumentOperand(1));
1058 __ JumpIfSmi(rbx, &convert_to_object, Label::kNear);
1059
1060 __ CompareRoot(rbx, Heap::kNullValueRootIndex);
1061 __ j(equal, &use_global_proxy);
1062 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1063 __ j(equal, &use_global_proxy);
1064
1065 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1066 __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, rcx);
1067 __ j(above_equal, &shift_arguments);
1068
1069 __ bind(&convert_to_object);
1070 {
1071 // Enter an internal frame in order to preserve argument count.
1072 FrameScope scope(masm, StackFrame::INTERNAL);
1073 __ Integer32ToSmi(rax, rax);
1074 __ Push(rax);
1075
1076 __ movp(rax, rbx);
1077 ToObjectStub stub(masm->isolate());
1078 __ CallStub(&stub);
1079 __ movp(rbx, rax);
1080 __ Set(rdx, 0); // indicate regular JS_FUNCTION
1081
1082 __ Pop(rax);
1083 __ SmiToInteger32(rax, rax);
1084 }
1085
1086 // Restore the function to rdi.
1087 __ movp(rdi, args.GetReceiverOperand()); 1033 __ movp(rdi, args.GetReceiverOperand());
1088 __ jmp(&patch_receiver, Label::kNear);
1089
1090 __ bind(&use_global_proxy);
1091 __ movp(rbx,
1092 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1093 __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset));
1094
1095 __ bind(&patch_receiver);
1096 __ movp(args.GetArgumentOperand(1), rbx);
1097
1098 __ jmp(&shift_arguments);
1099 } 1034 }
1100 1035
1101 // 3b. Check for function proxy. 1036 // 3. Shift arguments and return address one slot down on the stack
1102 __ bind(&slow);
1103 __ Set(rdx, 1); // indicate function proxy
1104 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
1105 __ j(equal, &shift_arguments);
1106 __ bind(&non_function);
1107 __ Set(rdx, 2); // indicate non-function
1108
1109 // 3c. Patch the first argument when calling a non-function. The
1110 // CALL_NON_FUNCTION builtin expects the non-function callee as
1111 // receiver, so overwrite the first argument which will ultimately
1112 // become the receiver.
1113 __ movp(args.GetArgumentOperand(1), rdi);
1114
1115 // 4. Shift arguments and return address one slot down on the stack
1116 // (overwriting the original receiver). Adjust argument count to make 1037 // (overwriting the original receiver). Adjust argument count to make
1117 // the original first argument the new receiver. 1038 // the original first argument the new receiver.
1118 __ bind(&shift_arguments); 1039 {
1119 { Label loop; 1040 Label loop;
1120 __ movp(rcx, rax); 1041 __ movp(rcx, rax);
1121 StackArgumentsAccessor args(rsp, rcx); 1042 StackArgumentsAccessor args(rsp, rcx);
1122 __ bind(&loop); 1043 __ bind(&loop);
1123 __ movp(rbx, args.GetArgumentOperand(1)); 1044 __ movp(rbx, args.GetArgumentOperand(1));
1124 __ movp(args.GetArgumentOperand(0), rbx); 1045 __ movp(args.GetArgumentOperand(0), rbx);
1125 __ decp(rcx); 1046 __ decp(rcx);
1126 __ j(not_zero, &loop); // While non-zero. 1047 __ j(not_zero, &loop); // While non-zero.
1127 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address. 1048 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address.
1128 __ decp(rax); // One fewer argument (first argument is new receiver). 1049 __ decp(rax); // One fewer argument (first argument is new receiver).
1129 } 1050 }
1130 1051
1131 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 1052 // 4. Call the callable.
1132 // or a function proxy via CALL_FUNCTION_PROXY. 1053 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1133 { Label function, non_proxy;
1134 __ testp(rdx, rdx);
1135 __ j(zero, &function);
1136 __ Set(rbx, 0);
1137 __ cmpp(rdx, Immediate(1));
1138 __ j(not_equal, &non_proxy);
1139
1140 __ PopReturnAddressTo(rdx);
1141 __ Push(rdi); // re-add proxy object as additional argument
1142 __ PushReturnAddressFrom(rdx);
1143 __ incp(rax);
1144 __ GetBuiltinEntry(rdx, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX);
1145 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1146 RelocInfo::CODE_TARGET);
1147
1148 __ bind(&non_proxy);
1149 __ GetBuiltinEntry(rdx, Context::CALL_NON_FUNCTION_BUILTIN_INDEX);
1150 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1151 RelocInfo::CODE_TARGET);
1152 __ bind(&function);
1153 }
1154
1155 // 5b. Get the code to call from the function and check that the number of
1156 // expected arguments matches what we're providing. If so, jump
1157 // (tail-call) to the code in register edx without checking arguments.
1158 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1159 __ LoadSharedFunctionInfoSpecialField(rbx, rdx,
1160 SharedFunctionInfo::kFormalParameterCountOffset);
1161 __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
1162 __ cmpp(rax, rbx);
1163 __ j(not_equal,
1164 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1165 RelocInfo::CODE_TARGET);
1166
1167 ParameterCount expected(0);
1168 __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, NullCallWrapper());
1169 } 1054 }
1170 1055
1171 1056
1172 static void Generate_PushAppliedArguments(MacroAssembler* masm, 1057 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1173 const int argumentsOffset, 1058 const int argumentsOffset,
1174 const int indexOffset, 1059 const int indexOffset,
1175 const int limitOffset) { 1060 const int limitOffset) {
1176 Register receiver = LoadDescriptor::ReceiverRegister(); 1061 Register receiver = LoadDescriptor::ReceiverRegister();
1177 Register key = LoadDescriptor::NameRegister(); 1062 Register key = LoadDescriptor::NameRegister();
1178 Register slot = LoadDescriptor::SlotRegister(); 1063 Register slot = LoadDescriptor::SlotRegister();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 __ Push(Operand(rbp, kArgumentsOffset)); 1129 __ Push(Operand(rbp, kArgumentsOffset));
1245 if (targetIsArgument) { 1130 if (targetIsArgument) {
1246 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, 1131 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX,
1247 CALL_FUNCTION); 1132 CALL_FUNCTION);
1248 } else { 1133 } else {
1249 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); 1134 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION);
1250 } 1135 }
1251 1136
1252 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged); 1137 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged);
1253 1138
1254 // Push current index and limit. 1139 // Push current index and limit, and receiver.
1255 const int kLimitOffset = 1140 const int kLimitOffset =
1256 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 1141 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1257 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 1142 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1258 __ Push(rax); // limit 1143 __ Push(rax); // limit
1259 __ Push(Immediate(0)); // index 1144 __ Push(Immediate(0)); // index
1260 1145 __ Push(Operand(rbp, kReceiverOffset)); // receiver
1261 // Get the receiver.
1262 __ movp(rbx, Operand(rbp, kReceiverOffset));
1263
1264 // Check that the function is a JS function (otherwise it must be a proxy).
1265 Label push_receiver;
1266 __ movp(rdi, Operand(rbp, kFunctionOffset));
1267 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1268 __ j(not_equal, &push_receiver);
1269
1270 // Change context eagerly to get the right global object if necessary.
1271 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
1272
1273 // Do not transform the receiver for strict mode functions.
1274 Label call_to_object, use_global_proxy;
1275 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1276 __ testb(FieldOperand(rdx, SharedFunctionInfo::kStrictModeByteOffset),
1277 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1278 __ j(not_equal, &push_receiver);
1279
1280 // Do not transform the receiver for natives.
1281 __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
1282 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
1283 __ j(not_equal, &push_receiver);
1284
1285 // Compute the receiver in sloppy mode.
1286 __ JumpIfSmi(rbx, &call_to_object, Label::kNear);
1287 __ CompareRoot(rbx, Heap::kNullValueRootIndex);
1288 __ j(equal, &use_global_proxy);
1289 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1290 __ j(equal, &use_global_proxy);
1291
1292 // If given receiver is already a JavaScript object then there's no
1293 // reason for converting it.
1294 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1295 __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, rcx);
1296 __ j(above_equal, &push_receiver);
1297
1298 // Convert the receiver to an object.
1299 __ bind(&call_to_object);
1300 __ movp(rax, rbx);
1301 ToObjectStub stub(masm->isolate());
1302 __ CallStub(&stub);
1303 __ movp(rbx, rax);
1304 __ jmp(&push_receiver, Label::kNear);
1305
1306 __ bind(&use_global_proxy);
1307 __ movp(rbx,
1308 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1309 __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset));
1310
1311 // Push the receiver.
1312 __ bind(&push_receiver);
1313 __ Push(rbx);
1314 1146
1315 // Loop over the arguments array, pushing each value to the stack 1147 // Loop over the arguments array, pushing each value to the stack
1316 Generate_PushAppliedArguments( 1148 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset,
1317 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); 1149 kLimitOffset);
1318 1150
1319 // Call the function. 1151 // Call the callable.
1320 Label call_proxy; 1152 // TODO(bmeurer): This should be a tail call according to ES6.
1321 ParameterCount actual(rax);
1322 __ movp(rdi, Operand(rbp, kFunctionOffset)); 1153 __ movp(rdi, Operand(rbp, kFunctionOffset));
1323 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 1154 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1324 __ j(not_equal, &call_proxy);
1325 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
1326
1327 frame_scope.GenerateLeaveFrame();
1328 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1329
1330 // Call the function proxy.
1331 __ bind(&call_proxy);
1332 __ Push(rdi); // add function proxy as last argument
1333 __ incp(rax);
1334 __ Set(rbx, 0);
1335 __ GetBuiltinEntry(rdx, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX);
1336 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1337 RelocInfo::CODE_TARGET);
1338 1155
1339 // Leave internal frame. 1156 // Leave internal frame.
1340 } 1157 }
1341 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments 1158 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1342 } 1159 }
1343 1160
1344 1161
1345 // Used by ReflectConstruct 1162 // Used by ReflectConstruct
1346 static void Generate_ConstructHelper(MacroAssembler* masm) { 1163 static void Generate_ConstructHelper(MacroAssembler* masm) {
1347 const int kFormalParameters = 3; 1164 const int kFormalParameters = 3;
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
1801 __ bind(&stack_overflow); 1618 __ bind(&stack_overflow);
1802 { 1619 {
1803 FrameScope frame(masm, StackFrame::MANUAL); 1620 FrameScope frame(masm, StackFrame::MANUAL);
1804 EnterArgumentsAdaptorFrame(masm); 1621 EnterArgumentsAdaptorFrame(masm);
1805 __ InvokeBuiltin(Context::STACK_OVERFLOW_BUILTIN_INDEX, CALL_FUNCTION); 1622 __ InvokeBuiltin(Context::STACK_OVERFLOW_BUILTIN_INDEX, CALL_FUNCTION);
1806 __ int3(); 1623 __ int3();
1807 } 1624 }
1808 } 1625 }
1809 1626
1810 1627
1628 // static
1629 void Builtins::Generate_CallFunction(MacroAssembler* masm) {
1630 // ----------- S t a t e -------------
1631 // -- rax : the number of arguments (not including the receiver)
1632 // -- rdi : the function to call (checked to be a JSFunction)
1633 // -----------------------------------
1634
1635 Label convert, convert_global_proxy, convert_to_object, done_convert;
1636 StackArgumentsAccessor args(rsp, rax);
1637 __ AssertFunction(rdi);
1638 // TODO(bmeurer): Throw a TypeError if function's [[FunctionKind]] internal
1639 // slot is "classConstructor".
1640 // Enter the context of the function; ToObject has to run in the function
1641 // context, and we also need to take the global proxy from the function
1642 // context in case of conversion.
1643 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1644 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
1645 SharedFunctionInfo::kStrictModeByteOffset);
1646 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
1647 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1648 // We need to convert the receiver for non-native sloppy mode functions.
1649 __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
1650 Immediate((1 << SharedFunctionInfo::kNativeBitWithinByte) |
1651 (1 << SharedFunctionInfo::kStrictModeBitWithinByte)));
1652 __ j(not_zero, &done_convert);
1653 {
1654 __ movp(rcx, args.GetReceiverOperand());
1655
1656 // ----------- S t a t e -------------
1657 // -- rax : the number of arguments (not including the receiver)
1658 // -- rcx : the receiver
1659 // -- rdx : the shared function info.
1660 // -- rdi : the function to call (checked to be a JSFunction)
1661 // -- rsi : the function context.
1662 // -----------------------------------
1663
1664 Label convert_receiver;
1665 __ JumpIfSmi(rcx, &convert_to_object, Label::kNear);
1666 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1667 __ CmpObjectType(rcx, FIRST_JS_RECEIVER_TYPE, rbx);
1668 __ j(above_equal, &done_convert);
1669 __ JumpIfRoot(rcx, Heap::kUndefinedValueRootIndex, &convert_global_proxy,
1670 Label::kNear);
1671 __ JumpIfNotRoot(rcx, Heap::kNullValueRootIndex, &convert_to_object,
1672 Label::kNear);
1673 __ bind(&convert_global_proxy);
1674 {
1675 // Patch receiver to global proxy.
1676 __ LoadGlobalProxy(rcx);
1677 }
1678 __ jmp(&convert_receiver);
1679 __ bind(&convert_to_object);
1680 {
1681 // Convert receiver using ToObject.
1682 // TODO(bmeurer): Inline the allocation here to avoid building the frame
1683 // in the fast case? (fall back to AllocateInNewSpace?)
1684 FrameScope scope(masm, StackFrame::INTERNAL);
1685 __ Integer32ToSmi(rax, rax);
1686 __ Push(rax);
1687 __ Push(rdi);
1688 __ movp(rax, rcx);
1689 ToObjectStub stub(masm->isolate());
1690 __ CallStub(&stub);
1691 __ movp(rcx, rax);
1692 __ Pop(rdi);
1693 __ Pop(rax);
1694 __ SmiToInteger32(rax, rax);
1695 }
1696 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1697 __ bind(&convert_receiver);
1698 __ movp(args.GetReceiverOperand(), rcx);
1699 }
1700 __ bind(&done_convert);
1701
1702 // ----------- S t a t e -------------
1703 // -- rax : the number of arguments (not including the receiver)
1704 // -- rdx : the shared function info.
1705 // -- rdi : the function to call (checked to be a JSFunction)
1706 // -- rsi : the function context.
1707 // -----------------------------------
1708
1709 __ LoadSharedFunctionInfoSpecialField(
1710 rbx, rdx, SharedFunctionInfo::kFormalParameterCountOffset);
1711 __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
1712 ParameterCount actual(rax);
1713 ParameterCount expected(rbx);
1714 __ InvokeCode(rdx, expected, actual, JUMP_FUNCTION, NullCallWrapper());
1715 }
1716
1717
1718 // static
1719 void Builtins::Generate_Call(MacroAssembler* masm) {
1720 // ----------- S t a t e -------------
1721 // -- rax : the number of arguments (not including the receiver)
1722 // -- rdi : the target to call (can be any Object).
1723 // -----------------------------------
1724
1725 Label non_smi, non_function;
1726 __ JumpIfSmi(rdi, &non_function);
1727 __ bind(&non_smi);
1728 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rdx);
1729 __ j(equal, masm->isolate()->builtins()->CallFunction(),
1730 RelocInfo::CODE_TARGET);
1731 __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
1732 __ j(not_equal, &non_function);
1733
1734 // 1. Call to function proxy.
1735 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies.
1736 __ movp(rdi, FieldOperand(rdi, JSFunctionProxy::kCallTrapOffset));
1737 __ AssertNotSmi(rdi);
1738 __ jmp(&non_smi);
1739
1740 // 2. Call to something else, which might have a [[Call]] internal method (if
1741 // not we raise an exception).
1742 __ bind(&non_function);
1743 // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
1744 // be awesome instead; i.e. a trivial improvement would be to call into the
1745 // runtime and just deal with the API function there instead of returning a
1746 // delegate from a runtime call that just jumps back to the runtime once
1747 // called. Or, bonus points, call directly into the C API function here, as
1748 // we do in some Crankshaft fast cases.
1749 StackArgumentsAccessor args(rsp, rax);
1750 // Overwrite the original receiver with the (original) target.
1751 __ movp(args.GetReceiverOperand(), rdi);
1752 {
1753 // Determine the delegate for the target (if any).
1754 FrameScope scope(masm, StackFrame::INTERNAL);
1755 __ Integer32ToSmi(rax, rax);
1756 __ Push(rax);
1757 __ Push(rdi);
1758 __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
1759 __ movp(rdi, rax);
1760 __ Pop(rax);
1761 __ SmiToInteger32(rax, rax);
1762 }
1763 // The delegate is always a regular function.
1764 __ AssertFunction(rdi);
1765 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
1766 }
1767
1768
1811 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 1769 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1812 // Lookup the function in the JavaScript frame. 1770 // Lookup the function in the JavaScript frame.
1813 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1771 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1814 { 1772 {
1815 FrameScope scope(masm, StackFrame::INTERNAL); 1773 FrameScope scope(masm, StackFrame::INTERNAL);
1816 // Pass function as argument. 1774 // Pass function as argument.
1817 __ Push(rax); 1775 __ Push(rax);
1818 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 1776 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1819 } 1777 }
1820 1778
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1860 __ ret(0); 1818 __ ret(0);
1861 } 1819 }
1862 1820
1863 1821
1864 #undef __ 1822 #undef __
1865 1823
1866 } // namespace internal 1824 } // namespace internal
1867 } // namespace v8 1825 } // namespace v8
1868 1826
1869 #endif // V8_TARGET_ARCH_X64 1827 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/runtime/runtime-function.cc ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698