Chromium Code Reviews

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: Fix FrameScope for API functions. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« 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 992 matching lines...)
1003 } 1003 }
1004 1004
1005 1005
1006 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { 1006 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1007 // Stack Layout: 1007 // Stack Layout:
1008 // rsp[0] : Return address 1008 // rsp[0] : Return address
1009 // rsp[8] : Argument n 1009 // rsp[8] : Argument n
1010 // rsp[16] : Argument n-1 1010 // rsp[16] : Argument n-1
1011 // ... 1011 // ...
1012 // rsp[8 * n] : Argument 1 1012 // rsp[8 * n] : Argument 1
1013 // rsp[8 * (n + 1)] : Receiver (function to call) 1013 // rsp[8 * (n + 1)] : Receiver (callable to call)
1014 // 1014 //
1015 // rax contains the number of arguments, n, not counting the receiver. 1015 // rax contains the number of arguments, n, not counting the receiver.
1016 // 1016 //
1017 // 1. Make sure we have at least one argument. 1017 // 1. Make sure we have at least one argument.
1018 { Label done; 1018 {
1019 Label done;
1019 __ testp(rax, rax); 1020 __ testp(rax, rax);
1020 __ j(not_zero, &done); 1021 __ j(not_zero, &done, Label::kNear);
1021 __ PopReturnAddressTo(rbx); 1022 __ PopReturnAddressTo(rbx);
1022 __ Push(masm->isolate()->factory()->undefined_value()); 1023 __ PushRoot(Heap::kUndefinedValueRootIndex);
1023 __ PushReturnAddressFrom(rbx); 1024 __ PushReturnAddressFrom(rbx);
1024 __ incp(rax); 1025 __ incp(rax);
1025 __ bind(&done); 1026 __ bind(&done);
1026 } 1027 }
1027 1028
1028 // 2. Get the function to call (passed as receiver) from the stack, check 1029 // 2. Get the callable to call (passed as receiver) from the stack.
1029 // if it is a function. 1030 {
1030 Label slow, non_function; 1031 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()); 1032 __ 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 } 1033 }
1100 1034
1101 // 3b. Check for function proxy. 1035 // 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 1036 // (overwriting the original receiver). Adjust argument count to make
1117 // the original first argument the new receiver. 1037 // the original first argument the new receiver.
1118 __ bind(&shift_arguments); 1038 {
1119 { Label loop; 1039 Label loop;
1120 __ movp(rcx, rax); 1040 __ movp(rcx, rax);
1121 StackArgumentsAccessor args(rsp, rcx); 1041 StackArgumentsAccessor args(rsp, rcx);
1122 __ bind(&loop); 1042 __ bind(&loop);
1123 __ movp(rbx, args.GetArgumentOperand(1)); 1043 __ movp(rbx, args.GetArgumentOperand(1));
1124 __ movp(args.GetArgumentOperand(0), rbx); 1044 __ movp(args.GetArgumentOperand(0), rbx);
1125 __ decp(rcx); 1045 __ decp(rcx);
1126 __ j(not_zero, &loop); // While non-zero. 1046 __ j(not_zero, &loop); // While non-zero.
1127 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address. 1047 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address.
1128 __ decp(rax); // One fewer argument (first argument is new receiver). 1048 __ decp(rax); // One fewer argument (first argument is new receiver).
1129 } 1049 }
1130 1050
1131 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 1051 // 4. Call the callable.
1132 // or a function proxy via CALL_FUNCTION_PROXY. 1052 __ Jump(masm->isolate()->builtins()->Invoke(), 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 } 1053 }
1170 1054
1171 1055
1172 static void Generate_PushAppliedArguments(MacroAssembler* masm, 1056 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1173 const int argumentsOffset, 1057 const int argumentsOffset,
1174 const int indexOffset, 1058 const int indexOffset,
1175 const int limitOffset) { 1059 const int limitOffset) {
1176 Register receiver = LoadDescriptor::ReceiverRegister(); 1060 Register receiver = LoadDescriptor::ReceiverRegister();
1177 Register key = LoadDescriptor::NameRegister(); 1061 Register key = LoadDescriptor::NameRegister();
1178 Register slot = LoadDescriptor::SlotRegister(); 1062 Register slot = LoadDescriptor::SlotRegister();
(...skipping 65 matching lines...)
1244 __ Push(Operand(rbp, kArgumentsOffset)); 1128 __ Push(Operand(rbp, kArgumentsOffset));
1245 if (targetIsArgument) { 1129 if (targetIsArgument) {
1246 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, 1130 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX,
1247 CALL_FUNCTION); 1131 CALL_FUNCTION);
1248 } else { 1132 } else {
1249 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); 1133 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION);
1250 } 1134 }
1251 1135
1252 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged); 1136 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged);
1253 1137
1254 // Push current index and limit. 1138 // Push current index and limit, and receiver.
1255 const int kLimitOffset = 1139 const int kLimitOffset =
1256 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 1140 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1257 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 1141 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1258 __ Push(rax); // limit 1142 __ Push(rax); // limit
1259 __ Push(Immediate(0)); // index 1143 __ Push(Immediate(0)); // index
1260 1144 __ 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 1145
1315 // Loop over the arguments array, pushing each value to the stack 1146 // Loop over the arguments array, pushing each value to the stack
1316 Generate_PushAppliedArguments( 1147 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset,
1317 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); 1148 kLimitOffset);
1318 1149
1319 // Call the function. 1150 // Call the callable.
1320 Label call_proxy; 1151 // TODO(bmeurer): This should be a tail call according to ES6.
1321 ParameterCount actual(rax);
1322 __ movp(rdi, Operand(rbp, kFunctionOffset)); 1152 __ movp(rdi, Operand(rbp, kFunctionOffset));
1323 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 1153 __ Call(masm->isolate()->builtins()->Invoke(), 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 1154
1339 // Leave internal frame. 1155 // Leave internal frame.
1340 } 1156 }
1341 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments 1157 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1342 } 1158 }
1343 1159
1344 1160
1345 // Used by ReflectConstruct 1161 // Used by ReflectConstruct
1346 static void Generate_ConstructHelper(MacroAssembler* masm) { 1162 static void Generate_ConstructHelper(MacroAssembler* masm) {
1347 const int kFormalParameters = 3; 1163 const int kFormalParameters = 3;
(...skipping 453 matching lines...)
1801 __ bind(&stack_overflow); 1617 __ bind(&stack_overflow);
1802 { 1618 {
1803 FrameScope frame(masm, StackFrame::MANUAL); 1619 FrameScope frame(masm, StackFrame::MANUAL);
1804 EnterArgumentsAdaptorFrame(masm); 1620 EnterArgumentsAdaptorFrame(masm);
1805 __ InvokeBuiltin(Context::STACK_OVERFLOW_BUILTIN_INDEX, CALL_FUNCTION); 1621 __ InvokeBuiltin(Context::STACK_OVERFLOW_BUILTIN_INDEX, CALL_FUNCTION);
1806 __ int3(); 1622 __ int3();
1807 } 1623 }
1808 } 1624 }
1809 1625
1810 1626
1627 // static
1628 void Builtins::Generate_InvokeFunction(MacroAssembler* masm) {
1629 // ----------- S t a t e -------------
1630 // -- rax : the number of arguments (not including the receiver)
1631 // -- rdi : the function to call (checked to be a JSFunction)
1632 // -----------------------------------
1633
1634 Label convert, convert_global_proxy, convert_to_object, done_convert;
1635 StackArgumentsAccessor args(rsp, rax);
1636 __ AssertFunction(rdi);
1637 // Enter the context of the function; ToObject has to run in the function
1638 // context, and we also need to take the global proxy from the function
1639 // context in case of conversion.
1640 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1641 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
1642 SharedFunctionInfo::kStrictModeByteOffset);
1643 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
1644 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1645 // We need to convert the receiver for non-native sloppy mode functions.
1646 __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
1647 Immediate((1 << SharedFunctionInfo::kNativeBitWithinByte) |
1648 (1 << SharedFunctionInfo::kStrictModeBitWithinByte)));
1649 __ j(not_zero, &done_convert);
1650 {
1651 __ movp(rcx, args.GetReceiverOperand());
1652
1653 // ----------- S t a t e -------------
1654 // -- rax : the number of arguments (not including the receiver)
1655 // -- rcx : the receiver
1656 // -- rdx : the shared function info.
1657 // -- rdi : the function to call (checked to be a JSFunction)
1658 // -- rsi : the function context.
1659 // -----------------------------------
1660
1661 Label convert_writeback;
1662 __ JumpIfSmi(rcx, &convert_to_object, Label::kNear);
1663 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1664 __ CmpObjectType(rcx, FIRST_JS_RECEIVER_TYPE, rbx);
1665 __ j(above_equal, &done_convert);
1666 __ JumpIfRoot(rcx, Heap::kUndefinedValueRootIndex, &convert_global_proxy,
1667 Label::kNear);
1668 __ JumpIfNotRoot(rcx, Heap::kNullValueRootIndex, &convert_to_object,
1669 Label::kNear);
1670 __ bind(&convert_global_proxy);
1671 {
1672 // Patch receiver to global proxy.
1673 __ LoadGlobalProxy(rcx);
1674 }
1675 __ jmp(&convert_writeback);
1676 __ bind(&convert_to_object);
1677 {
1678 // Convert receiver using ToObject.
1679 // TODO(bmeurer): Inline the allocation here to avoid building the frame
1680 // in the fast case? (fall back to AllocateInNewSpace?)
1681 FrameScope scope(masm, StackFrame::INTERNAL);
1682 __ Integer32ToSmi(rax, rax);
1683 __ Push(rax);
1684 __ Push(rdi);
1685 __ movp(rax, rcx);
1686 ToObjectStub stub(masm->isolate());
1687 __ CallStub(&stub);
1688 __ movp(rcx, rax);
1689 __ Pop(rdi);
1690 __ Pop(rax);
1691 __ SmiToInteger32(rax, rax);
1692 }
1693 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1694 __ bind(&convert_writeback);
1695 __ movp(args.GetReceiverOperand(), rcx);
1696 }
1697 __ bind(&done_convert);
1698
1699 // ----------- S t a t e -------------
1700 // -- rax : the number of arguments (not including the receiver)
1701 // -- rdx : the shared function info.
1702 // -- rdi : the function to call (checked to be a JSFunction)
1703 // -- rsi : the function context.
1704 // -----------------------------------
1705
1706 __ LoadSharedFunctionInfoSpecialField(
1707 rbx, rdx, SharedFunctionInfo::kFormalParameterCountOffset);
1708 __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
1709 ParameterCount actual(rax);
1710 ParameterCount expected(rbx);
1711 __ InvokeCode(rdx, expected, actual, JUMP_FUNCTION, NullCallWrapper());
1712 }
1713
1714
1715 // static
1716 void Builtins::Generate_Invoke(MacroAssembler* masm) {
1717 // ----------- S t a t e -------------
1718 // -- rax : the number of arguments (not including the receiver)
1719 // -- rdi : the target to call (can be any Object).
1720 // -----------------------------------
1721
1722 Label non_smi, non_function;
1723 __ JumpIfSmi(rdi, &non_function);
1724 __ bind(&non_smi);
1725 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rdx);
1726 __ j(equal, masm->isolate()->builtins()->InvokeFunction(),
1727 RelocInfo::CODE_TARGET);
1728 __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
1729 __ j(not_equal, &non_function);
1730
1731 // 1. Call to function proxy.
1732 // TODO(bmeurer): This doesn't match the ES6 spec for [[Call]] on proxies.
Jarin 2015/09/07 07:49:43 You might want to add @neis to this TODO.
Benedikt Meurer 2015/09/07 09:14:34 Done.
1733 __ movp(rdi, FieldOperand(rdi, JSFunctionProxy::kCallTrapOffset));
1734 __ AssertNotSmi(rdi);
1735 __ jmp(&non_smi);
1736
1737 // 2. Call to something else, which might have a [[Call]] internal method (if
1738 // not we raise an exception).
1739 __ bind(&non_function);
1740 // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
1741 // be awesome instead; i.e. a trivial improvement would be to call into the
1742 // runtime and just deal with the API function there instead of returning a
1743 // delegate from a runtime call that just jumps back to the runtime once
1744 // called. Or, bonus points, call directly into the C API function here, as
1745 // we do in some Crankshaft fast cases.
1746 StackArgumentsAccessor args(rsp, rax);
1747 // Overwrite the original receiver with the (original) target.
1748 __ movp(args.GetReceiverOperand(), rdi);
1749 {
1750 // Determine the delegate for the target (if any).
1751 FrameScope scope(masm, StackFrame::INTERNAL);
1752 __ Integer32ToSmi(rax, rax);
1753 __ Push(rax);
1754 __ Push(rdi);
1755 __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
1756 __ movp(rdi, rax);
1757 __ Pop(rax);
1758 __ SmiToInteger32(rax, rax);
1759 }
1760 // The delegate is always a regular function.
1761 __ AssertFunction(rdi);
1762 __ Jump(masm->isolate()->builtins()->InvokeFunction(),
1763 RelocInfo::CODE_TARGET);
1764 }
1765
1766
1811 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 1767 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1812 // Lookup the function in the JavaScript frame. 1768 // Lookup the function in the JavaScript frame.
1813 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1769 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1814 { 1770 {
1815 FrameScope scope(masm, StackFrame::INTERNAL); 1771 FrameScope scope(masm, StackFrame::INTERNAL);
1816 // Pass function as argument. 1772 // Pass function as argument.
1817 __ Push(rax); 1773 __ Push(rax);
1818 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 1774 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1819 } 1775 }
1820 1776
(...skipping 39 matching lines...)
1860 __ ret(0); 1816 __ ret(0);
1861 } 1817 }
1862 1818
1863 1819
1864 #undef __ 1820 #undef __
1865 1821
1866 } // namespace internal 1822 } // namespace internal
1867 } // namespace v8 1823 } // namespace v8
1868 1824
1869 #endif // V8_TARGET_ARCH_X64 1825 #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