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

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

Issue 913073003: [es6] implement Reflect.apply() & Reflect.construct() (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove phantom edits Created 5 years, 9 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/runtime.js ('k') | test/mjsunit/harmony/reflect-apply.js » ('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 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_X64 7 #if V8_TARGET_ARCH_X64
8 8
9 #include "src/code-factory.h" 9 #include "src/code-factory.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after
1044 __ cmpp(rax, rbx); 1044 __ cmpp(rax, rbx);
1045 __ j(not_equal, 1045 __ j(not_equal,
1046 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1046 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1047 RelocInfo::CODE_TARGET); 1047 RelocInfo::CODE_TARGET);
1048 1048
1049 ParameterCount expected(0); 1049 ParameterCount expected(0);
1050 __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); 1050 __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, NullCallWrapper());
1051 } 1051 }
1052 1052
1053 1053
1054 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 1054 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1055 Register receiver, Register key,
1056 const int kArgumentsOffset,
1057 const int kIndexOffset,
Dmitry Lomov (no reviews) 2015/03/13 09:39:09 These are not constants anymore, name them indexOf
1058 const int kLimitOffset) {
1059 // Copy all arguments from the array to the stack.
1060 Label entry, loop;
1061 __ movp(key, Operand(rbp, kIndexOffset));
Dmitry Lomov (no reviews) 2015/03/13 09:39:09 Receiver and key must be LoadDescriptor::{Reeceive
1062 __ jmp(&entry);
1063 __ bind(&loop);
1064 __ movp(receiver, Operand(rbp, kArgumentsOffset)); // load arguments
1065
1066 // Use inline caching to speed up access to arguments.
1067 if (FLAG_vector_ics) {
1068 // TODO(mvstanton): Vector-based ics need additional infrastructure to
1069 // be embedded here. For now, just call the runtime.
1070 __ Push(receiver);
1071 __ Push(key);
1072 __ CallRuntime(Runtime::kGetProperty, 2);
1073 } else {
1074 Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
1075 __ Call(ic, RelocInfo::CODE_TARGET);
1076 // It is important that we do not have a test instruction after the
1077 // call. A test instruction after the call is used to indicate that
1078 // we have generated an inline version of the keyed load. In this
1079 // case, we know that we are not generating a test instruction next.
1080 }
1081
1082 // Push the nth argument.
1083 __ Push(rax);
1084
1085 // Update the index on the stack and in register key.
1086 __ movp(key, Operand(rbp, kIndexOffset));
1087 __ SmiAddConstant(key, key, Smi::FromInt(1));
1088 __ movp(Operand(rbp, kIndexOffset), key);
1089
1090 __ bind(&entry);
1091 __ cmpp(key, Operand(rbp, kLimitOffset));
1092 __ j(not_equal, &loop);
1093 }
1094
1095
1096 // Used by FunctionApply and ReflectApply
1097 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1098 const int kFormalParameters = targetIsArgument ? 3 : 2;
1099 const int kStackSize = kFormalParameters + 1;
1100
1055 // Stack at entry: 1101 // Stack at entry:
1056 // rsp : return address 1102 // rsp : return address
1057 // rsp[8] : arguments 1103 // rsp[8] : arguments
1058 // rsp[16] : receiver ("this") 1104 // rsp[16] : receiver ("this")
1059 // rsp[24] : function 1105 // rsp[24] : function
1060 { 1106 {
1061 FrameScope frame_scope(masm, StackFrame::INTERNAL); 1107 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1062 // Stack frame: 1108 // Stack frame:
1063 // rbp : Old base pointer 1109 // rbp : Old base pointer
1064 // rbp[8] : return address 1110 // rbp[8] : return address
1065 // rbp[16] : function arguments 1111 // rbp[16] : function arguments
1066 // rbp[24] : receiver 1112 // rbp[24] : receiver
1067 // rbp[32] : function 1113 // rbp[32] : function
1068 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; 1114 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1069 static const int kReceiverOffset = kArgumentsOffset + kPointerSize; 1115 static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1070 static const int kFunctionOffset = kReceiverOffset + kPointerSize; 1116 static const int kFunctionOffset = kReceiverOffset + kPointerSize;
1071 1117
1072 __ Push(Operand(rbp, kFunctionOffset)); 1118 __ Push(Operand(rbp, kFunctionOffset));
1073 __ Push(Operand(rbp, kArgumentsOffset)); 1119 __ Push(Operand(rbp, kArgumentsOffset));
1074 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 1120 if (targetIsArgument) {
1121 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION);
1122 } else {
1123 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1124 }
1075 1125
1076 // Check the stack for overflow. We are not trying to catch 1126 // Check the stack for overflow. We are not trying to catch
1077 // interruptions (e.g. debug break and preemption) here, so the "real stack 1127 // interruptions (e.g. debug break and preemption) here, so the "real stack
1078 // limit" is checked. 1128 // limit" is checked.
1079 Label okay; 1129 Label okay;
1080 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); 1130 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
1081 __ movp(rcx, rsp); 1131 __ movp(rcx, rsp);
1082 // Make rcx the space we have left. The stack might already be overflowed 1132 // Make rcx the space we have left. The stack might already be overflowed
1083 // here which will cause rcx to become negative. 1133 // here which will cause rcx to become negative.
1084 __ subp(rcx, kScratchRegister); 1134 __ subp(rcx, kScratchRegister);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 1199
1150 __ bind(&use_global_proxy); 1200 __ bind(&use_global_proxy);
1151 __ movp(rbx, 1201 __ movp(rbx,
1152 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 1202 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1153 __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset)); 1203 __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset));
1154 1204
1155 // Push the receiver. 1205 // Push the receiver.
1156 __ bind(&push_receiver); 1206 __ bind(&push_receiver);
1157 __ Push(rbx); 1207 __ Push(rbx);
1158 1208
1159 // Copy all arguments from the array to the stack.
1160 Label entry, loop;
1161 Register receiver = LoadDescriptor::ReceiverRegister(); 1209 Register receiver = LoadDescriptor::ReceiverRegister();
1162 Register key = LoadDescriptor::NameRegister(); 1210 Register key = LoadDescriptor::NameRegister();
1163 __ movp(key, Operand(rbp, kIndexOffset));
1164 __ jmp(&entry);
1165 __ bind(&loop);
1166 __ movp(receiver, Operand(rbp, kArgumentsOffset)); // load arguments
1167 1211
1168 // Use inline caching to speed up access to arguments. 1212 // Loop over the arguments array, pushing each value to the stack
1169 if (FLAG_vector_ics) { 1213 Generate_PushAppliedArguments(
1170 // TODO(mvstanton): Vector-based ics need additional infrastructure to 1214 masm, receiver, key, kArgumentsOffset, kIndexOffset, kLimitOffset);
1171 // be embedded here. For now, just call the runtime.
1172 __ Push(receiver);
1173 __ Push(key);
1174 __ CallRuntime(Runtime::kGetProperty, 2);
1175 } else {
1176 Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
1177 __ Call(ic, RelocInfo::CODE_TARGET);
1178 // It is important that we do not have a test instruction after the
1179 // call. A test instruction after the call is used to indicate that
1180 // we have generated an inline version of the keyed load. In this
1181 // case, we know that we are not generating a test instruction next.
1182 }
1183
1184 // Push the nth argument.
1185 __ Push(rax);
1186
1187 // Update the index on the stack and in register key.
1188 __ movp(key, Operand(rbp, kIndexOffset));
1189 __ SmiAddConstant(key, key, Smi::FromInt(1));
1190 __ movp(Operand(rbp, kIndexOffset), key);
1191
1192 __ bind(&entry);
1193 __ cmpp(key, Operand(rbp, kLimitOffset));
1194 __ j(not_equal, &loop);
1195 1215
1196 // Call the function. 1216 // Call the function.
1197 Label call_proxy; 1217 Label call_proxy;
1198 ParameterCount actual(rax); 1218 ParameterCount actual(rax);
1199 __ SmiToInteger32(rax, key); 1219 __ SmiToInteger32(rax, key);
1200 __ movp(rdi, Operand(rbp, kFunctionOffset)); 1220 __ movp(rdi, Operand(rbp, kFunctionOffset));
1201 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 1221 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1202 __ j(not_equal, &call_proxy); 1222 __ j(not_equal, &call_proxy);
1203 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); 1223 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
1204 1224
1205 frame_scope.GenerateLeaveFrame(); 1225 frame_scope.GenerateLeaveFrame();
1206 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 1226 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1207 1227
1208 // Call the function proxy. 1228 // Call the function proxy.
1209 __ bind(&call_proxy); 1229 __ bind(&call_proxy);
1210 __ Push(rdi); // add function proxy as last argument 1230 __ Push(rdi); // add function proxy as last argument
1211 __ incp(rax); 1231 __ incp(rax);
1212 __ Set(rbx, 0); 1232 __ Set(rbx, 0);
1213 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); 1233 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
1214 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1234 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1215 RelocInfo::CODE_TARGET); 1235 RelocInfo::CODE_TARGET);
1216 1236
1217 // Leave internal frame. 1237 // Leave internal frame.
1218 } 1238 }
1219 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 1239 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1220 } 1240 }
1221 1241
1222 1242
1243 // Used by ReflectConstruct
1244 static void Generate_ConstructHelper(MacroAssembler* masm) {
1245 const int kFormalParameters = 3;
1246 const int kStackSize = kFormalParameters + 1;
1247
1248 // Stack at entry:
1249 // rsp : return address
1250 // rsp[8] : original constructor (new.target)
1251 // rsp[16] : arguments
1252 // rsp[24] : constructor
1253 {
1254 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1255 // Stack frame:
1256 // rbp : Old base pointer
1257 // rbp[8] : return address
1258 // rbp[16] : function arguments
1259 // rbp[24] : receiver
1260 // rbp[32] : function
1261 static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
1262 static const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
1263 static const int kFunctionOffset = kArgumentsOffset + kPointerSize;
1264
1265 // If newTarget is not supplied, set it to constructor
1266 Label validate_arguments;
1267 __ movp(rax, Operand(rbp, kNewTargetOffset));
1268 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1269 __ j(not_equal, &validate_arguments, Label::kNear);
1270 __ movp(rax, Operand(rbp, kFunctionOffset));
1271 __ movp(Operand(rbp, kNewTargetOffset), rax);
1272
1273 // Validate arguments
1274 __ bind(&validate_arguments);
1275 __ Push(Operand(rbp, kFunctionOffset));
1276 __ Push(Operand(rbp, kArgumentsOffset));
1277 __ Push(Operand(rbp, kNewTargetOffset));
1278 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION);
1279
1280 // Check the stack for overflow. We are not trying to catch
Dmitry Lomov (no reviews) 2015/03/13 09:39:09 Please share the stack overflow check code between
caitp (gmail) 2015/03/13 15:10:37 I notice that the stack overflow check is running
Dmitry Lomov (no reviews) 2015/03/13 16:40:03 We can overshoot, so just make it 2 pointers alway
1281 // interruptions (e.g. debug break and preemption) here, so the "real stack
1282 // limit" is checked.
1283 Label okay;
1284 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
1285 __ movp(rcx, rsp);
1286 // Make rcx the space we have left. The stack might already be overflowed
1287 // here which will cause rcx to become negative.
1288 __ subp(rcx, kScratchRegister);
1289 // Make rdx the space we need for the array when it is unrolled onto the
1290 // stack.
1291 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2);
1292 // Check if the arguments will overflow the stack.
1293 __ cmpp(rcx, rdx);
1294 __ j(greater, &okay); // Signed comparison.
1295
1296 // Out of stack space.
1297 __ Push(Operand(rbp, kFunctionOffset));
1298 __ Push(rax);
1299 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1300 __ bind(&okay);
1301 // End of stack check.
1302
1303 // Push current index and limit.
1304 const int kLimitOffset =
1305 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1306 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1307 __ Push(rax); // limit
1308 __ Push(Immediate(0)); // index
1309 // Push newTarget and callee functions
1310 __ Push(Operand(rbp, kNewTargetOffset));
1311 __ Push(Operand(rbp, kFunctionOffset));
1312
1313 Register receiver = LoadDescriptor::ReceiverRegister();
1314 Register key = LoadDescriptor::NameRegister();
1315
1316 // Loop over the arguments array, pushing each value to the stack
1317 Generate_PushAppliedArguments(
1318 masm, receiver, key, kArgumentsOffset, kIndexOffset, kLimitOffset);
1319
1320 // Use undefined feedback vector
1321 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
1322
1323 __ movp(rax, Operand(rbp, kLimitOffset));
1324 __ SmiToInteger64(rax, rax);
1325 __ movp(rdi, Operand(rbp, kFunctionOffset));
1326
1327 // Call the function.
1328 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
1329 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
1330
1331 __ Drop(1);
1332
1333 // Leave internal frame.
1334 }
1335 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1336 }
1337
1338
1339 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1340 Generate_ApplyHelper(masm, false);
1341 }
1342
1343
1344 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1345 Generate_ApplyHelper(masm, true);
1346 }
1347
1348
1349 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1350 Generate_ConstructHelper(masm);
1351 }
1352
1353
1223 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 1354 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1224 // ----------- S t a t e ------------- 1355 // ----------- S t a t e -------------
1225 // -- rax : argc 1356 // -- rax : argc
1226 // -- rsp[0] : return address 1357 // -- rsp[0] : return address
1227 // -- rsp[8] : last argument 1358 // -- rsp[8] : last argument
1228 // ----------------------------------- 1359 // -----------------------------------
1229 Label generic_array_code; 1360 Label generic_array_code;
1230 1361
1231 // Get the InternalArray function. 1362 // Get the InternalArray function.
1232 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi); 1363 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi);
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
1615 __ bind(&ok); 1746 __ bind(&ok);
1616 __ ret(0); 1747 __ ret(0);
1617 } 1748 }
1618 1749
1619 1750
1620 #undef __ 1751 #undef __
1621 1752
1622 } } // namespace v8::internal 1753 } } // namespace v8::internal
1623 1754
1624 #endif // V8_TARGET_ARCH_X64 1755 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/runtime.js ('k') | test/mjsunit/harmony/reflect-apply.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698