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

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: Fix arm 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_CheckStackOverflow(MacroAssembler* masm,
1055 const int calleeOffset) {
1056 // rax : the number of items to be pushed to the stack
1057 //
1058 // Check the stack for overflow. We are not trying to catch
1059 // interruptions (e.g. debug break and preemption) here, so the "real stack
1060 // limit" is checked.
1061 Label okay;
1062 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
1063 __ movp(rcx, rsp);
1064 // Make rcx the space we have left. The stack might already be overflowed
1065 // here which will cause rcx to become negative.
1066 __ subp(rcx, kScratchRegister);
1067 // Make rdx the space we need for the array when it is unrolled onto the
1068 // stack.
1069 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2);
1070 // Check if the arguments will overflow the stack.
1071 __ cmpp(rcx, rdx);
1072 __ j(greater, &okay); // Signed comparison.
1073
1074 // Out of stack space.
1075 __ Push(Operand(rbp, calleeOffset));
1076 __ Push(rax);
1077 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1078
1079 __ bind(&okay);
1080 }
1081
1082
1083 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1084 const int argumentsOffset,
1085 const int indexOffset,
1086 const int limitOffset) {
1087 Register receiver = LoadDescriptor::ReceiverRegister();
1088 Register key = LoadDescriptor::NameRegister();
1089
1090 // Copy all arguments from the array to the stack.
1091 Label entry, loop;
1092 __ movp(key, Operand(rbp, indexOffset));
1093 __ jmp(&entry);
1094 __ bind(&loop);
1095 __ movp(receiver, Operand(rbp, argumentsOffset)); // load arguments
1096
1097 // Use inline caching to speed up access to arguments.
1098 if (FLAG_vector_ics) {
1099 // TODO(mvstanton): Vector-based ics need additional infrastructure to
1100 // be embedded here. For now, just call the runtime.
1101 __ Push(receiver);
1102 __ Push(key);
1103 __ CallRuntime(Runtime::kGetProperty, 2);
1104 } else {
1105 Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
1106 __ Call(ic, RelocInfo::CODE_TARGET);
1107 // It is important that we do not have a test instruction after the
1108 // call. A test instruction after the call is used to indicate that
1109 // we have generated an inline version of the keyed load. In this
1110 // case, we know that we are not generating a test instruction next.
1111 }
1112
1113 // Push the nth argument.
1114 __ Push(rax);
1115
1116 // Update the index on the stack and in register key.
1117 __ movp(key, Operand(rbp, indexOffset));
1118 __ SmiAddConstant(key, key, Smi::FromInt(1));
1119 __ movp(Operand(rbp, indexOffset), key);
1120
1121 __ bind(&entry);
1122 __ cmpp(key, Operand(rbp, limitOffset));
1123 __ j(not_equal, &loop);
1124
1125 // On exit, the pushed arguments count is in rax, untagged
1126 __ SmiToInteger64(rax, key);
1127 }
1128
1129
1130 // Used by FunctionApply and ReflectApply
1131 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1132 const int kFormalParameters = targetIsArgument ? 3 : 2;
1133 const int kStackSize = kFormalParameters + 1;
1134
1055 // Stack at entry: 1135 // Stack at entry:
1056 // rsp : return address 1136 // rsp : return address
1057 // rsp[8] : arguments 1137 // rsp[8] : arguments
1058 // rsp[16] : receiver ("this") 1138 // rsp[16] : receiver ("this")
1059 // rsp[24] : function 1139 // rsp[24] : function
1060 { 1140 {
1061 FrameScope frame_scope(masm, StackFrame::INTERNAL); 1141 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1062 // Stack frame: 1142 // Stack frame:
1063 // rbp : Old base pointer 1143 // rbp : Old base pointer
1064 // rbp[8] : return address 1144 // rbp[8] : return address
1065 // rbp[16] : function arguments 1145 // rbp[16] : function arguments
1066 // rbp[24] : receiver 1146 // rbp[24] : receiver
1067 // rbp[32] : function 1147 // rbp[32] : function
1068 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; 1148 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1069 static const int kReceiverOffset = kArgumentsOffset + kPointerSize; 1149 static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1070 static const int kFunctionOffset = kReceiverOffset + kPointerSize; 1150 static const int kFunctionOffset = kReceiverOffset + kPointerSize;
1071 1151
1072 __ Push(Operand(rbp, kFunctionOffset)); 1152 __ Push(Operand(rbp, kFunctionOffset));
1073 __ Push(Operand(rbp, kArgumentsOffset)); 1153 __ Push(Operand(rbp, kArgumentsOffset));
1074 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 1154 if (targetIsArgument) {
1155 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION);
1156 } else {
1157 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1158 }
1075 1159
1076 // Check the stack for overflow. We are not trying to catch 1160 Generate_CheckStackOverflow(masm, kFunctionOffset);
1077 // interruptions (e.g. debug break and preemption) here, so the "real stack
1078 // limit" is checked.
1079 Label okay;
1080 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
1081 __ movp(rcx, rsp);
1082 // Make rcx the space we have left. The stack might already be overflowed
1083 // here which will cause rcx to become negative.
1084 __ subp(rcx, kScratchRegister);
1085 // Make rdx the space we need for the array when it is unrolled onto the
1086 // stack.
1087 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2);
1088 // Check if the arguments will overflow the stack.
1089 __ cmpp(rcx, rdx);
1090 __ j(greater, &okay); // Signed comparison.
1091
1092 // Out of stack space.
1093 __ Push(Operand(rbp, kFunctionOffset));
1094 __ Push(rax);
1095 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1096 __ bind(&okay);
1097 // End of stack check.
1098 1161
1099 // Push current index and limit. 1162 // Push current index and limit.
1100 const int kLimitOffset = 1163 const int kLimitOffset =
1101 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 1164 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1102 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 1165 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1103 __ Push(rax); // limit 1166 __ Push(rax); // limit
1104 __ Push(Immediate(0)); // index 1167 __ Push(Immediate(0)); // index
1105 1168
1106 // Get the receiver. 1169 // Get the receiver.
1107 __ movp(rbx, Operand(rbp, kReceiverOffset)); 1170 __ movp(rbx, Operand(rbp, kReceiverOffset));
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 1212
1150 __ bind(&use_global_proxy); 1213 __ bind(&use_global_proxy);
1151 __ movp(rbx, 1214 __ movp(rbx,
1152 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 1215 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1153 __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset)); 1216 __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset));
1154 1217
1155 // Push the receiver. 1218 // Push the receiver.
1156 __ bind(&push_receiver); 1219 __ bind(&push_receiver);
1157 __ Push(rbx); 1220 __ Push(rbx);
1158 1221
1159 // Copy all arguments from the array to the stack. 1222 // Loop over the arguments array, pushing each value to the stack
1160 Label entry, loop; 1223 Generate_PushAppliedArguments(
1161 Register receiver = LoadDescriptor::ReceiverRegister(); 1224 masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1162 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
1168 // Use inline caching to speed up access to arguments.
1169 if (FLAG_vector_ics) {
1170 // TODO(mvstanton): Vector-based ics need additional infrastructure to
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 1225
1196 // Call the function. 1226 // Call the function.
1197 Label call_proxy; 1227 Label call_proxy;
1198 ParameterCount actual(rax); 1228 ParameterCount actual(rax);
1199 __ SmiToInteger32(rax, key);
1200 __ movp(rdi, Operand(rbp, kFunctionOffset)); 1229 __ movp(rdi, Operand(rbp, kFunctionOffset));
1201 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 1230 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1202 __ j(not_equal, &call_proxy); 1231 __ j(not_equal, &call_proxy);
1203 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); 1232 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
1204 1233
1205 frame_scope.GenerateLeaveFrame(); 1234 frame_scope.GenerateLeaveFrame();
1206 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 1235 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1207 1236
1208 // Call the function proxy. 1237 // Call the function proxy.
1209 __ bind(&call_proxy); 1238 __ bind(&call_proxy);
1210 __ Push(rdi); // add function proxy as last argument 1239 __ Push(rdi); // add function proxy as last argument
1211 __ incp(rax); 1240 __ incp(rax);
1212 __ Set(rbx, 0); 1241 __ Set(rbx, 0);
1213 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); 1242 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
1214 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1243 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1215 RelocInfo::CODE_TARGET); 1244 RelocInfo::CODE_TARGET);
1216 1245
1217 // Leave internal frame. 1246 // Leave internal frame.
1218 } 1247 }
1219 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 1248 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1220 } 1249 }
1221 1250
1222 1251
1252 // Used by ReflectConstruct
1253 static void Generate_ConstructHelper(MacroAssembler* masm) {
1254 const int kFormalParameters = 3;
1255 const int kStackSize = kFormalParameters + 1;
1256
1257 // Stack at entry:
1258 // rsp : return address
1259 // rsp[8] : original constructor (new.target)
1260 // rsp[16] : arguments
1261 // rsp[24] : constructor
1262 {
1263 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1264 // Stack frame:
1265 // rbp : Old base pointer
1266 // rbp[8] : return address
1267 // rbp[16] : original constructor (new.target)
1268 // rbp[24] : arguments
1269 // rbp[32] : constructor
1270 static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
1271 static const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
1272 static const int kFunctionOffset = kArgumentsOffset + kPointerSize;
1273
1274 // If newTarget is not supplied, set it to constructor
1275 Label validate_arguments;
1276 __ movp(rax, Operand(rbp, kNewTargetOffset));
1277 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1278 __ j(not_equal, &validate_arguments, Label::kNear);
1279 __ movp(rax, Operand(rbp, kFunctionOffset));
1280 __ movp(Operand(rbp, kNewTargetOffset), rax);
1281
1282 // Validate arguments
1283 __ bind(&validate_arguments);
1284 __ Push(Operand(rbp, kFunctionOffset));
1285 __ Push(Operand(rbp, kArgumentsOffset));
1286 __ Push(Operand(rbp, kNewTargetOffset));
1287 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION);
1288
1289 Generate_CheckStackOverflow(masm, kFunctionOffset);
1290
1291 // Push current index and limit.
1292 const int kLimitOffset =
1293 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1294 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1295 __ Push(rax); // limit
1296 __ Push(Immediate(0)); // index
1297 // Push newTarget and callee functions
1298 __ Push(Operand(rbp, kNewTargetOffset));
1299 __ Push(Operand(rbp, kFunctionOffset));
1300
1301 // Loop over the arguments array, pushing each value to the stack
1302 Generate_PushAppliedArguments(
1303 masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1304
1305 // Use undefined feedback vector
1306 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
1307 __ movp(rdi, Operand(rbp, kFunctionOffset));
1308
1309 // Call the function.
1310 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
1311 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
1312
1313 __ Drop(1);
1314
1315 // Leave internal frame.
1316 }
1317 // remove this, target, arguments and newTarget
1318 __ ret(kStackSize * kPointerSize);
1319 }
1320
1321
1322 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1323 Generate_ApplyHelper(masm, false);
1324 }
1325
1326
1327 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1328 Generate_ApplyHelper(masm, true);
1329 }
1330
1331
1332 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1333 Generate_ConstructHelper(masm);
1334 }
1335
1336
1223 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 1337 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1224 // ----------- S t a t e ------------- 1338 // ----------- S t a t e -------------
1225 // -- rax : argc 1339 // -- rax : argc
1226 // -- rsp[0] : return address 1340 // -- rsp[0] : return address
1227 // -- rsp[8] : last argument 1341 // -- rsp[8] : last argument
1228 // ----------------------------------- 1342 // -----------------------------------
1229 Label generic_array_code; 1343 Label generic_array_code;
1230 1344
1231 // Get the InternalArray function. 1345 // Get the InternalArray function.
1232 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi); 1346 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi);
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
1615 __ bind(&ok); 1729 __ bind(&ok);
1616 __ ret(0); 1730 __ ret(0);
1617 } 1731 }
1618 1732
1619 1733
1620 #undef __ 1734 #undef __
1621 1735
1622 } } // namespace v8::internal 1736 } } // namespace v8::internal
1623 1737
1624 #endif // V8_TARGET_ARCH_X64 1738 #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