OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/arm64/frames-arm64.h" | 7 #include "src/arm64/frames-arm64.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
10 #include "src/deoptimizer.h" | 10 #include "src/deoptimizer.h" |
(...skipping 1272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1283 __ Sub(argc, argc, 1); | 1283 __ Sub(argc, argc, 1); |
1284 __ Drop(1); | 1284 __ Drop(1); |
1285 } | 1285 } |
1286 | 1286 |
1287 // 4. Call the callable. | 1287 // 4. Call the callable. |
1288 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1288 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1289 } | 1289 } |
1290 | 1290 |
1291 | 1291 |
1292 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1292 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
| 1293 const int vectorOffset, |
1293 const int argumentsOffset, | 1294 const int argumentsOffset, |
1294 const int indexOffset, | 1295 const int indexOffset, |
1295 const int limitOffset) { | 1296 const int limitOffset) { |
1296 Label entry, loop; | 1297 Label entry, loop; |
1297 Register receiver = LoadDescriptor::ReceiverRegister(); | 1298 Register receiver = LoadDescriptor::ReceiverRegister(); |
1298 Register key = LoadDescriptor::NameRegister(); | 1299 Register key = LoadDescriptor::NameRegister(); |
1299 Register slot = LoadDescriptor::SlotRegister(); | 1300 Register slot = LoadDescriptor::SlotRegister(); |
1300 Register vector = LoadWithVectorDescriptor::VectorRegister(); | 1301 Register vector = LoadWithVectorDescriptor::VectorRegister(); |
1301 | 1302 |
1302 __ Ldr(key, MemOperand(fp, indexOffset)); | 1303 __ Ldr(key, MemOperand(fp, indexOffset)); |
1303 __ B(&entry); | 1304 __ B(&entry); |
1304 | 1305 |
1305 // Load the current argument from the arguments array. | 1306 // Load the current argument from the arguments array. |
1306 __ Bind(&loop); | 1307 __ Bind(&loop); |
1307 __ Ldr(receiver, MemOperand(fp, argumentsOffset)); | 1308 __ Ldr(receiver, MemOperand(fp, argumentsOffset)); |
1308 | 1309 |
1309 // Use inline caching to speed up access to arguments. | 1310 // Use inline caching to speed up access to arguments. |
1310 Code::Kind kinds[] = {Code::KEYED_LOAD_IC}; | 1311 int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); |
1311 FeedbackVectorSpec spec(0, 1, kinds); | 1312 __ Mov(slot, Operand(Smi::FromInt(slot_index))); |
1312 Handle<TypeFeedbackVector> feedback_vector = | 1313 __ Ldr(vector, MemOperand(fp, vectorOffset)); |
1313 masm->isolate()->factory()->NewTypeFeedbackVector(&spec); | |
1314 int index = feedback_vector->GetIndex(FeedbackVectorICSlot(0)); | |
1315 __ Mov(slot, Smi::FromInt(index)); | |
1316 __ Mov(vector, feedback_vector); | |
1317 Handle<Code> ic = | 1314 Handle<Code> ic = |
1318 KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); | 1315 KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); |
1319 __ Call(ic, RelocInfo::CODE_TARGET); | 1316 __ Call(ic, RelocInfo::CODE_TARGET); |
1320 | 1317 |
1321 // Push the nth argument. | 1318 // Push the nth argument. |
1322 __ Push(x0); | 1319 __ Push(x0); |
1323 | 1320 |
1324 __ Ldr(key, MemOperand(fp, indexOffset)); | 1321 __ Ldr(key, MemOperand(fp, indexOffset)); |
1325 __ Add(key, key, Smi::FromInt(1)); | 1322 __ Add(key, key, Smi::FromInt(1)); |
1326 __ Str(key, MemOperand(fp, indexOffset)); | 1323 __ Str(key, MemOperand(fp, indexOffset)); |
(...skipping 14 matching lines...) Expand all Loading... |
1341 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { | 1338 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { |
1342 const int kFormalParameters = targetIsArgument ? 3 : 2; | 1339 const int kFormalParameters = targetIsArgument ? 3 : 2; |
1343 const int kStackSize = kFormalParameters + 1; | 1340 const int kStackSize = kFormalParameters + 1; |
1344 | 1341 |
1345 { | 1342 { |
1346 FrameScope frame_scope(masm, StackFrame::INTERNAL); | 1343 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
1347 | 1344 |
1348 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; | 1345 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; |
1349 const int kReceiverOffset = kArgumentsOffset + kPointerSize; | 1346 const int kReceiverOffset = kArgumentsOffset + kPointerSize; |
1350 const int kFunctionOffset = kReceiverOffset + kPointerSize; | 1347 const int kFunctionOffset = kReceiverOffset + kPointerSize; |
1351 const int kIndexOffset = | 1348 const int kVectorOffset = |
1352 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 1349 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; |
1353 const int kLimitOffset = | 1350 const int kIndexOffset = kVectorOffset - (2 * kPointerSize); |
1354 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | 1351 const int kLimitOffset = kVectorOffset - (1 * kPointerSize); |
1355 | 1352 |
1356 Register args = x12; | 1353 Register args = x12; |
1357 Register receiver = x14; | 1354 Register receiver = x14; |
1358 Register function = x15; | 1355 Register function = x15; |
| 1356 Register apply_function = x1; |
| 1357 |
| 1358 // Push the vector. |
| 1359 __ Ldr( |
| 1360 apply_function, |
| 1361 FieldMemOperand(apply_function, JSFunction::kSharedFunctionInfoOffset)); |
| 1362 __ Ldr(apply_function, |
| 1363 FieldMemOperand(apply_function, |
| 1364 SharedFunctionInfo::kFeedbackVectorOffset)); |
| 1365 __ Push(apply_function); |
1359 | 1366 |
1360 // Get the length of the arguments via a builtin call. | 1367 // Get the length of the arguments via a builtin call. |
1361 __ Ldr(function, MemOperand(fp, kFunctionOffset)); | 1368 __ Ldr(function, MemOperand(fp, kFunctionOffset)); |
1362 __ Ldr(args, MemOperand(fp, kArgumentsOffset)); | 1369 __ Ldr(args, MemOperand(fp, kArgumentsOffset)); |
1363 __ Push(function, args); | 1370 __ Push(function, args); |
1364 if (targetIsArgument) { | 1371 if (targetIsArgument) { |
1365 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, | 1372 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, |
1366 CALL_FUNCTION); | 1373 CALL_FUNCTION); |
1367 } else { | 1374 } else { |
1368 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); | 1375 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); |
1369 } | 1376 } |
1370 Register argc = x0; | 1377 Register argc = x0; |
1371 | 1378 |
1372 Generate_CheckStackOverflow(masm, kFunctionOffset, argc, kArgcIsSmiTagged); | 1379 Generate_CheckStackOverflow(masm, kFunctionOffset, argc, kArgcIsSmiTagged); |
1373 | 1380 |
1374 // Push current limit, index and receiver. | 1381 // Push current limit, index and receiver. |
1375 __ Mov(x1, 0); // Initial index. | 1382 __ Mov(x1, 0); // Initial index. |
1376 __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); | 1383 __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); |
1377 __ Push(argc, x1, receiver); | 1384 __ Push(argc, x1, receiver); |
1378 | 1385 |
1379 // Copy all arguments from the array to the stack. | 1386 // Copy all arguments from the array to the stack. |
1380 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset, | 1387 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, |
1381 kLimitOffset); | 1388 kIndexOffset, kLimitOffset); |
1382 | 1389 |
1383 // At the end of the loop, the number of arguments is stored in x0, untagged | 1390 // At the end of the loop, the number of arguments is stored in x0, untagged |
1384 | 1391 |
1385 // Call the callable. | 1392 // Call the callable. |
1386 // TODO(bmeurer): This should be a tail call according to ES6. | 1393 // TODO(bmeurer): This should be a tail call according to ES6. |
1387 __ Ldr(x1, MemOperand(fp, kFunctionOffset)); | 1394 __ Ldr(x1, MemOperand(fp, kFunctionOffset)); |
1388 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1395 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1389 } | 1396 } |
1390 __ Drop(kStackSize); | 1397 __ Drop(kStackSize); |
1391 __ Ret(); | 1398 __ Ret(); |
1392 } | 1399 } |
1393 | 1400 |
1394 | 1401 |
1395 static void Generate_ConstructHelper(MacroAssembler* masm) { | 1402 static void Generate_ConstructHelper(MacroAssembler* masm) { |
1396 const int kFormalParameters = 3; | 1403 const int kFormalParameters = 3; |
1397 const int kStackSize = kFormalParameters + 1; | 1404 const int kStackSize = kFormalParameters + 1; |
1398 | 1405 |
1399 { | 1406 { |
1400 FrameScope frame_scope(masm, StackFrame::INTERNAL); | 1407 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
1401 | 1408 |
1402 const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; | 1409 const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; |
1403 const int kArgumentsOffset = kNewTargetOffset + kPointerSize; | 1410 const int kArgumentsOffset = kNewTargetOffset + kPointerSize; |
1404 const int kFunctionOffset = kArgumentsOffset + kPointerSize; | 1411 const int kFunctionOffset = kArgumentsOffset + kPointerSize; |
1405 | 1412 const int kVectorOffset = |
1406 const int kIndexOffset = | 1413 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; |
1407 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 1414 const int kIndexOffset = kVectorOffset - (2 * kPointerSize); |
1408 const int kLimitOffset = | 1415 const int kLimitOffset = kVectorOffset - (1 * kPointerSize); |
1409 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | |
1410 | 1416 |
1411 // Is x11 safe to use? | 1417 // Is x11 safe to use? |
1412 Register newTarget = x11; | 1418 Register newTarget = x11; |
1413 Register args = x12; | 1419 Register args = x12; |
1414 Register function = x15; | 1420 Register function = x15; |
| 1421 Register construct_function = x1; |
| 1422 |
| 1423 // Push the vector. |
| 1424 __ Ldr(construct_function, |
| 1425 FieldMemOperand(construct_function, |
| 1426 JSFunction::kSharedFunctionInfoOffset)); |
| 1427 __ Ldr(construct_function, |
| 1428 FieldMemOperand(construct_function, |
| 1429 SharedFunctionInfo::kFeedbackVectorOffset)); |
| 1430 __ Push(construct_function); |
1415 | 1431 |
1416 // If newTarget is not supplied, set it to constructor | 1432 // If newTarget is not supplied, set it to constructor |
1417 Label validate_arguments; | 1433 Label validate_arguments; |
1418 __ Ldr(x0, MemOperand(fp, kNewTargetOffset)); | 1434 __ Ldr(x0, MemOperand(fp, kNewTargetOffset)); |
1419 __ CompareRoot(x0, Heap::kUndefinedValueRootIndex); | 1435 __ CompareRoot(x0, Heap::kUndefinedValueRootIndex); |
1420 __ B(ne, &validate_arguments); | 1436 __ B(ne, &validate_arguments); |
1421 __ Ldr(x0, MemOperand(fp, kFunctionOffset)); | 1437 __ Ldr(x0, MemOperand(fp, kFunctionOffset)); |
1422 __ Str(x0, MemOperand(fp, kNewTargetOffset)); | 1438 __ Str(x0, MemOperand(fp, kNewTargetOffset)); |
1423 | 1439 |
1424 // Validate arguments | 1440 // Validate arguments |
1425 __ Bind(&validate_arguments); | 1441 __ Bind(&validate_arguments); |
1426 __ Ldr(function, MemOperand(fp, kFunctionOffset)); | 1442 __ Ldr(function, MemOperand(fp, kFunctionOffset)); |
1427 __ Ldr(args, MemOperand(fp, kArgumentsOffset)); | 1443 __ Ldr(args, MemOperand(fp, kArgumentsOffset)); |
1428 __ Ldr(newTarget, MemOperand(fp, kNewTargetOffset)); | 1444 __ Ldr(newTarget, MemOperand(fp, kNewTargetOffset)); |
1429 __ Push(function, args, newTarget); | 1445 __ Push(function, args, newTarget); |
1430 __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, | 1446 __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, |
1431 CALL_FUNCTION); | 1447 CALL_FUNCTION); |
1432 Register argc = x0; | 1448 Register argc = x0; |
1433 | 1449 |
1434 Generate_CheckStackOverflow(masm, kFunctionOffset, argc, kArgcIsSmiTagged); | 1450 Generate_CheckStackOverflow(masm, kFunctionOffset, argc, kArgcIsSmiTagged); |
1435 | 1451 |
1436 // Push current limit and index & constructor function as callee. | 1452 // Push current limit and index & constructor function as callee. |
1437 __ Mov(x1, 0); // Initial index. | 1453 __ Mov(x1, 0); // Initial index. |
1438 __ Push(argc, x1, function); | 1454 __ Push(argc, x1, function); |
1439 | 1455 |
1440 // Copy all arguments from the array to the stack. | 1456 // Copy all arguments from the array to the stack. |
1441 Generate_PushAppliedArguments( | 1457 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, |
1442 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); | 1458 kIndexOffset, kLimitOffset); |
1443 | 1459 |
1444 // Use undefined feedback vector | 1460 // Use undefined feedback vector |
1445 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); | 1461 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); |
1446 __ Ldr(x1, MemOperand(fp, kFunctionOffset)); | 1462 __ Ldr(x1, MemOperand(fp, kFunctionOffset)); |
1447 __ Ldr(x4, MemOperand(fp, kNewTargetOffset)); | 1463 __ Ldr(x4, MemOperand(fp, kNewTargetOffset)); |
1448 | 1464 |
1449 // Call the function. | 1465 // Call the function. |
1450 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); | 1466 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); |
1451 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 1467 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
1452 | 1468 |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1855 } | 1871 } |
1856 } | 1872 } |
1857 | 1873 |
1858 | 1874 |
1859 #undef __ | 1875 #undef __ |
1860 | 1876 |
1861 } // namespace internal | 1877 } // namespace internal |
1862 } // namespace v8 | 1878 } // namespace v8 |
1863 | 1879 |
1864 #endif // V8_TARGET_ARCH_ARM | 1880 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |