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

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

Issue 1328963004: Revert of [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/ia32/assembler-ia32.cc ('k') | src/ia32/code-stubs-ia32.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_IA32 5 #if V8_TARGET_ARCH_IA32
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
960 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { 959 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
961 // Stack Layout: 960 Factory* factory = masm->isolate()->factory();
962 // esp[0] : Return address 961
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 //
971 // 1. Make sure we have at least one argument. 962 // 1. Make sure we have at least one argument.
972 { 963 { Label done;
973 Label done;
974 __ test(eax, eax); 964 __ test(eax, eax);
975 __ j(not_zero, &done, Label::kNear); 965 __ j(not_zero, &done);
976 __ PopReturnAddressTo(ebx); 966 __ pop(ebx);
977 __ PushRoot(Heap::kUndefinedValueRootIndex); 967 __ push(Immediate(factory->undefined_value()));
978 __ PushReturnAddressFrom(ebx); 968 __ push(ebx);
979 __ inc(eax); 969 __ inc(eax);
980 __ bind(&done); 970 __ bind(&done);
981 } 971 }
982 972
983 // 2. Get the callable to call (passed as receiver) from the stack. 973 // 2. Get the function to call (passed as receiver) from the stack, check
984 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); 974 // if it is a function.
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);
985 981
986 // 3. Shift arguments and return address one slot down on the stack 982
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
987 // (overwriting the original receiver). Adjust argument count to make 1062 // (overwriting the original receiver). Adjust argument count to make
988 // the original first argument the new receiver. 1063 // the original first argument the new receiver.
989 { 1064 __ bind(&shift_arguments);
990 Label loop; 1065 { Label loop;
991 __ mov(ecx, eax); 1066 __ mov(ecx, eax);
992 __ bind(&loop); 1067 __ bind(&loop);
993 __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0)); 1068 __ mov(ebx, Operand(esp, ecx, times_4, 0));
994 __ mov(Operand(esp, ecx, times_pointer_size, kPointerSize), ebx); 1069 __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx);
995 __ dec(ecx); 1070 __ dec(ecx);
996 __ j(not_sign, &loop); // While non-negative (to copy return address). 1071 __ j(not_sign, &loop); // While non-negative (to copy return address).
997 __ pop(ebx); // Discard copy of return address. 1072 __ pop(ebx); // Discard copy of return address.
998 __ dec(eax); // One fewer argument (first argument is new receiver). 1073 __ dec(eax); // One fewer argument (first argument is new receiver).
999 } 1074 }
1000 1075
1001 // 4. Call the callable. 1076 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1002 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1077 // or a function proxy via CALL_FUNCTION_PROXY.
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());
1003 } 1114 }
1004 1115
1005 1116
1006 static void Generate_PushAppliedArguments(MacroAssembler* masm, 1117 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1007 const int argumentsOffset, 1118 const int argumentsOffset,
1008 const int indexOffset, 1119 const int indexOffset,
1009 const int limitOffset) { 1120 const int limitOffset) {
1010 // Copy all arguments from the array to the stack. 1121 // Copy all arguments from the array to the stack.
1011 Label entry, loop; 1122 Label entry, loop;
1012 Register receiver = LoadDescriptor::ReceiverRegister(); 1123 Register receiver = LoadDescriptor::ReceiverRegister();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 // Stack frame: 1178 // Stack frame:
1068 // ebp : Old base pointer 1179 // ebp : Old base pointer
1069 // ebp[4] : return address 1180 // ebp[4] : return address
1070 // ebp[8] : function arguments 1181 // ebp[8] : function arguments
1071 // ebp[12] : receiver 1182 // ebp[12] : receiver
1072 // ebp[16] : function 1183 // ebp[16] : function
1073 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; 1184 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1074 static const int kReceiverOffset = kArgumentsOffset + kPointerSize; 1185 static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1075 static const int kFunctionOffset = kReceiverOffset + kPointerSize; 1186 static const int kFunctionOffset = kReceiverOffset + kPointerSize;
1076 1187
1077 __ push(Operand(ebp, kFunctionOffset)); // push this 1188 __ push(Operand(ebp, kFunctionOffset)); // push this
1078 __ push(Operand(ebp, kArgumentsOffset)); // push arguments 1189 __ push(Operand(ebp, kArgumentsOffset)); // push arguments
1079 if (targetIsArgument) { 1190 if (targetIsArgument) {
1080 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, 1191 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX,
1081 CALL_FUNCTION); 1192 CALL_FUNCTION);
1082 } else { 1193 } else {
1083 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); 1194 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION);
1084 } 1195 }
1085 1196
1086 Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged); 1197 Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged);
1087 1198
1088 // Push current index and limit. 1199 // Push current index and limit.
1089 const int kLimitOffset = 1200 const int kLimitOffset =
1090 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 1201 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1091 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 1202 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1092 __ Push(eax); // limit 1203 __ push(eax); // limit
1093 __ Push(Immediate(0)); // index 1204 __ push(Immediate(0)); // index
1094 __ Push(Operand(ebp, kReceiverOffset)); // receiver 1205
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);
1095 1260
1096 // Loop over the arguments array, pushing each value to the stack 1261 // Loop over the arguments array, pushing each value to the stack
1097 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset, 1262 Generate_PushAppliedArguments(
1098 kLimitOffset); 1263 masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1099 1264
1100 // Call the callable. 1265 // Call the function.
1101 // TODO(bmeurer): This should be a tail call according to ES6. 1266 Label call_proxy;
1267 ParameterCount actual(eax);
1102 __ mov(edi, Operand(ebp, kFunctionOffset)); 1268 __ mov(edi, Operand(ebp, kFunctionOffset));
1103 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1269 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
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);
1104 1284
1105 // Leave internal frame. 1285 // Leave internal frame.
1106 } 1286 }
1107 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments 1287 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1108 } 1288 }
1109 1289
1110 1290
1111 // Used by ReflectConstruct 1291 // Used by ReflectConstruct
1112 static void Generate_ConstructHelper(MacroAssembler* masm) { 1292 static void Generate_ConstructHelper(MacroAssembler* masm) {
1113 const int kFormalParameters = 3; 1293 const int kFormalParameters = 3;
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 __ leave(); 1610 __ leave();
1431 1611
1432 // Remove caller arguments from the stack. 1612 // Remove caller arguments from the stack.
1433 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 1613 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1434 __ pop(ecx); 1614 __ pop(ecx);
1435 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 1615 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
1436 __ push(ecx); 1616 __ push(ecx);
1437 } 1617 }
1438 1618
1439 1619
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
1580 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 1620 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1581 // ----------- S t a t e ------------- 1621 // ----------- S t a t e -------------
1582 // -- eax : actual number of arguments 1622 // -- eax : actual number of arguments
1583 // -- ebx : expected number of arguments 1623 // -- ebx : expected number of arguments
1584 // -- edi : function (passed through to callee) 1624 // -- edi : function (passed through to callee)
1585 // ----------------------------------- 1625 // -----------------------------------
1586 1626
1587 Label invoke, dont_adapt_arguments; 1627 Label invoke, dont_adapt_arguments;
1588 __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1); 1628 __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
1589 1629
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1758 1798
1759 __ bind(&ok); 1799 __ bind(&ok);
1760 __ ret(0); 1800 __ ret(0);
1761 } 1801 }
1762 1802
1763 #undef __ 1803 #undef __
1764 } // namespace internal 1804 } // namespace internal
1765 } // namespace v8 1805 } // namespace v8
1766 1806
1767 #endif // V8_TARGET_ARCH_IA32 1807 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698