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

Side by Side Diff: src/x64/builtins-x64.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_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 989 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 __ j(not_zero, &loop); // While non-zero. 1000 __ j(not_zero, &loop); // While non-zero.
1001 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address. 1001 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address.
1002 __ decp(rax); // One fewer argument (first argument is new receiver). 1002 __ decp(rax); // One fewer argument (first argument is new receiver).
1003 } 1003 }
1004 1004
1005 // 4. Call the callable. 1005 // 4. Call the callable.
1006 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1006 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1007 } 1007 }
1008 1008
1009 1009
1010 static void Generate_PushAppliedArguments(MacroAssembler* masm, 1010 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1011 const int vectorOffset, 1011 // ----------- S t a t e -------------
1012 const int argumentsOffset, 1012 // -- rax : argc
1013 const int indexOffset, 1013 // -- rsp[0] : return address
1014 const int limitOffset) { 1014 // -- rsp[8] : argArray
1015 Register receiver = LoadDescriptor::ReceiverRegister(); 1015 // -- rsp[16] : thisArg
1016 Register key = LoadDescriptor::NameRegister(); 1016 // -- rsp[24] : receiver
1017 Register slot = LoadDescriptor::SlotRegister(); 1017 // -----------------------------------
1018 Register vector = LoadWithVectorDescriptor::VectorRegister(); 1018
1019 1019 // 1. Load receiver into rdi, argArray into rax (if present), remove all
1020 // Copy all arguments from the array to the stack. 1020 // arguments from the stack (including the receiver), and push thisArg (if
1021 Label entry, loop; 1021 // present) instead.
1022 __ movp(key, Operand(rbp, indexOffset)); 1022 {
1023 __ jmp(&entry); 1023 Label no_arg_array, no_this_arg;
1024 __ bind(&loop); 1024 StackArgumentsAccessor args(rsp, rax);
1025 __ movp(receiver, Operand(rbp, argumentsOffset)); // load arguments 1025 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
1026 1026 __ movp(rbx, rdx);
1027 // Use inline caching to speed up access to arguments. 1027 __ movp(rdi, args.GetReceiverOperand());
1028 int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); 1028 __ testp(rax, rax);
1029 __ Move(slot, Smi::FromInt(slot_index)); 1029 __ j(zero, &no_this_arg, Label::kNear);
1030 __ movp(vector, Operand(rbp, vectorOffset)); 1030 {
1031 Handle<Code> ic = 1031 __ movp(rdx, args.GetArgumentOperand(1));
1032 KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); 1032 __ cmpp(rax, Immediate(1));
1033 __ Call(ic, RelocInfo::CODE_TARGET); 1033 __ j(equal, &no_arg_array, Label::kNear);
1034 // It is important that we do not have a test instruction after the 1034 __ movp(rbx, args.GetArgumentOperand(2));
1035 // call. A test instruction after the call is used to indicate that 1035 __ bind(&no_arg_array);
1036 // we have generated an inline version of the keyed load. In this
1037 // case, we know that we are not generating a test instruction next.
1038
1039 // Push the nth argument.
1040 __ Push(rax);
1041
1042 // Update the index on the stack and in register key.
1043 __ movp(key, Operand(rbp, indexOffset));
1044 __ SmiAddConstant(key, key, Smi::FromInt(1));
1045 __ movp(Operand(rbp, indexOffset), key);
1046
1047 __ bind(&entry);
1048 __ cmpp(key, Operand(rbp, limitOffset));
1049 __ j(not_equal, &loop);
1050
1051 // On exit, the pushed arguments count is in rax, untagged
1052 __ SmiToInteger64(rax, key);
1053 }
1054
1055
1056 // Used by FunctionApply and ReflectApply
1057 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1058 const int kFormalParameters = targetIsArgument ? 3 : 2;
1059 const int kStackSize = kFormalParameters + 1;
1060
1061 // Stack at entry:
1062 // rsp : return address
1063 // rsp[8] : arguments
1064 // rsp[16] : receiver ("this")
1065 // rsp[24] : function
1066 {
1067 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1068 // Stack frame:
1069 // rbp : Old base pointer
1070 // rbp[8] : return address
1071 // rbp[16] : function arguments
1072 // rbp[24] : receiver
1073 // rbp[32] : function
1074 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1075 static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1076 static const int kFunctionOffset = kReceiverOffset + kPointerSize;
1077 static const int kVectorOffset =
1078 InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
1079
1080 // Push the vector.
1081 __ movp(rdi, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1082 __ movp(rdi, FieldOperand(rdi, SharedFunctionInfo::kFeedbackVectorOffset));
1083 __ Push(rdi);
1084
1085 __ Push(Operand(rbp, kFunctionOffset));
1086 __ Push(Operand(rbp, kArgumentsOffset));
1087 if (targetIsArgument) {
1088 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX,
1089 CALL_FUNCTION);
1090 } else {
1091 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION);
1092 } 1036 }
1093 1037 __ bind(&no_this_arg);
1094 Generate_CheckStackOverflow(masm, kRaxIsSmiTagged); 1038 __ PopReturnAddressTo(rcx);
1095 1039 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
1096 // Push current index and limit, and receiver. 1040 __ Push(rdx);
1097 const int kLimitOffset = kVectorOffset - 1 * kPointerSize; 1041 __ PushReturnAddressFrom(rcx);
1098 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 1042 __ movp(rax, rbx);
1099 __ Push(rax); // limit 1043 }
1100 __ Push(Immediate(0)); // index 1044
1101 __ Push(Operand(rbp, kReceiverOffset)); // receiver 1045 // ----------- S t a t e -------------
1102 1046 // -- rax : argArray
1103 // Loop over the arguments array, pushing each value to the stack 1047 // -- rdi : receiver
1104 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, 1048 // -- rsp[0] : return address
1105 kIndexOffset, kLimitOffset); 1049 // -- rsp[8] : thisArg
1106 1050 // -----------------------------------
1107 // Call the callable. 1051
1108 // TODO(bmeurer): This should be a tail call according to ES6. 1052 // 2. Make sure the receiver is actually callable.
1109 __ movp(rdi, Operand(rbp, kFunctionOffset)); 1053 Label receiver_not_callable;
1110 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1054 __ JumpIfSmi(rdi, &receiver_not_callable, Label::kNear);
1111 1055 __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset));
1112 // Leave internal frame. 1056 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
1113 } 1057 Immediate(1 << Map::kIsCallable));
1114 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments 1058 __ j(zero, &receiver_not_callable, Label::kNear);
1115 } 1059
1116 1060 // 3. Tail call with no arguments if argArray is null or undefined.
1117 1061 Label no_arguments;
1118 // Used by ReflectConstruct 1062 __ JumpIfRoot(rax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear);
1119 static void Generate_ConstructHelper(MacroAssembler* masm) { 1063 __ JumpIfRoot(rax, Heap::kUndefinedValueRootIndex, &no_arguments,
1120 const int kFormalParameters = 3; 1064 Label::kNear);
1121 const int kStackSize = kFormalParameters + 1; 1065
1122 1066 // 4a. Apply the receiver to the given argArray (passing undefined for
1123 // Stack at entry: 1067 // new.target).
1124 // rsp : return address 1068 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
1125 // rsp[8] : new target 1069 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1126 // rsp[16] : arguments 1070
1127 // rsp[24] : constructor 1071 // 4b. The argArray is either null or undefined, so we tail call without any
1128 { 1072 // arguments to the receiver.
1129 FrameScope frame_scope(masm, StackFrame::INTERNAL); 1073 __ bind(&no_arguments);
1130 // Stack frame: 1074 {
1131 // rbp : Old base pointer 1075 __ Set(rax, 0);
1132 // rbp[8] : return address 1076 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1133 // rbp[16] : new target 1077 }
1134 // rbp[24] : arguments 1078
1135 // rbp[32] : constructor 1079 // 4c. The receiver is not callable, throw an appropriate TypeError.
1136 static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; 1080 __ bind(&receiver_not_callable);
1137 static const int kArgumentsOffset = kNewTargetOffset + kPointerSize; 1081 {
1138 static const int kFunctionOffset = kArgumentsOffset + kPointerSize; 1082 StackArgumentsAccessor args(rsp, 0);
1139 1083 __ movp(args.GetReceiverOperand(), rdi);
1140 static const int kVectorOffset = 1084 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1);
1141 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; 1085 }
1142
1143 // Push the vector.
1144 __ movp(rdi, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1145 __ movp(rdi, FieldOperand(rdi, SharedFunctionInfo::kFeedbackVectorOffset));
1146 __ Push(rdi);
1147
1148 // If newTarget is not supplied, set it to constructor
1149 Label validate_arguments;
1150 __ movp(rax, Operand(rbp, kNewTargetOffset));
1151 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1152 __ j(not_equal, &validate_arguments, Label::kNear);
1153 __ movp(rax, Operand(rbp, kFunctionOffset));
1154 __ movp(Operand(rbp, kNewTargetOffset), rax);
1155
1156 // Validate arguments
1157 __ bind(&validate_arguments);
1158 __ Push(Operand(rbp, kFunctionOffset));
1159 __ Push(Operand(rbp, kArgumentsOffset));
1160 __ Push(Operand(rbp, kNewTargetOffset));
1161 __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX,
1162 CALL_FUNCTION);
1163
1164 Generate_CheckStackOverflow(masm, kRaxIsSmiTagged);
1165
1166 // Push current index and limit.
1167 const int kLimitOffset = kVectorOffset - 1 * kPointerSize;
1168 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1169 __ Push(rax); // limit
1170 __ Push(Immediate(0)); // index
1171 // Push the constructor function as callee.
1172 __ Push(Operand(rbp, kFunctionOffset));
1173
1174 // Loop over the arguments array, pushing each value to the stack
1175 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
1176 kIndexOffset, kLimitOffset);
1177
1178 // Use undefined feedback vector
1179 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
1180 __ movp(rdi, Operand(rbp, kFunctionOffset));
1181 __ movp(rdx, Operand(rbp, kNewTargetOffset));
1182
1183 // Call the function.
1184 __ Call(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1185
1186 // Leave internal frame.
1187 }
1188 // remove this, target, arguments and newTarget
1189 __ ret(kStackSize * kPointerSize);
1190 }
1191
1192
1193 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1194 Generate_ApplyHelper(masm, false);
1195 } 1086 }
1196 1087
1197 1088
1198 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { 1089 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1199 Generate_ApplyHelper(masm, true); 1090 // ----------- S t a t e -------------
1091 // -- rax : argc
1092 // -- rsp[0] : return address
1093 // -- rsp[8] : argumentsList
1094 // -- rsp[16] : thisArgument
1095 // -- rsp[24] : target
1096 // -- rsp[32] : receiver
1097 // -----------------------------------
1098
1099 // 1. Load target into rdi (if present), argumentsList into rax (if present),
1100 // remove all arguments from the stack (including the receiver), and push
1101 // thisArgument (if present) instead.
1102 {
1103 Label done;
1104 StackArgumentsAccessor args(rsp, rax);
1105 __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex);
1106 __ movp(rdx, rdi);
1107 __ movp(rbx, rdi);
1108 __ cmpp(rax, Immediate(1));
1109 __ j(below, &done, Label::kNear);
1110 __ movp(rdi, args.GetArgumentOperand(1)); // target
1111 __ j(equal, &done, Label::kNear);
1112 __ movp(rdx, args.GetArgumentOperand(2)); // thisArgument
1113 __ cmpp(rax, Immediate(3));
1114 __ j(below, &done, Label::kNear);
1115 __ movp(rbx, args.GetArgumentOperand(3)); // argumentsList
1116 __ bind(&done);
1117 __ PopReturnAddressTo(rcx);
1118 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
1119 __ Push(rdx);
1120 __ PushReturnAddressFrom(rcx);
1121 __ movp(rax, rbx);
1122 }
1123
1124 // ----------- S t a t e -------------
1125 // -- rax : argumentsList
1126 // -- rdi : target
1127 // -- rsp[0] : return address
1128 // -- rsp[8] : thisArgument
1129 // -----------------------------------
1130
1131 // 2. Make sure the target is actually callable.
1132 Label target_not_callable;
1133 __ JumpIfSmi(rdi, &target_not_callable, Label::kNear);
1134 __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset));
1135 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
1136 Immediate(1 << Map::kIsCallable));
1137 __ j(zero, &target_not_callable, Label::kNear);
1138
1139 // 3a. Apply the target to the given argumentsList (passing undefined for
1140 // new.target).
1141 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
1142 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1143
1144 // 3b. The target is not callable, throw an appropriate TypeError.
1145 __ bind(&target_not_callable);
1146 {
1147 StackArgumentsAccessor args(rsp, 0);
1148 __ movp(args.GetReceiverOperand(), rdi);
1149 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1);
1150 }
1200 } 1151 }
1201 1152
1202 1153
1203 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { 1154 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1204 Generate_ConstructHelper(masm); 1155 // ----------- S t a t e -------------
1205 } 1156 // -- rax : argc
1206 1157 // -- rsp[0] : return address
1207 1158 // -- rsp[8] : new.target (optional)
1159 // -- rsp[16] : argumentsList
1160 // -- rsp[24] : target
1161 // -- rsp[32] : receiver
1162 // -----------------------------------
1163
1164 // 1. Load target into rdi (if present), argumentsList into rax (if present),
1165 // new.target into rdx (if present, otherwise use target), remove all
1166 // arguments from the stack (including the receiver), and push thisArgument
1167 // (if present) instead.
1168 {
1169 Label done;
1170 StackArgumentsAccessor args(rsp, rax);
1171 __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex);
1172 __ movp(rdx, rdi);
1173 __ movp(rbx, rdi);
1174 __ cmpp(rax, Immediate(1));
1175 __ j(below, &done, Label::kNear);
1176 __ movp(rdi, args.GetArgumentOperand(1)); // target
1177 __ movp(rdx, rdi); // new.target defaults to target
1178 __ j(equal, &done, Label::kNear);
1179 __ movp(rbx, args.GetArgumentOperand(2)); // argumentsList
1180 __ cmpp(rax, Immediate(3));
1181 __ j(below, &done, Label::kNear);
1182 __ movp(rdx, args.GetArgumentOperand(3)); // new.target
1183 __ bind(&done);
1184 __ PopReturnAddressTo(rcx);
1185 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
1186 __ PushRoot(Heap::kUndefinedValueRootIndex);
1187 __ PushReturnAddressFrom(rcx);
1188 __ movp(rax, rbx);
1189 }
1190
1191 // ----------- S t a t e -------------
1192 // -- rax : argumentsList
1193 // -- rdx : new.target
1194 // -- rdi : target
1195 // -- rsp[0] : return address
1196 // -- rsp[8] : receiver (undefined)
1197 // -----------------------------------
1198
1199 // 2. Make sure the target is actually a constructor.
1200 Label target_not_constructor;
1201 __ JumpIfSmi(rdi, &target_not_constructor, Label::kNear);
1202 __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset));
1203 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
1204 Immediate(1 << Map::kIsConstructor));
1205 __ j(zero, &target_not_constructor, Label::kNear);
1206
1207 // 3. Make sure the target is actually a constructor.
1208 Label new_target_not_constructor;
1209 __ JumpIfSmi(rdx, &new_target_not_constructor, Label::kNear);
1210 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
1211 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
1212 Immediate(1 << Map::kIsConstructor));
1213 __ j(zero, &new_target_not_constructor, Label::kNear);
1214
1215 // 4a. Construct the target with the given new.target and argumentsList.
1216 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1217
1218 // 4b. The target is not a constructor, throw an appropriate TypeError.
1219 __ bind(&target_not_constructor);
1220 {
1221 StackArgumentsAccessor args(rsp, 0);
1222 __ movp(args.GetReceiverOperand(), rdi);
1223 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1);
1224 }
1225
1226 // 4c. The new.target is not a constructor, throw an appropriate TypeError.
1227 __ bind(&new_target_not_constructor);
1228 {
1229 StackArgumentsAccessor args(rsp, 0);
1230 __ movp(args.GetReceiverOperand(), rdx);
1231 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1);
1232 }
1233 }
1234
1235
1208 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 1236 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1209 // ----------- S t a t e ------------- 1237 // ----------- S t a t e -------------
1210 // -- rax : argc 1238 // -- rax : argc
1211 // -- rsp[0] : return address 1239 // -- rsp[0] : return address
1212 // -- rsp[8] : last argument 1240 // -- rsp[8] : last argument
1213 // ----------------------------------- 1241 // -----------------------------------
1214 Label generic_array_code; 1242 Label generic_array_code;
1215 1243
1216 // Get the InternalArray function. 1244 // Get the InternalArray function.
1217 __ LoadNativeContextSlot(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi); 1245 __ LoadNativeContextSlot(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi);
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
1606 __ bind(&stack_overflow); 1634 __ bind(&stack_overflow);
1607 { 1635 {
1608 FrameScope frame(masm, StackFrame::MANUAL); 1636 FrameScope frame(masm, StackFrame::MANUAL);
1609 __ CallRuntime(Runtime::kThrowStackOverflow, 0); 1637 __ CallRuntime(Runtime::kThrowStackOverflow, 0);
1610 __ int3(); 1638 __ int3();
1611 } 1639 }
1612 } 1640 }
1613 1641
1614 1642
1615 // static 1643 // static
1644 void Builtins::Generate_Apply(MacroAssembler* masm) {
1645 // ----------- S t a t e -------------
1646 // -- rax : argumentsList
1647 // -- rdi : target
1648 // -- rdx : new.target (checked to be constructor or undefined)
1649 // -- rsp[0] : return address.
1650 // -- rsp[8] : thisArgument
1651 // -----------------------------------
1652
1653 // Create the list of arguments from the array-like argumentsList.
1654 {
1655 Label create_arguments, create_array, create_runtime, done_create;
1656 __ JumpIfSmi(rax, &create_runtime);
1657
1658 // Load the map of argumentsList into rcx.
1659 __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset));
1660
1661 // Load native context into rbx.
1662 __ movp(rbx, NativeContextOperand());
1663
1664 // Check if argumentsList is an (unmodified) arguments object.
1665 __ cmpp(rcx, ContextOperand(rbx, Context::SLOPPY_ARGUMENTS_MAP_INDEX));
1666 __ j(equal, &create_arguments);
1667 __ cmpp(rcx, ContextOperand(rbx, Context::STRICT_ARGUMENTS_MAP_INDEX));
1668 __ j(equal, &create_arguments);
1669
1670 // Check if argumentsList is a fast JSArray.
1671 __ CmpInstanceType(rcx, JS_ARRAY_TYPE);
1672 __ j(equal, &create_array);
1673
1674 // Ask the runtime to create the list (actually a FixedArray).
1675 __ bind(&create_runtime);
1676 {
1677 FrameScope scope(masm, StackFrame::INTERNAL);
1678 __ Push(rdi);
1679 __ Push(rdx);
1680 __ Push(rax);
1681 __ CallRuntime(Runtime::kCreateListFromArrayLike, 1);
1682 __ Pop(rdx);
1683 __ Pop(rdi);
1684 __ SmiToInteger32(rbx, FieldOperand(rax, FixedArray::kLengthOffset));
1685 }
1686 __ jmp(&done_create);
1687
1688 // Try to create the list from an arguments object.
1689 __ bind(&create_arguments);
1690 __ movp(rbx,
1691 FieldOperand(rax, JSObject::kHeaderSize +
1692 Heap::kArgumentsLengthIndex * kPointerSize));
1693 __ movp(rcx, FieldOperand(rax, JSObject::kElementsOffset));
1694 __ cmpp(rbx, FieldOperand(rcx, FixedArray::kLengthOffset));
1695 __ j(not_equal, &create_runtime);
1696 __ SmiToInteger32(rbx, rbx);
1697 __ movp(rax, rcx);
1698 __ jmp(&done_create);
1699
1700 // Try to create the list from a JSArray object.
1701 __ bind(&create_array);
1702 __ movzxbp(rcx, FieldOperand(rcx, Map::kBitField2Offset));
1703 __ DecodeField<Map::ElementsKindBits>(rcx);
1704 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
1705 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
1706 STATIC_ASSERT(FAST_ELEMENTS == 2);
1707 __ cmpl(rcx, Immediate(FAST_ELEMENTS));
1708 __ j(above, &create_runtime);
1709 __ cmpl(rcx, Immediate(FAST_HOLEY_SMI_ELEMENTS));
1710 __ j(equal, &create_runtime);
1711 __ SmiToInteger32(rbx, FieldOperand(rax, JSArray::kLengthOffset));
1712 __ movp(rax, FieldOperand(rax, JSArray::kElementsOffset));
1713
1714 __ bind(&done_create);
1715 }
1716
1717 // Check for stack overflow.
1718 {
1719 // Check the stack for overflow. We are not trying to catch interruptions
1720 // (i.e. debug break and preemption) here, so check the "real stack limit".
1721 Label done;
1722 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
1723 __ movp(rcx, rsp);
1724 // Make rcx the space we have left. The stack might already be overflowed
1725 // here which will cause rcx to become negative.
1726 __ subp(rcx, kScratchRegister);
1727 __ sarp(rcx, Immediate(kPointerSizeLog2));
1728 // Check if the arguments will overflow the stack.
1729 __ cmpp(rcx, rbx);
1730 __ j(greater, &done, Label::kNear); // Signed comparison.
1731 __ TailCallRuntime(Runtime::kThrowStackOverflow, 1, 1);
1732 __ bind(&done);
1733 }
1734
1735 // ----------- S t a t e -------------
1736 // -- rdi : target
1737 // -- rax : args (a FixedArray built from argumentsList)
1738 // -- rbx : len (number of elements to push from args)
1739 // -- rdx : new.target (checked to be constructor or undefined)
1740 // -- rsp[0] : return address.
1741 // -- rsp[8] : thisArgument
1742 // -----------------------------------
1743
1744 // Push arguments onto the stack (thisArgument is already on the stack).
1745 {
1746 __ PopReturnAddressTo(r8);
1747 __ Set(rcx, 0);
1748 Label done, loop;
1749 __ bind(&loop);
1750 __ cmpl(rcx, rbx);
1751 __ j(equal, &done, Label::kNear);
1752 __ Push(
1753 FieldOperand(rax, rcx, times_pointer_size, FixedArray::kHeaderSize));
1754 __ incl(rcx);
1755 __ jmp(&loop);
1756 __ bind(&done);
1757 __ PushReturnAddressFrom(r8);
1758 __ Move(rax, rcx);
1759 }
1760
1761 // Dispatch to Call or Construct depending on whether new.target is undefined.
1762 {
1763 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
1764 __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1765 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1766 }
1767 }
1768
1769
1770 // static
1616 void Builtins::Generate_CallFunction(MacroAssembler* masm, 1771 void Builtins::Generate_CallFunction(MacroAssembler* masm,
1617 ConvertReceiverMode mode) { 1772 ConvertReceiverMode mode) {
1618 // ----------- S t a t e ------------- 1773 // ----------- S t a t e -------------
1619 // -- rax : the number of arguments (not including the receiver) 1774 // -- rax : the number of arguments (not including the receiver)
1620 // -- rdi : the function to call (checked to be a JSFunction) 1775 // -- rdi : the function to call (checked to be a JSFunction)
1621 // ----------------------------------- 1776 // -----------------------------------
1622 StackArgumentsAccessor args(rsp, rax); 1777 StackArgumentsAccessor args(rsp, rax);
1623 __ AssertFunction(rdi); 1778 __ AssertFunction(rdi);
1624 1779
1625 // ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) 1780 // ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
2051 __ ret(0); 2206 __ ret(0);
2052 } 2207 }
2053 2208
2054 2209
2055 #undef __ 2210 #undef __
2056 2211
2057 } // namespace internal 2212 } // namespace internal
2058 } // namespace v8 2213 } // namespace v8
2059 2214
2060 #endif // V8_TARGET_ARCH_X64 2215 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698