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

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

Issue 1523753002: [es6] Correct Function.prototype.apply, Reflect.construct and Reflect.apply. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: arm port. Small improvements. Created 5 years 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
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 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 __ j(not_sign, &loop); // While non-negative (to copy return address). 946 __ j(not_sign, &loop); // While non-negative (to copy return address).
947 __ pop(ebx); // Discard copy of return address. 947 __ pop(ebx); // Discard copy of return address.
948 __ dec(eax); // One fewer argument (first argument is new receiver). 948 __ dec(eax); // One fewer argument (first argument is new receiver).
949 } 949 }
950 950
951 // 4. Call the callable. 951 // 4. Call the callable.
952 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 952 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
953 } 953 }
954 954
955 955
956 static void Generate_PushAppliedArguments(MacroAssembler* masm, 956 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
957 const int vectorOffset, 957 // ----------- S t a t e -------------
958 const int argumentsOffset, 958 // -- eax : argc
959 const int indexOffset, 959 // -- esp[0] : return address
960 const int limitOffset) { 960 // -- esp[4] : argArray
961 // Copy all arguments from the array to the stack. 961 // -- esp[8] : thisArg
962 Label entry, loop; 962 // -- esp[12] : receiver
963 Register receiver = LoadDescriptor::ReceiverRegister(); 963 // -----------------------------------
964 Register key = LoadDescriptor::NameRegister(); 964
965 Register slot = LoadDescriptor::SlotRegister(); 965 // 1. Load receiver into edi, argArray into eax (if present), remove all
966 Register vector = LoadWithVectorDescriptor::VectorRegister(); 966 // arguments from the stack (including the receiver), and push thisArg (if
967 __ mov(key, Operand(ebp, indexOffset)); 967 // present) instead.
968 __ jmp(&entry); 968 {
969 __ bind(&loop); 969 Label no_arg_array, no_this_arg;
970 __ mov(receiver, Operand(ebp, argumentsOffset)); // load arguments 970 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex);
971 971 __ mov(ebx, edx);
972 // Use inline caching to speed up access to arguments. 972 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize));
973 int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); 973 __ test(eax, eax);
974 __ mov(slot, Immediate(Smi::FromInt(slot_index))); 974 __ j(zero, &no_this_arg, Label::kNear);
975 __ mov(vector, Operand(ebp, vectorOffset)); 975 {
976 Handle<Code> ic = 976 __ mov(edx, Operand(esp, eax, times_pointer_size, 0));
977 KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); 977 __ cmp(eax, Immediate(1));
978 __ call(ic, RelocInfo::CODE_TARGET); 978 __ j(equal, &no_arg_array, Label::kNear);
979 // It is important that we do not have a test instruction after the 979 __ mov(ebx, Operand(esp, eax, times_pointer_size, -kPointerSize));
980 // call. A test instruction after the call is used to indicate that 980 __ bind(&no_arg_array);
981 // we have generated an inline version of the keyed load. In this
982 // case, we know that we are not generating a test instruction next.
983
984 // Push the nth argument.
985 __ push(eax);
986
987 // Update the index on the stack and in register key.
988 __ mov(key, Operand(ebp, indexOffset));
989 __ add(key, Immediate(1 << kSmiTagSize));
990 __ mov(Operand(ebp, indexOffset), key);
991
992 __ bind(&entry);
993 __ cmp(key, Operand(ebp, limitOffset));
994 __ j(not_equal, &loop);
995
996 // On exit, the pushed arguments count is in eax, untagged
997 __ Move(eax, key);
998 __ SmiUntag(eax);
999 }
1000
1001
1002 // Used by FunctionApply and ReflectApply
1003 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1004 const int kFormalParameters = targetIsArgument ? 3 : 2;
1005 const int kStackSize = kFormalParameters + 1;
1006
1007 // Stack at entry:
1008 // esp : return address
1009 // esp[4] : arguments
1010 // esp[8] : receiver ("this")
1011 // esp[12] : function
1012 {
1013 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1014 // Stack frame:
1015 // ebp : Old base pointer
1016 // ebp[4] : return address
1017 // ebp[8] : function arguments
1018 // ebp[12] : receiver
1019 // ebp[16] : function
1020 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1021 static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1022 static const int kFunctionOffset = kReceiverOffset + kPointerSize;
1023 static const int kVectorOffset =
1024 InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
1025
1026 // Push the vector.
1027 __ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1028 __ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset));
1029 __ push(edi);
1030
1031 __ push(Operand(ebp, kFunctionOffset)); // push this
1032 __ push(Operand(ebp, kArgumentsOffset)); // push arguments
1033 if (targetIsArgument) {
1034 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX,
1035 CALL_FUNCTION);
1036 } else {
1037 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION);
1038 } 981 }
1039 982 __ bind(&no_this_arg);
1040 Generate_CheckStackOverflow(masm, kEaxIsSmiTagged); 983 __ PopReturnAddressTo(ecx);
1041 984 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1042 // Push current index and limit. 985 __ Push(edx);
1043 const int kLimitOffset = kVectorOffset - 1 * kPointerSize; 986 __ PushReturnAddressFrom(ecx);
1044 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 987 __ Move(eax, ebx);
1045 __ Push(eax); // limit 988 }
1046 __ Push(Immediate(0)); // index 989
1047 __ Push(Operand(ebp, kReceiverOffset)); // receiver 990 // ----------- S t a t e -------------
1048 991 // -- eax : argArray
1049 // Loop over the arguments array, pushing each value to the stack 992 // -- edi : receiver
1050 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, 993 // -- esp[0] : return address
1051 kIndexOffset, kLimitOffset); 994 // -- esp[4] : thisArg
1052 995 // -----------------------------------
1053 // Call the callable. 996
1054 // TODO(bmeurer): This should be a tail call according to ES6. 997 // 2. Make sure the receiver is actually callable.
1055 __ mov(edi, Operand(ebp, kFunctionOffset)); 998 Label receiver_not_callable;
1056 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 999 __ JumpIfSmi(edi, &receiver_not_callable, Label::kNear);
1057 1000 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));
1058 // Leave internal frame. 1001 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable);
1059 } 1002 __ j(zero, &receiver_not_callable, Label::kNear);
1060 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments 1003
1061 } 1004 // 3. Tail call with no arguments if argArray is null or undefined.
1062 1005 Label no_arguments;
1063 1006 __ JumpIfRoot(eax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear);
1064 // Used by ReflectConstruct 1007 __ JumpIfRoot(eax, Heap::kUndefinedValueRootIndex, &no_arguments,
1065 static void Generate_ConstructHelper(MacroAssembler* masm) { 1008 Label::kNear);
1066 const int kFormalParameters = 3; 1009
1067 const int kStackSize = kFormalParameters + 1; 1010 // 4a. Apply the receiver to the given argArray (passing undefined for
1068 1011 // new.target).
1069 // Stack at entry: 1012 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex);
1070 // esp : return address 1013 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1071 // esp[4] : new target 1014
1072 // esp[8] : arguments 1015 // 4b. The argArray is either null or undefined, so we tail call without any
1073 // esp[16] : constructor 1016 // arguments to the receiver.
1074 { 1017 __ bind(&no_arguments);
1075 FrameScope frame_scope(masm, StackFrame::INTERNAL); 1018 {
1076 // Stack frame: 1019 __ Set(eax, 0);
1077 // ebp : Old base pointer 1020 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1078 // ebp[4] : return address 1021 }
1079 // ebp[8] : new target 1022
1080 // ebp[12] : arguments 1023 // 4c. The receiver is not callable, throw an appropriate TypeError.
1081 // ebp[16] : constructor 1024 __ bind(&receiver_not_callable);
1082 static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; 1025 {
1083 static const int kArgumentsOffset = kNewTargetOffset + kPointerSize; 1026 __ mov(Operand(esp, kPointerSize), edi);
1084 static const int kFunctionOffset = kArgumentsOffset + kPointerSize; 1027 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1);
1085 static const int kVectorOffset = 1028 }
1086 InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
1087
1088 // Push the vector.
1089 __ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1090 __ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset));
1091 __ push(edi);
1092
1093 // If newTarget is not supplied, set it to constructor
1094 Label validate_arguments;
1095 __ mov(eax, Operand(ebp, kNewTargetOffset));
1096 __ CompareRoot(eax, Heap::kUndefinedValueRootIndex);
1097 __ j(not_equal, &validate_arguments, Label::kNear);
1098 __ mov(eax, Operand(ebp, kFunctionOffset));
1099 __ mov(Operand(ebp, kNewTargetOffset), eax);
1100
1101 // Validate arguments
1102 __ bind(&validate_arguments);
1103 __ push(Operand(ebp, kFunctionOffset));
1104 __ push(Operand(ebp, kArgumentsOffset));
1105 __ push(Operand(ebp, kNewTargetOffset));
1106 __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX,
1107 CALL_FUNCTION);
1108
1109 Generate_CheckStackOverflow(masm, kEaxIsSmiTagged);
1110
1111 // Push current index and limit.
1112 const int kLimitOffset = kVectorOffset - 1 * kPointerSize;
1113 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1114 __ Push(eax); // limit
1115 __ push(Immediate(0)); // index
1116 // Push the constructor function as callee.
1117 __ push(Operand(ebp, kFunctionOffset));
1118
1119 // Loop over the arguments array, pushing each value to the stack
1120 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
1121 kIndexOffset, kLimitOffset);
1122
1123 // Use undefined feedback vector
1124 __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex);
1125 __ mov(edi, Operand(ebp, kFunctionOffset));
1126 __ mov(edx, Operand(ebp, kNewTargetOffset));
1127
1128 // Call the function.
1129 __ Call(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1130
1131 // Leave internal frame.
1132 }
1133 // remove this, target, arguments, and newTarget
1134 __ ret(kStackSize * kPointerSize);
1135 }
1136
1137
1138 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1139 Generate_ApplyHelper(masm, false);
1140 } 1029 }
1141 1030
1142 1031
1143 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { 1032 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1144 Generate_ApplyHelper(masm, true); 1033 // ----------- S t a t e -------------
1034 // -- eax : argc
1035 // -- esp[0] : return address
1036 // -- esp[4] : argumentsList
1037 // -- esp[8] : thisArgument
1038 // -- esp[12] : target
1039 // -- esp[16] : receiver
1040 // -----------------------------------
1041
1042 // 1. Load target into edi (if present), argumentsList into eax (if present),
1043 // remove all arguments from the stack (including the receiver), and push
1044 // thisArgument (if present) instead.
1045 {
1046 Label done;
1047 __ LoadRoot(edi, Heap::kUndefinedValueRootIndex);
1048 __ mov(edx, edi);
1049 __ mov(ebx, edi);
1050 __ cmp(eax, Immediate(1));
1051 __ j(below, &done, Label::kNear);
1052 __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize));
1053 __ j(equal, &done, Label::kNear);
1054 __ mov(edx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize));
1055 __ cmp(eax, Immediate(3));
1056 __ j(below, &done, Label::kNear);
1057 __ mov(ebx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize));
1058 __ bind(&done);
1059 __ PopReturnAddressTo(ecx);
1060 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1061 __ Push(edx);
1062 __ PushReturnAddressFrom(ecx);
1063 __ Move(eax, ebx);
1064 }
1065
1066 // ----------- S t a t e -------------
1067 // -- eax : argumentsList
1068 // -- edi : target
1069 // -- esp[0] : return address
1070 // -- esp[4] : thisArgument
1071 // -----------------------------------
1072
1073 // 2. Make sure the target is actually callable.
1074 Label target_not_callable;
1075 __ JumpIfSmi(edi, &target_not_callable, Label::kNear);
1076 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));
1077 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable);
1078 __ j(zero, &target_not_callable, Label::kNear);
1079
1080 // 3a. Apply the target to the given argumentsList (passing undefined for
1081 // new.target).
1082 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex);
1083 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1084
1085 // 3b. The target is not callable, throw an appropriate TypeError.
1086 __ bind(&target_not_callable);
1087 {
1088 __ mov(Operand(esp, kPointerSize), edi);
1089 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1);
1090 }
1145 } 1091 }
1146 1092
1147 1093
1148 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { 1094 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1149 Generate_ConstructHelper(masm); 1095 // ----------- S t a t e -------------
1150 } 1096 // -- eax : argc
1151 1097 // -- esp[0] : return address
1152 1098 // -- esp[4] : new.target (optional)
1099 // -- esp[8] : argumentsList
1100 // -- esp[12] : target
1101 // -- esp[16] : receiver
1102 // -----------------------------------
1103
1104 // 1. Load target into edi (if present), argumentsList into eax (if present),
1105 // new.target into edx (if present, otherwise use target), remove all
1106 // arguments from the stack (including the receiver), and push thisArgument
1107 // (if present) instead.
1108 {
1109 Label done;
1110 __ LoadRoot(edi, Heap::kUndefinedValueRootIndex);
1111 __ mov(edx, edi);
1112 __ mov(ebx, edi);
1113 __ cmp(eax, Immediate(1));
1114 __ j(below, &done, Label::kNear);
1115 __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize));
1116 __ mov(edx, edi);
1117 __ j(equal, &done, Label::kNear);
1118 __ mov(ebx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize));
1119 __ cmp(eax, Immediate(3));
1120 __ j(below, &done, Label::kNear);
1121 __ mov(edx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize));
1122 __ bind(&done);
1123 __ PopReturnAddressTo(ecx);
1124 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1125 __ PushRoot(Heap::kUndefinedValueRootIndex);
1126 __ PushReturnAddressFrom(ecx);
1127 __ Move(eax, ebx);
1128 }
1129
1130 // ----------- S t a t e -------------
1131 // -- eax : argumentsList
1132 // -- edx : new.target
1133 // -- edi : target
1134 // -- esp[0] : return address
1135 // -- esp[4] : receiver (undefined)
1136 // -----------------------------------
1137
1138 // 2. Make sure the target is actually a constructor.
1139 Label target_not_constructor;
1140 __ JumpIfSmi(edi, &target_not_constructor, Label::kNear);
1141 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));
1142 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor);
1143 __ j(zero, &target_not_constructor, Label::kNear);
1144
1145 // 3. Make sure the target is actually a constructor.
1146 Label new_target_not_constructor;
1147 __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear);
1148 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
1149 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor);
1150 __ j(zero, &new_target_not_constructor, Label::kNear);
1151
1152 // 4a. Construct the target with the given new.target and argumentsList.
1153 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1154
1155 // 4b. The target is not a constructor, throw an appropriate TypeError.
1156 __ bind(&target_not_constructor);
1157 {
1158 __ mov(Operand(esp, kPointerSize), edi);
1159 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1);
1160 }
1161
1162 // 4c. The new.target is not a constructor, throw an appropriate TypeError.
1163 __ bind(&new_target_not_constructor);
1164 {
1165 __ mov(Operand(esp, kPointerSize), edx);
1166 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1);
1167 }
1168 }
1169
1170
1153 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 1171 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1154 // ----------- S t a t e ------------- 1172 // ----------- S t a t e -------------
1155 // -- eax : argc 1173 // -- eax : argc
1156 // -- esp[0] : return address 1174 // -- esp[0] : return address
1157 // -- esp[4] : last argument 1175 // -- esp[4] : last argument
1158 // ----------------------------------- 1176 // -----------------------------------
1159 Label generic_array_code; 1177 Label generic_array_code;
1160 1178
1161 // Get the InternalArray function. 1179 // Get the InternalArray function.
1162 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); 1180 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi);
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
1412 1430
1413 // Remove caller arguments from the stack. 1431 // Remove caller arguments from the stack.
1414 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 1432 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1415 __ pop(ecx); 1433 __ pop(ecx);
1416 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 1434 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
1417 __ push(ecx); 1435 __ push(ecx);
1418 } 1436 }
1419 1437
1420 1438
1421 // static 1439 // static
1440 void Builtins::Generate_Apply(MacroAssembler* masm) {
1441 // ----------- S t a t e -------------
1442 // -- eax : argumentsList
1443 // -- edi : target
1444 // -- edx : new.target (checked to be constructor or undefined)
1445 // -- esp[0] : return address.
1446 // -- esp[4] : thisArgument
1447 // -----------------------------------
1448
1449 // Create the list of arguments from the array-like argumentsList.
1450 {
1451 Label create_arguments, create_array, create_runtime, done_create;
1452 __ JumpIfSmi(eax, &create_runtime);
1453
1454 // Load the map of argumentsList into ecx.
1455 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
1456
1457 // Load native context into ebx.
1458 __ mov(ebx, NativeContextOperand());
1459
1460 // Check if argumentsList is an (unmodified) arguments object.
1461 __ cmp(ecx, ContextOperand(ebx, Context::SLOPPY_ARGUMENTS_MAP_INDEX));
1462 __ j(equal, &create_arguments);
1463 __ cmp(ecx, ContextOperand(ebx, Context::STRICT_ARGUMENTS_MAP_INDEX));
1464 __ j(equal, &create_arguments);
1465
1466 // Check if argumentsList is a fast JSArray.
1467 __ CmpInstanceType(ecx, JS_ARRAY_TYPE);
1468 __ j(equal, &create_array);
1469
1470 // Ask the runtime to create the list (actually a FixedArray).
1471 __ bind(&create_runtime);
1472 {
1473 FrameScope scope(masm, StackFrame::INTERNAL);
1474 __ Push(edi);
1475 __ Push(edx);
1476 __ Push(eax);
1477 __ CallRuntime(Runtime::kCreateListFromArrayLike, 1);
1478 __ Pop(edx);
1479 __ Pop(edi);
1480 __ mov(ebx, FieldOperand(eax, FixedArray::kLengthOffset));
1481 __ SmiUntag(ebx);
1482 }
1483 __ jmp(&done_create);
1484
1485 // Try to create the list from an arguments object.
1486 __ bind(&create_arguments);
1487 __ mov(ebx,
1488 FieldOperand(eax, JSObject::kHeaderSize +
1489 Heap::kArgumentsLengthIndex * kPointerSize));
1490 __ mov(ecx, FieldOperand(eax, JSObject::kElementsOffset));
1491 __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
1492 __ j(not_equal, &create_runtime);
1493 __ SmiUntag(ebx);
1494 __ mov(eax, ecx);
1495 __ jmp(&done_create);
1496
1497 // Try to create the list from a JSArray object.
1498 __ bind(&create_array);
1499 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset));
1500 __ DecodeField<Map::ElementsKindBits>(ecx);
1501 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
1502 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
1503 STATIC_ASSERT(FAST_ELEMENTS == 2);
1504 __ cmp(ecx, Immediate(FAST_ELEMENTS));
1505 __ j(above, &create_runtime);
1506 __ cmp(ecx, Immediate(FAST_HOLEY_SMI_ELEMENTS));
1507 __ j(equal, &create_runtime);
1508 __ mov(ebx, FieldOperand(eax, JSArray::kLengthOffset));
1509 __ SmiUntag(ebx);
1510 __ mov(eax, FieldOperand(eax, JSArray::kElementsOffset));
1511
1512 __ bind(&done_create);
1513 }
1514
1515 // Check for stack overflow.
1516 {
1517 // Check the stack for overflow. We are not trying to catch interruptions
1518 // (i.e. debug break and preemption) here, so check the "real stack limit".
1519 Label done;
1520 ExternalReference real_stack_limit =
1521 ExternalReference::address_of_real_stack_limit(masm->isolate());
1522 __ mov(ecx, Operand::StaticVariable(real_stack_limit));
1523 // Make ecx the space we have left. The stack might already be overflowed
1524 // here which will cause ecx to become negative.
1525 __ neg(ecx);
1526 __ add(ecx, esp);
1527 __ sar(ecx, kPointerSizeLog2);
1528 // Check if the arguments will overflow the stack.
1529 __ cmp(ecx, ebx);
1530 __ j(greater, &done, Label::kNear); // Signed comparison.
1531 __ TailCallRuntime(Runtime::kThrowStackOverflow, 1, 1);
1532 __ bind(&done);
1533 }
1534
1535 // ----------- S t a t e -------------
1536 // -- edi : target
1537 // -- eax : args (a FixedArray built from argumentsList)
1538 // -- ebx : len (number of elements to push from args)
1539 // -- edx : new.target (checked to be constructor or undefined)
1540 // -- esp[0] : return address.
1541 // -- esp[4] : thisArgument
1542 // -----------------------------------
1543
1544 // Push arguments onto the stack (thisArgument is already on the stack).
1545 {
1546 __ movd(xmm0, edx);
1547 __ PopReturnAddressTo(edx);
1548 __ Move(ecx, Immediate(0));
1549 Label done, loop;
1550 __ bind(&loop);
1551 __ cmp(ecx, ebx);
1552 __ j(equal, &done, Label::kNear);
1553 __ Push(
1554 FieldOperand(eax, ecx, times_pointer_size, FixedArray::kHeaderSize));
1555 __ inc(ecx);
1556 __ jmp(&loop);
1557 __ bind(&done);
1558 __ PushReturnAddressFrom(edx);
1559 __ movd(edx, xmm0);
1560 __ Move(eax, ebx);
1561 }
1562
1563 // Dispatch to Call or Construct depending on whether new.target is undefined.
1564 {
1565 __ CompareRoot(edx, Heap::kUndefinedValueRootIndex);
1566 __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1567 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1568 }
1569 }
1570
1571
1572 // static
1422 void Builtins::Generate_CallFunction(MacroAssembler* masm, 1573 void Builtins::Generate_CallFunction(MacroAssembler* masm,
1423 ConvertReceiverMode mode) { 1574 ConvertReceiverMode mode) {
1424 // ----------- S t a t e ------------- 1575 // ----------- S t a t e -------------
1425 // -- eax : the number of arguments (not including the receiver) 1576 // -- eax : the number of arguments (not including the receiver)
1426 // -- edi : the function to call (checked to be a JSFunction) 1577 // -- edi : the function to call (checked to be a JSFunction)
1427 // ----------------------------------- 1578 // -----------------------------------
1428 __ AssertFunction(edi); 1579 __ AssertFunction(edi);
1429 1580
1430 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) 1581 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1431 // Check that the function is not a "classConstructor". 1582 // Check that the function is not a "classConstructor".
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after
1976 2127
1977 __ bind(&ok); 2128 __ bind(&ok);
1978 __ ret(0); 2129 __ ret(0);
1979 } 2130 }
1980 2131
1981 #undef __ 2132 #undef __
1982 } // namespace internal 2133 } // namespace internal
1983 } // namespace v8 2134 } // namespace v8
1984 2135
1985 #endif // V8_TARGET_ARCH_IA32 2136 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« src/bootstrapper.cc ('K') | « src/contexts.h ('k') | src/js/runtime.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698