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

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

Issue 1332703002: X87: [builtins] Unify the various versions of [[Call]] with a Call builtin. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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/x87/assembler-x87.cc ('k') | src/x87/code-stubs-x87.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_X87 5 #if V8_TARGET_ARCH_X87
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 938 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) { 949 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
950 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); 950 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
951 } 951 }
952 952
953 953
954 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 954 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
955 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 955 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
956 } 956 }
957 957
958 958
959 // static
959 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { 960 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
960 Factory* factory = masm->isolate()->factory(); 961 // Stack Layout:
961 962 // esp[0] : Return address
963 // esp[8] : Argument n
964 // esp[16] : Argument n-1
965 // ...
966 // esp[8 * n] : Argument 1
967 // esp[8 * (n + 1)] : Receiver (callable to call)
968 //
969 // eax contains the number of arguments, n, not counting the receiver.
970 //
962 // 1. Make sure we have at least one argument. 971 // 1. Make sure we have at least one argument.
963 { Label done; 972 {
973 Label done;
964 __ test(eax, eax); 974 __ test(eax, eax);
965 __ j(not_zero, &done); 975 __ j(not_zero, &done, Label::kNear);
966 __ pop(ebx); 976 __ PopReturnAddressTo(ebx);
967 __ push(Immediate(factory->undefined_value())); 977 __ PushRoot(Heap::kUndefinedValueRootIndex);
968 __ push(ebx); 978 __ PushReturnAddressFrom(ebx);
969 __ inc(eax); 979 __ inc(eax);
970 __ bind(&done); 980 __ bind(&done);
971 } 981 }
972 982
973 // 2. Get the function to call (passed as receiver) from the stack, check 983 // 2. Get the callable to call (passed as receiver) from the stack.
974 // if it is a function. 984 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize));
975 Label slow, non_function;
976 // 1 ~ return address.
977 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize));
978 __ JumpIfSmi(edi, &non_function);
979 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
980 __ j(not_equal, &slow);
981 985
982 986 // 3. Shift arguments and return address one slot down on the stack
983 // 3a. Patch the first argument if necessary when calling a function.
984 Label shift_arguments;
985 __ Move(edx, Immediate(0)); // indicate regular JS_FUNCTION
986 { Label convert_to_object, use_global_proxy, patch_receiver;
987 // Change context eagerly in case we need the global receiver.
988 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
989
990 // Do not transform the receiver for strict mode functions.
991 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
992 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset),
993 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
994 __ j(not_equal, &shift_arguments);
995
996 // Do not transform the receiver for natives (shared already in ebx).
997 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset),
998 1 << SharedFunctionInfo::kNativeBitWithinByte);
999 __ j(not_equal, &shift_arguments);
1000
1001 // Compute the receiver in sloppy mode.
1002 __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument.
1003
1004 // Call ToObject on the receiver if it is not an object, or use the
1005 // global object if it is null or undefined.
1006 __ JumpIfSmi(ebx, &convert_to_object);
1007 __ cmp(ebx, factory->null_value());
1008 __ j(equal, &use_global_proxy);
1009 __ cmp(ebx, factory->undefined_value());
1010 __ j(equal, &use_global_proxy);
1011 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1012 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx);
1013 __ j(above_equal, &shift_arguments);
1014
1015 __ bind(&convert_to_object);
1016
1017 { // In order to preserve argument count.
1018 FrameScope scope(masm, StackFrame::INTERNAL);
1019 __ SmiTag(eax);
1020 __ push(eax);
1021
1022 __ mov(eax, ebx);
1023 ToObjectStub stub(masm->isolate());
1024 __ CallStub(&stub);
1025 __ mov(ebx, eax);
1026 __ Move(edx, Immediate(0)); // restore
1027
1028 __ pop(eax);
1029 __ SmiUntag(eax);
1030 }
1031
1032 // Restore the function to edi.
1033 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize));
1034 __ jmp(&patch_receiver);
1035
1036 __ bind(&use_global_proxy);
1037 __ mov(ebx,
1038 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1039 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalProxyOffset));
1040
1041 __ bind(&patch_receiver);
1042 __ mov(Operand(esp, eax, times_4, 0), ebx);
1043
1044 __ jmp(&shift_arguments);
1045 }
1046
1047 // 3b. Check for function proxy.
1048 __ bind(&slow);
1049 __ Move(edx, Immediate(1)); // indicate function proxy
1050 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
1051 __ j(equal, &shift_arguments);
1052 __ bind(&non_function);
1053 __ Move(edx, Immediate(2)); // indicate non-function
1054
1055 // 3c. Patch the first argument when calling a non-function. The
1056 // CALL_NON_FUNCTION builtin expects the non-function callee as
1057 // receiver, so overwrite the first argument which will ultimately
1058 // become the receiver.
1059 __ mov(Operand(esp, eax, times_4, 0), edi);
1060
1061 // 4. Shift arguments and return address one slot down on the stack
1062 // (overwriting the original receiver). Adjust argument count to make 987 // (overwriting the original receiver). Adjust argument count to make
1063 // the original first argument the new receiver. 988 // the original first argument the new receiver.
1064 __ bind(&shift_arguments); 989 {
1065 { Label loop; 990 Label loop;
1066 __ mov(ecx, eax); 991 __ mov(ecx, eax);
1067 __ bind(&loop); 992 __ bind(&loop);
1068 __ mov(ebx, Operand(esp, ecx, times_4, 0)); 993 __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0));
1069 __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx); 994 __ mov(Operand(esp, ecx, times_pointer_size, kPointerSize), ebx);
1070 __ dec(ecx); 995 __ dec(ecx);
1071 __ j(not_sign, &loop); // While non-negative (to copy return address). 996 __ j(not_sign, &loop); // While non-negative (to copy return address).
1072 __ pop(ebx); // Discard copy of return address. 997 __ pop(ebx); // Discard copy of return address.
1073 __ dec(eax); // One fewer argument (first argument is new receiver). 998 __ dec(eax); // One fewer argument (first argument is new receiver).
1074 } 999 }
1075 1000
1076 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 1001 // 4. Call the callable.
1077 // or a function proxy via CALL_FUNCTION_PROXY. 1002 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1078 { Label function, non_proxy;
1079 __ test(edx, edx);
1080 __ j(zero, &function);
1081 __ Move(ebx, Immediate(0));
1082 __ cmp(edx, Immediate(1));
1083 __ j(not_equal, &non_proxy);
1084
1085 __ pop(edx); // return address
1086 __ push(edi); // re-add proxy object as additional argument
1087 __ push(edx);
1088 __ inc(eax);
1089 __ GetBuiltinEntry(edx, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX);
1090 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1091 RelocInfo::CODE_TARGET);
1092
1093 __ bind(&non_proxy);
1094 __ GetBuiltinEntry(edx, Context::CALL_NON_FUNCTION_BUILTIN_INDEX);
1095 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1096 RelocInfo::CODE_TARGET);
1097 __ bind(&function);
1098 }
1099
1100 // 5b. Get the code to call from the function and check that the number of
1101 // expected arguments matches what we're providing. If so, jump
1102 // (tail-call) to the code in register edx without checking arguments.
1103 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1104 __ mov(ebx,
1105 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
1106 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
1107 __ SmiUntag(ebx);
1108 __ cmp(eax, ebx);
1109 __ j(not_equal,
1110 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline());
1111
1112 ParameterCount expected(0);
1113 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper());
1114 } 1003 }
1115 1004
1116 1005
1117 static void Generate_PushAppliedArguments(MacroAssembler* masm, 1006 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1118 const int argumentsOffset, 1007 const int argumentsOffset,
1119 const int indexOffset, 1008 const int indexOffset,
1120 const int limitOffset) { 1009 const int limitOffset) {
1121 // Copy all arguments from the array to the stack. 1010 // Copy all arguments from the array to the stack.
1122 Label entry, loop; 1011 Label entry, loop;
1123 Register receiver = LoadDescriptor::ReceiverRegister(); 1012 Register receiver = LoadDescriptor::ReceiverRegister();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 // Stack frame: 1067 // Stack frame:
1179 // ebp : Old base pointer 1068 // ebp : Old base pointer
1180 // ebp[4] : return address 1069 // ebp[4] : return address
1181 // ebp[8] : function arguments 1070 // ebp[8] : function arguments
1182 // ebp[12] : receiver 1071 // ebp[12] : receiver
1183 // ebp[16] : function 1072 // ebp[16] : function
1184 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; 1073 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1185 static const int kReceiverOffset = kArgumentsOffset + kPointerSize; 1074 static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1186 static const int kFunctionOffset = kReceiverOffset + kPointerSize; 1075 static const int kFunctionOffset = kReceiverOffset + kPointerSize;
1187 1076
1188 __ push(Operand(ebp, kFunctionOffset)); // push this 1077 __ push(Operand(ebp, kFunctionOffset)); // push this
1189 __ push(Operand(ebp, kArgumentsOffset)); // push arguments 1078 __ push(Operand(ebp, kArgumentsOffset)); // push arguments
1190 if (targetIsArgument) { 1079 if (targetIsArgument) {
1191 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, 1080 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX,
1192 CALL_FUNCTION); 1081 CALL_FUNCTION);
1193 } else { 1082 } else {
1194 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); 1083 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION);
1195 } 1084 }
1196 1085
1197 Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged); 1086 Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged);
1198 1087
1199 // Push current index and limit. 1088 // Push current index and limit.
1200 const int kLimitOffset = 1089 const int kLimitOffset =
1201 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 1090 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1202 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 1091 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1203 __ push(eax); // limit 1092 __ Push(eax); // limit
1204 __ push(Immediate(0)); // index 1093 __ Push(Immediate(0)); // index
1205 1094 __ Push(Operand(ebp, kReceiverOffset)); // receiver
1206 // Get the receiver.
1207 __ mov(ebx, Operand(ebp, kReceiverOffset));
1208
1209 // Check that the function is a JS function (otherwise it must be a proxy).
1210 Label push_receiver, use_global_proxy;
1211 __ mov(edi, Operand(ebp, kFunctionOffset));
1212 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
1213 __ j(not_equal, &push_receiver);
1214
1215 // Change context eagerly to get the right global object if necessary.
1216 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1217
1218 // Compute the receiver.
1219 // Do not transform the receiver for strict mode functions.
1220 Label call_to_object;
1221 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1222 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
1223 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
1224 __ j(not_equal, &push_receiver);
1225
1226 Factory* factory = masm->isolate()->factory();
1227
1228 // Do not transform the receiver for natives (shared already in ecx).
1229 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
1230 1 << SharedFunctionInfo::kNativeBitWithinByte);
1231 __ j(not_equal, &push_receiver);
1232
1233 // Compute the receiver in sloppy mode.
1234 // Call ToObject on the receiver if it is not an object, or use the
1235 // global object if it is null or undefined.
1236 __ JumpIfSmi(ebx, &call_to_object);
1237 __ cmp(ebx, factory->null_value());
1238 __ j(equal, &use_global_proxy);
1239 __ cmp(ebx, factory->undefined_value());
1240 __ j(equal, &use_global_proxy);
1241 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1242 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx);
1243 __ j(above_equal, &push_receiver);
1244
1245 __ bind(&call_to_object);
1246 __ mov(eax, ebx);
1247 ToObjectStub stub(masm->isolate());
1248 __ CallStub(&stub);
1249 __ mov(ebx, eax);
1250 __ jmp(&push_receiver);
1251
1252 __ bind(&use_global_proxy);
1253 __ mov(ebx,
1254 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1255 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalProxyOffset));
1256
1257 // Push the receiver.
1258 __ bind(&push_receiver);
1259 __ push(ebx);
1260 1095
1261 // Loop over the arguments array, pushing each value to the stack 1096 // Loop over the arguments array, pushing each value to the stack
1262 Generate_PushAppliedArguments( 1097 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset,
1263 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); 1098 kLimitOffset);
1264 1099
1265 // Call the function. 1100 // Call the callable.
1266 Label call_proxy; 1101 // TODO(bmeurer): This should be a tail call according to ES6.
1267 ParameterCount actual(eax);
1268 __ mov(edi, Operand(ebp, kFunctionOffset)); 1102 __ mov(edi, Operand(ebp, kFunctionOffset));
1269 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 1103 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1270 __ j(not_equal, &call_proxy);
1271 __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper());
1272
1273 frame_scope.GenerateLeaveFrame();
1274 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1275
1276 // Call the function proxy.
1277 __ bind(&call_proxy);
1278 __ push(edi); // add function proxy as last argument
1279 __ inc(eax);
1280 __ Move(ebx, Immediate(0));
1281 __ GetBuiltinEntry(edx, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX);
1282 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1283 RelocInfo::CODE_TARGET);
1284 1104
1285 // Leave internal frame. 1105 // Leave internal frame.
1286 } 1106 }
1287 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments 1107 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1288 } 1108 }
1289 1109
1290 1110
1291 // Used by ReflectConstruct 1111 // Used by ReflectConstruct
1292 static void Generate_ConstructHelper(MacroAssembler* masm) { 1112 static void Generate_ConstructHelper(MacroAssembler* masm) {
1293 const int kFormalParameters = 3; 1113 const int kFormalParameters = 3;
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1610 __ leave(); 1430 __ leave();
1611 1431
1612 // Remove caller arguments from the stack. 1432 // Remove caller arguments from the stack.
1613 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 1433 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1614 __ pop(ecx); 1434 __ pop(ecx);
1615 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 1435 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
1616 __ push(ecx); 1436 __ push(ecx);
1617 } 1437 }
1618 1438
1619 1439
1440 // static
1441 void Builtins::Generate_CallFunction(MacroAssembler* masm) {
1442 // ----------- S t a t e -------------
1443 // -- eax : the number of arguments (not including the receiver)
1444 // -- edi : the function to call (checked to be a JSFunction)
1445 // -----------------------------------
1446
1447 Label convert, convert_global_proxy, convert_to_object, done_convert;
1448 __ AssertFunction(edi);
1449 // TODO(bmeurer): Throw a TypeError if function's [[FunctionKind]] internal
1450 // slot is "classConstructor".
1451 // Enter the context of the function; ToObject has to run in the function
1452 // context, and we also need to take the global proxy from the function
1453 // context in case of conversion.
1454 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1455 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
1456 SharedFunctionInfo::kStrictModeByteOffset);
1457 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1458 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1459 // We need to convert the receiver for non-native sloppy mode functions.
1460 __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset),
1461 (1 << SharedFunctionInfo::kNativeBitWithinByte) |
1462 (1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1463 __ j(not_zero, &done_convert);
1464 {
1465 __ mov(ecx, Operand(esp, eax, times_pointer_size, kPointerSize));
1466
1467 // ----------- S t a t e -------------
1468 // -- eax : the number of arguments (not including the receiver)
1469 // -- ecx : the receiver
1470 // -- edx : the shared function info.
1471 // -- edi : the function to call (checked to be a JSFunction)
1472 // -- esi : the function context.
1473 // -----------------------------------
1474
1475 Label convert_receiver;
1476 __ JumpIfSmi(ecx, &convert_to_object, Label::kNear);
1477 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1478 __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ebx);
1479 __ j(above_equal, &done_convert);
1480 __ JumpIfRoot(ecx, Heap::kUndefinedValueRootIndex, &convert_global_proxy,
1481 Label::kNear);
1482 __ JumpIfNotRoot(ecx, Heap::kNullValueRootIndex, &convert_to_object,
1483 Label::kNear);
1484 __ bind(&convert_global_proxy);
1485 {
1486 // Patch receiver to global proxy.
1487 __ LoadGlobalProxy(ecx);
1488 }
1489 __ jmp(&convert_receiver);
1490 __ bind(&convert_to_object);
1491 {
1492 // Convert receiver using ToObject.
1493 // TODO(bmeurer): Inline the allocation here to avoid building the frame
1494 // in the fast case? (fall back to AllocateInNewSpace?)
1495 FrameScope scope(masm, StackFrame::INTERNAL);
1496 __ SmiTag(eax);
1497 __ Push(eax);
1498 __ Push(edi);
1499 __ mov(eax, ecx);
1500 ToObjectStub stub(masm->isolate());
1501 __ CallStub(&stub);
1502 __ mov(ecx, eax);
1503 __ Pop(edi);
1504 __ Pop(eax);
1505 __ SmiUntag(eax);
1506 }
1507 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1508 __ bind(&convert_receiver);
1509 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ecx);
1510 }
1511 __ bind(&done_convert);
1512
1513 // ----------- S t a t e -------------
1514 // -- eax : the number of arguments (not including the receiver)
1515 // -- edx : the shared function info.
1516 // -- edi : the function to call (checked to be a JSFunction)
1517 // -- esi : the function context.
1518 // -----------------------------------
1519
1520 __ mov(ebx,
1521 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
1522 __ SmiUntag(ebx);
1523 ParameterCount actual(eax);
1524 ParameterCount expected(ebx);
1525 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), expected,
1526 actual, JUMP_FUNCTION, NullCallWrapper());
1527 }
1528
1529
1530 // static
1531 void Builtins::Generate_Call(MacroAssembler* masm) {
1532 // ----------- S t a t e -------------
1533 // -- eax : the number of arguments (not including the receiver)
1534 // -- edi : the target to call (can be any Object).
1535 // -----------------------------------
1536
1537 Label non_smi, non_function;
1538 __ JumpIfSmi(edi, &non_function);
1539 __ bind(&non_smi);
1540 __ CmpObjectType(edi, JS_FUNCTION_TYPE, edx);
1541 __ j(equal, masm->isolate()->builtins()->CallFunction(),
1542 RelocInfo::CODE_TARGET);
1543 __ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
1544 __ j(not_equal, &non_function);
1545
1546 // 1. Call to function proxy.
1547 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies.
1548 __ mov(edi, FieldOperand(edi, JSFunctionProxy::kCallTrapOffset));
1549 __ AssertNotSmi(edi);
1550 __ jmp(&non_smi);
1551
1552 // 2. Call to something else, which might have a [[Call]] internal method (if
1553 // not we raise an exception).
1554 __ bind(&non_function);
1555 // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
1556 // be awesome instead; i.e. a trivial improvement would be to call into the
1557 // runtime and just deal with the API function there instead of returning a
1558 // delegate from a runtime call that just jumps back to the runtime once
1559 // called. Or, bonus points, call directly into the C API function here, as
1560 // we do in some Crankshaft fast cases.
1561 // Overwrite the original receiver with the (original) target.
1562 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi);
1563 {
1564 // Determine the delegate for the target (if any).
1565 FrameScope scope(masm, StackFrame::INTERNAL);
1566 __ SmiTag(eax);
1567 __ Push(eax);
1568 __ Push(edi);
1569 __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
1570 __ mov(edi, eax);
1571 __ Pop(eax);
1572 __ SmiUntag(eax);
1573 }
1574 // The delegate is always a regular function.
1575 __ AssertFunction(edi);
1576 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
1577 }
1578
1579
1620 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 1580 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1621 // ----------- S t a t e ------------- 1581 // ----------- S t a t e -------------
1622 // -- eax : actual number of arguments 1582 // -- eax : actual number of arguments
1623 // -- ebx : expected number of arguments 1583 // -- ebx : expected number of arguments
1624 // -- edi : function (passed through to callee) 1584 // -- edi : function (passed through to callee)
1625 // ----------------------------------- 1585 // -----------------------------------
1626 1586
1627 Label invoke, dont_adapt_arguments; 1587 Label invoke, dont_adapt_arguments;
1628 __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1); 1588 __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
1629 1589
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1798 1758
1799 __ bind(&ok); 1759 __ bind(&ok);
1800 __ ret(0); 1760 __ ret(0);
1801 } 1761 }
1802 1762
1803 #undef __ 1763 #undef __
1804 } // namespace internal 1764 } // namespace internal
1805 } // namespace v8 1765 } // namespace v8
1806 1766
1807 #endif // V8_TARGET_ARCH_X87 1767 #endif // V8_TARGET_ARCH_X87
OLDNEW
« no previous file with comments | « src/x87/assembler-x87.cc ('k') | src/x87/code-stubs-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698