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 1292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1303 // (which is a copy of the last argument). | 1303 // (which is a copy of the last argument). |
1304 __ Sub(argc, argc, 1); | 1304 __ Sub(argc, argc, 1); |
1305 __ Drop(1); | 1305 __ Drop(1); |
1306 } | 1306 } |
1307 | 1307 |
1308 // 4. Call the callable. | 1308 // 4. Call the callable. |
1309 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1309 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1310 } | 1310 } |
1311 | 1311 |
1312 | 1312 |
1313 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1313 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
1314 const int vectorOffset, | 1314 // ----------- S t a t e ------------- |
1315 const int argumentsOffset, | 1315 // -- r0 : argc |
1316 const int indexOffset, | 1316 // -- sp[0] : argArray |
1317 const int limitOffset) { | 1317 // -- sp[8] : thisArg |
1318 Label entry, loop; | 1318 // -- sp[16] : receiver |
1319 Register receiver = LoadDescriptor::ReceiverRegister(); | 1319 // ----------------------------------- |
1320 Register key = LoadDescriptor::NameRegister(); | 1320 ASM_LOCATION("Builtins::Generate_FunctionApply"); |
1321 Register slot = LoadDescriptor::SlotRegister(); | 1321 |
1322 Register vector = LoadWithVectorDescriptor::VectorRegister(); | 1322 // 1. Load receiver into x1, argArray into x0 (if present), remove all |
1323 | 1323 // arguments from the stack (including the receiver), and push thisArg (if |
1324 __ Ldr(key, MemOperand(fp, indexOffset)); | 1324 // present) instead. |
1325 __ B(&entry); | 1325 { |
1326 | 1326 Label done; |
1327 // Load the current argument from the arguments array. | |
1328 __ Bind(&loop); | |
1329 __ Ldr(receiver, MemOperand(fp, argumentsOffset)); | |
1330 | |
1331 // Use inline caching to speed up access to arguments. | |
1332 int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); | |
1333 __ Mov(slot, Operand(Smi::FromInt(slot_index))); | |
1334 __ Ldr(vector, MemOperand(fp, vectorOffset)); | |
1335 Handle<Code> ic = | |
1336 KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); | |
1337 __ Call(ic, RelocInfo::CODE_TARGET); | |
1338 | |
1339 // Push the nth argument. | |
1340 __ Push(x0); | |
1341 | |
1342 __ Ldr(key, MemOperand(fp, indexOffset)); | |
1343 __ Add(key, key, Smi::FromInt(1)); | |
1344 __ Str(key, MemOperand(fp, indexOffset)); | |
1345 | |
1346 // Test if the copy loop has finished copying all the elements from the | |
1347 // arguments object. | |
1348 __ Bind(&entry); | |
1349 __ Ldr(x1, MemOperand(fp, limitOffset)); | |
1350 __ Cmp(key, x1); | |
1351 __ B(ne, &loop); | |
1352 | |
1353 // On exit, the pushed arguments count is in x0, untagged | |
1354 __ Mov(x0, key); | |
1355 __ SmiUntag(x0); | |
1356 } | |
1357 | |
1358 | |
1359 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { | |
1360 const int kFormalParameters = targetIsArgument ? 3 : 2; | |
1361 const int kStackSize = kFormalParameters + 1; | |
1362 | |
1363 { | |
1364 FrameScope frame_scope(masm, StackFrame::INTERNAL); | |
1365 | |
1366 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; | |
1367 const int kReceiverOffset = kArgumentsOffset + kPointerSize; | |
1368 const int kFunctionOffset = kReceiverOffset + kPointerSize; | |
1369 const int kVectorOffset = | |
1370 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; | |
1371 const int kIndexOffset = kVectorOffset - (2 * kPointerSize); | |
1372 const int kLimitOffset = kVectorOffset - (1 * kPointerSize); | |
1373 | |
1374 Register args = x12; | |
1375 Register receiver = x14; | |
1376 Register function = x15; | |
1377 Register apply_function = x1; | |
1378 | |
1379 // Push the vector. | |
1380 __ Ldr( | |
1381 apply_function, | |
1382 FieldMemOperand(apply_function, JSFunction::kSharedFunctionInfoOffset)); | |
1383 __ Ldr(apply_function, | |
1384 FieldMemOperand(apply_function, | |
1385 SharedFunctionInfo::kFeedbackVectorOffset)); | |
1386 __ Push(apply_function); | |
1387 | |
1388 // Get the length of the arguments via a builtin call. | |
1389 __ Ldr(function, MemOperand(fp, kFunctionOffset)); | |
1390 __ Ldr(args, MemOperand(fp, kArgumentsOffset)); | |
1391 __ Push(function, args); | |
1392 if (targetIsArgument) { | |
1393 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, | |
1394 CALL_FUNCTION); | |
1395 } else { | |
1396 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); | |
1397 } | |
1398 Register argc = x0; | |
1399 | |
1400 Generate_CheckStackOverflow(masm, argc, kArgcIsSmiTagged); | |
1401 | |
1402 // Push current limit, index and receiver. | |
1403 __ Mov(x1, 0); // Initial index. | |
1404 __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); | |
1405 __ Push(argc, x1, receiver); | |
1406 | |
1407 // Copy all arguments from the array to the stack. | |
1408 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, | |
1409 kIndexOffset, kLimitOffset); | |
1410 | |
1411 // At the end of the loop, the number of arguments is stored in x0, untagged | |
1412 | |
1413 // Call the callable. | |
1414 // TODO(bmeurer): This should be a tail call according to ES6. | |
1415 __ Ldr(x1, MemOperand(fp, kFunctionOffset)); | |
1416 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
1417 } | |
1418 __ Drop(kStackSize); | |
1419 __ Ret(); | |
1420 } | |
1421 | |
1422 | |
1423 static void Generate_ConstructHelper(MacroAssembler* masm) { | |
1424 const int kFormalParameters = 3; | |
1425 const int kStackSize = kFormalParameters + 1; | |
1426 | |
1427 { | |
1428 FrameScope frame_scope(masm, StackFrame::INTERNAL); | |
1429 | |
1430 const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; | |
1431 const int kArgumentsOffset = kNewTargetOffset + kPointerSize; | |
1432 const int kFunctionOffset = kArgumentsOffset + kPointerSize; | |
1433 const int kVectorOffset = | |
1434 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; | |
1435 const int kIndexOffset = kVectorOffset - (2 * kPointerSize); | |
1436 const int kLimitOffset = kVectorOffset - (1 * kPointerSize); | |
1437 | |
1438 // Is x11 safe to use? | |
1439 Register newTarget = x11; | |
1440 Register args = x12; | |
1441 Register function = x15; | |
1442 Register construct_function = x1; | |
1443 | |
1444 // Push the vector. | |
1445 __ Ldr(construct_function, | |
1446 FieldMemOperand(construct_function, | |
1447 JSFunction::kSharedFunctionInfoOffset)); | |
1448 __ Ldr(construct_function, | |
1449 FieldMemOperand(construct_function, | |
1450 SharedFunctionInfo::kFeedbackVectorOffset)); | |
1451 __ Push(construct_function); | |
1452 | |
1453 // If newTarget is not supplied, set it to constructor | |
1454 Label validate_arguments; | |
1455 __ Ldr(x0, MemOperand(fp, kNewTargetOffset)); | |
1456 __ CompareRoot(x0, Heap::kUndefinedValueRootIndex); | |
1457 __ B(ne, &validate_arguments); | |
1458 __ Ldr(x0, MemOperand(fp, kFunctionOffset)); | |
1459 __ Str(x0, MemOperand(fp, kNewTargetOffset)); | |
1460 | |
1461 // Validate arguments | |
1462 __ Bind(&validate_arguments); | |
1463 __ Ldr(function, MemOperand(fp, kFunctionOffset)); | |
1464 __ Ldr(args, MemOperand(fp, kArgumentsOffset)); | |
1465 __ Ldr(newTarget, MemOperand(fp, kNewTargetOffset)); | |
1466 __ Push(function, args, newTarget); | |
1467 __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, | |
1468 CALL_FUNCTION); | |
1469 Register argc = x0; | |
1470 | |
1471 Generate_CheckStackOverflow(masm, argc, kArgcIsSmiTagged); | |
1472 | |
1473 // Push current limit and index & constructor function as callee. | |
1474 __ Mov(x1, 0); // Initial index. | |
1475 __ Push(argc, x1, function); | |
1476 | |
1477 // Copy all arguments from the array to the stack. | |
1478 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, | |
1479 kIndexOffset, kLimitOffset); | |
1480 | |
1481 // Use undefined feedback vector | |
1482 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); | 1327 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); |
1483 __ Ldr(x1, MemOperand(fp, kFunctionOffset)); | 1328 __ Mov(x3, x2); |
1484 __ Ldr(x3, MemOperand(fp, kNewTargetOffset)); | 1329 __ Peek(x1, Operand(x0, LSL, kPointerSizeLog2)); // receiver |
1485 | 1330 __ Subs(x4, x0, 1); |
1486 // Call the function. | 1331 __ B(lt, &done); |
1487 __ Call(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 1332 __ Peek(x2, Operand(x4, LSL, kPointerSizeLog2)); // thisArg |
1488 | 1333 __ Subs(x4, x4, 1); |
1489 // Leave internal frame. | 1334 __ B(lt, &done); |
1490 } | 1335 __ Peek(x3, Operand(x4, LSL, kPointerSizeLog2)); // argArray |
1491 __ Drop(kStackSize); | 1336 __ Bind(&done); |
1492 __ Ret(); | 1337 __ Drop(x0); |
1493 } | 1338 __ Poke(x2, 0); |
1494 | 1339 __ Mov(x0, x3); |
1495 | 1340 } |
1496 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1341 |
1497 ASM_LOCATION("Builtins::Generate_FunctionApply"); | 1342 // ----------- S t a t e ------------- |
1498 Generate_ApplyHelper(masm, false); | 1343 // -- x0 : argArray |
| 1344 // -- x1 : receiver |
| 1345 // -- sp[0] : thisArg |
| 1346 // ----------------------------------- |
| 1347 |
| 1348 // 2. Make sure the receiver is actually callable. |
| 1349 Label receiver_not_callable; |
| 1350 __ JumpIfSmi(x1, &receiver_not_callable); |
| 1351 __ Ldr(x4, FieldMemOperand(x1, HeapObject::kMapOffset)); |
| 1352 __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset)); |
| 1353 __ TestAndBranchIfAllClear(x4, 1 << Map::kIsCallable, &receiver_not_callable); |
| 1354 |
| 1355 // 3. Tail call with no arguments if argArray is null or undefined. |
| 1356 Label no_arguments; |
| 1357 __ JumpIfRoot(x0, Heap::kNullValueRootIndex, &no_arguments); |
| 1358 __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, &no_arguments); |
| 1359 |
| 1360 // 4a. Apply the receiver to the given argArray (passing undefined for |
| 1361 // new.target). |
| 1362 __ LoadRoot(x3, Heap::kUndefinedValueRootIndex); |
| 1363 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |
| 1364 |
| 1365 // 4b. The argArray is either null or undefined, so we tail call without any |
| 1366 // arguments to the receiver. |
| 1367 __ Bind(&no_arguments); |
| 1368 { |
| 1369 __ Mov(x0, 0); |
| 1370 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1371 } |
| 1372 |
| 1373 // 4c. The receiver is not callable, throw an appropriate TypeError. |
| 1374 __ Bind(&receiver_not_callable); |
| 1375 { |
| 1376 __ Poke(x1, 0); |
| 1377 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1); |
| 1378 } |
1499 } | 1379 } |
1500 | 1380 |
1501 | 1381 |
1502 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 1382 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
| 1383 // ----------- S t a t e ------------- |
| 1384 // -- x0 : argc |
| 1385 // -- sp[0] : argumentsList |
| 1386 // -- sp[8] : thisArgument |
| 1387 // -- sp[16] : target |
| 1388 // -- sp[24] : receiver |
| 1389 // ----------------------------------- |
1503 ASM_LOCATION("Builtins::Generate_ReflectApply"); | 1390 ASM_LOCATION("Builtins::Generate_ReflectApply"); |
1504 Generate_ApplyHelper(masm, true); | 1391 |
| 1392 // 1. Load target into x1 (if present), argumentsList into x0 (if present), |
| 1393 // remove all arguments from the stack (including the receiver), and push |
| 1394 // thisArgument (if present) instead. |
| 1395 { |
| 1396 Label done; |
| 1397 __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); |
| 1398 __ Mov(x2, x1); |
| 1399 __ Mov(x3, x1); |
| 1400 __ Subs(x4, x0, 1); |
| 1401 __ B(lt, &done); |
| 1402 __ Peek(x1, Operand(x4, LSL, kPointerSizeLog2)); // target |
| 1403 __ Subs(x4, x4, 1); |
| 1404 __ B(lt, &done); |
| 1405 __ Peek(x2, Operand(x4, LSL, kPointerSizeLog2)); // thisArgument |
| 1406 __ Subs(x4, x4, 1); |
| 1407 __ B(lt, &done); |
| 1408 __ Peek(x3, Operand(x4, LSL, kPointerSizeLog2)); // argumentsList |
| 1409 __ Bind(&done); |
| 1410 __ Drop(x0); |
| 1411 __ Poke(x2, 0); |
| 1412 __ Mov(x0, x3); |
| 1413 } |
| 1414 |
| 1415 // ----------- S t a t e ------------- |
| 1416 // -- x0 : argumentsList |
| 1417 // -- x1 : target |
| 1418 // -- sp[0] : thisArgument |
| 1419 // ----------------------------------- |
| 1420 |
| 1421 // 2. Make sure the target is actually callable. |
| 1422 Label target_not_callable; |
| 1423 __ JumpIfSmi(x1, &target_not_callable); |
| 1424 __ Ldr(x4, FieldMemOperand(x1, HeapObject::kMapOffset)); |
| 1425 __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset)); |
| 1426 __ TestAndBranchIfAllClear(x4, 1 << Map::kIsCallable, &target_not_callable); |
| 1427 |
| 1428 // 3a. Apply the target to the given argumentsList (passing undefined for |
| 1429 // new.target). |
| 1430 __ LoadRoot(x3, Heap::kUndefinedValueRootIndex); |
| 1431 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |
| 1432 |
| 1433 // 3b. The target is not callable, throw an appropriate TypeError. |
| 1434 __ Bind(&target_not_callable); |
| 1435 { |
| 1436 __ Poke(x1, 0); |
| 1437 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1); |
| 1438 } |
1505 } | 1439 } |
1506 | 1440 |
1507 | 1441 |
1508 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 1442 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
| 1443 // ----------- S t a t e ------------- |
| 1444 // -- x0 : argc |
| 1445 // -- sp[0] : new.target (optional) |
| 1446 // -- sp[8] : argumentsList |
| 1447 // -- sp[16] : target |
| 1448 // -- sp[24] : receiver |
| 1449 // ----------------------------------- |
1509 ASM_LOCATION("Builtins::Generate_ReflectConstruct"); | 1450 ASM_LOCATION("Builtins::Generate_ReflectConstruct"); |
1510 Generate_ConstructHelper(masm); | 1451 |
1511 } | 1452 // 1. Load target into x1 (if present), argumentsList into x0 (if present), |
1512 | 1453 // new.target into x3 (if present, otherwise use target), remove all |
1513 | 1454 // arguments from the stack (including the receiver), and push thisArgument |
| 1455 // (if present) instead. |
| 1456 { |
| 1457 Label done; |
| 1458 __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); |
| 1459 __ Mov(x2, x1); |
| 1460 __ Poke(x2, Operand(x0, LSL, kPointerSizeLog2)); // receiver |
| 1461 __ Subs(x4, x0, 1); |
| 1462 __ B(lt, &done); |
| 1463 __ Peek(x1, Operand(x4, LSL, kPointerSizeLog2)); // target |
| 1464 __ Mov(x3, x1); // new.target defaults to target |
| 1465 __ Subs(x4, x4, 1); |
| 1466 __ B(lt, &done); |
| 1467 __ Peek(x2, Operand(x4, LSL, kPointerSizeLog2)); // argumentsList |
| 1468 __ Subs(x4, x4, 1); |
| 1469 __ B(lt, &done); |
| 1470 __ Peek(x3, Operand(x4, LSL, kPointerSizeLog2)); // new.target |
| 1471 __ Bind(&done); |
| 1472 __ Drop(x0); |
| 1473 __ Mov(x0, x2); |
| 1474 } |
| 1475 |
| 1476 // ----------- S t a t e ------------- |
| 1477 // -- x0 : argumentsList |
| 1478 // -- x3 : new.target |
| 1479 // -- x1 : target |
| 1480 // -- sp[0] : receiver (undefined) |
| 1481 // ----------------------------------- |
| 1482 |
| 1483 // 2. Make sure the target is actually a constructor. |
| 1484 Label target_not_constructor; |
| 1485 __ JumpIfSmi(x1, &target_not_constructor); |
| 1486 __ Ldr(x4, FieldMemOperand(x1, HeapObject::kMapOffset)); |
| 1487 __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset)); |
| 1488 __ TestAndBranchIfAllClear(x4, 1 << Map::kIsConstructor, |
| 1489 &target_not_constructor); |
| 1490 |
| 1491 // 3. Make sure the target is actually a constructor. |
| 1492 Label new_target_not_constructor; |
| 1493 __ JumpIfSmi(x3, &new_target_not_constructor); |
| 1494 __ Ldr(x4, FieldMemOperand(x3, HeapObject::kMapOffset)); |
| 1495 __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset)); |
| 1496 __ TestAndBranchIfAllClear(x4, 1 << Map::kIsConstructor, |
| 1497 &new_target_not_constructor); |
| 1498 |
| 1499 // 4a. Construct the target with the given new.target and argumentsList. |
| 1500 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |
| 1501 |
| 1502 // 4b. The target is not a constructor, throw an appropriate TypeError. |
| 1503 __ Bind(&target_not_constructor); |
| 1504 { |
| 1505 __ Poke(x1, 0); |
| 1506 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1); |
| 1507 } |
| 1508 |
| 1509 // 4c. The new.target is not a constructor, throw an appropriate TypeError. |
| 1510 __ Bind(&new_target_not_constructor); |
| 1511 { |
| 1512 __ Poke(x3, 0); |
| 1513 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1); |
| 1514 } |
| 1515 } |
| 1516 |
| 1517 |
1514 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, | 1518 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, |
1515 Label* stack_overflow) { | 1519 Label* stack_overflow) { |
1516 // ----------- S t a t e ------------- | 1520 // ----------- S t a t e ------------- |
1517 // -- x0 : actual number of arguments | 1521 // -- x0 : actual number of arguments |
1518 // -- x1 : function (passed through to callee) | 1522 // -- x1 : function (passed through to callee) |
1519 // -- x2 : expected number of arguments | 1523 // -- x2 : expected number of arguments |
1520 // -- x3 : new target (passed through to callee) | 1524 // -- x3 : new target (passed through to callee) |
1521 // ----------------------------------- | 1525 // ----------------------------------- |
1522 // Check the stack for overflow. | 1526 // Check the stack for overflow. |
1523 // We are not trying to catch interruptions (e.g. debug break and | 1527 // We are not trying to catch interruptions (e.g. debug break and |
(...skipping 28 matching lines...) Expand all Loading... |
1552 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + | 1556 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + |
1553 kPointerSize))); | 1557 kPointerSize))); |
1554 __ Mov(jssp, fp); | 1558 __ Mov(jssp, fp); |
1555 __ Pop(fp, lr); | 1559 __ Pop(fp, lr); |
1556 __ DropBySMI(x10, kXRegSize); | 1560 __ DropBySMI(x10, kXRegSize); |
1557 __ Drop(1); | 1561 __ Drop(1); |
1558 } | 1562 } |
1559 | 1563 |
1560 | 1564 |
1561 // static | 1565 // static |
| 1566 void Builtins::Generate_Apply(MacroAssembler* masm) { |
| 1567 // ----------- S t a t e ------------- |
| 1568 // -- x0 : argumentsList |
| 1569 // -- x1 : target |
| 1570 // -- x3 : new.target (checked to be constructor or undefined) |
| 1571 // -- sp[0] : thisArgument |
| 1572 // ----------------------------------- |
| 1573 |
| 1574 // Create the list of arguments from the array-like argumentsList. |
| 1575 { |
| 1576 Label create_arguments, create_array, create_runtime, done_create; |
| 1577 __ JumpIfSmi(x0, &create_runtime); |
| 1578 |
| 1579 // Load the map of argumentsList into x2. |
| 1580 __ Ldr(x2, FieldMemOperand(x0, HeapObject::kMapOffset)); |
| 1581 |
| 1582 // Load native context into x4. |
| 1583 __ Ldr(x4, NativeContextMemOperand()); |
| 1584 |
| 1585 // Check if argumentsList is an (unmodified) arguments object. |
| 1586 __ Ldr(x5, ContextMemOperand(x4, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); |
| 1587 __ Cmp(x5, x2); |
| 1588 __ B(eq, &create_arguments); |
| 1589 __ Ldr(x5, ContextMemOperand(x4, Context::STRICT_ARGUMENTS_MAP_INDEX)); |
| 1590 __ Cmp(x5, x2); |
| 1591 __ B(eq, &create_arguments); |
| 1592 |
| 1593 // Check if argumentsList is a fast JSArray. |
| 1594 __ CompareInstanceType(x2, x4, JS_ARRAY_TYPE); |
| 1595 __ B(eq, &create_array); |
| 1596 |
| 1597 // Ask the runtime to create the list (actually a FixedArray). |
| 1598 __ Bind(&create_runtime); |
| 1599 { |
| 1600 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1601 __ Push(x1, x3, x0); |
| 1602 __ CallRuntime(Runtime::kCreateListFromArrayLike, 1); |
| 1603 __ Pop(x3, x1); |
| 1604 __ Ldrsw(x2, UntagSmiFieldMemOperand(x0, FixedArray::kLengthOffset)); |
| 1605 } |
| 1606 __ B(&done_create); |
| 1607 |
| 1608 // Try to create the list from an arguments object. |
| 1609 __ Bind(&create_arguments); |
| 1610 __ Ldr(x2, |
| 1611 FieldMemOperand(x0, JSObject::kHeaderSize + |
| 1612 Heap::kArgumentsLengthIndex * kPointerSize)); |
| 1613 __ Ldr(x4, FieldMemOperand(x0, JSObject::kElementsOffset)); |
| 1614 __ Ldr(x5, FieldMemOperand(x4, FixedArray::kLengthOffset)); |
| 1615 __ Cmp(x2, x4); |
| 1616 __ B(ne, &create_runtime); |
| 1617 __ SmiUntag(x2); |
| 1618 __ Mov(x0, x4); |
| 1619 __ B(&done_create); |
| 1620 |
| 1621 // Try to create the list from a JSArray object. |
| 1622 __ Bind(&create_array); |
| 1623 __ Ldr(x2, FieldMemOperand(x2, Map::kBitField2Offset)); |
| 1624 __ DecodeField<Map::ElementsKindBits>(x2); |
| 1625 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); |
| 1626 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
| 1627 STATIC_ASSERT(FAST_ELEMENTS == 2); |
| 1628 __ Cmp(x2, FAST_ELEMENTS); |
| 1629 __ B(hi, &create_runtime); |
| 1630 __ Cmp(x2, FAST_HOLEY_SMI_ELEMENTS); |
| 1631 __ B(eq, &create_runtime); |
| 1632 __ Ldrsw(x2, UntagSmiFieldMemOperand(x0, JSArray::kLengthOffset)); |
| 1633 __ Ldr(x0, FieldMemOperand(x0, JSArray::kElementsOffset)); |
| 1634 |
| 1635 __ Bind(&done_create); |
| 1636 } |
| 1637 |
| 1638 // Check for stack overflow. |
| 1639 { |
| 1640 // Check the stack for overflow. We are not trying to catch interruptions |
| 1641 // (i.e. debug break and preemption) here, so check the "real stack limit". |
| 1642 Label done; |
| 1643 __ LoadRoot(x10, Heap::kRealStackLimitRootIndex); |
| 1644 // Make x10 the space we have left. The stack might already be overflowed |
| 1645 // here which will cause x10 to become negative. |
| 1646 __ Sub(x10, jssp, x10); |
| 1647 // Check if the arguments will overflow the stack. |
| 1648 __ Cmp(x10, Operand(x2, LSL, kPointerSizeLog2)); |
| 1649 __ B(gt, &done); // Signed comparison. |
| 1650 __ TailCallRuntime(Runtime::kThrowStackOverflow, 1, 1); |
| 1651 __ Bind(&done); |
| 1652 } |
| 1653 |
| 1654 // ----------- S t a t e ------------- |
| 1655 // -- x1 : target |
| 1656 // -- x0 : args (a FixedArray built from argumentsList) |
| 1657 // -- x2 : len (number of elements to push from args) |
| 1658 // -- x3 : new.target (checked to be constructor or undefined) |
| 1659 // -- sp[0] : thisArgument |
| 1660 // ----------------------------------- |
| 1661 |
| 1662 // Push arguments onto the stack (thisArgument is already on the stack). |
| 1663 { |
| 1664 __ Mov(x4, 0); |
| 1665 Label done, loop; |
| 1666 __ Bind(&loop); |
| 1667 __ Cmp(x4, x2); |
| 1668 __ B(eq, &done); |
| 1669 __ Add(x10, x0, Operand(x4, LSL, kPointerSizeLog2)); |
| 1670 __ Ldr(x10, FieldMemOperand(x10, FixedArray::kHeaderSize)); |
| 1671 __ Push(x10); |
| 1672 __ Add(x4, x4, 1); |
| 1673 __ B(&loop); |
| 1674 __ Bind(&done); |
| 1675 __ Mov(x0, x4); |
| 1676 } |
| 1677 |
| 1678 // Dispatch to Call or Construct depending on whether new.target is undefined. |
| 1679 { |
| 1680 __ CompareRoot(x3, Heap::kUndefinedValueRootIndex); |
| 1681 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq); |
| 1682 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 1683 } |
| 1684 } |
| 1685 |
| 1686 |
| 1687 // static |
1562 void Builtins::Generate_CallFunction(MacroAssembler* masm, | 1688 void Builtins::Generate_CallFunction(MacroAssembler* masm, |
1563 ConvertReceiverMode mode) { | 1689 ConvertReceiverMode mode) { |
1564 // ----------- S t a t e ------------- | 1690 // ----------- S t a t e ------------- |
1565 // -- x0 : the number of arguments (not including the receiver) | 1691 // -- x0 : the number of arguments (not including the receiver) |
1566 // -- x1 : the function to call (checked to be a JSFunction) | 1692 // -- x1 : the function to call (checked to be a JSFunction) |
1567 // ----------------------------------- | 1693 // ----------------------------------- |
1568 __ AssertFunction(x1); | 1694 __ AssertFunction(x1); |
1569 | 1695 |
1570 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 1696 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
1571 // Check that function is not a "classConstructor". | 1697 // Check that function is not a "classConstructor". |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2039 } | 2165 } |
2040 } | 2166 } |
2041 | 2167 |
2042 | 2168 |
2043 #undef __ | 2169 #undef __ |
2044 | 2170 |
2045 } // namespace internal | 2171 } // namespace internal |
2046 } // namespace v8 | 2172 } // namespace v8 |
2047 | 2173 |
2048 #endif // V8_TARGET_ARCH_ARM | 2174 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |