OLD | NEW |
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_ARM | 5 #if V8_TARGET_ARCH_ARM |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.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 1317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 // (which is a copy of the last argument). | 1328 // (which is a copy of the last argument). |
1329 __ sub(r0, r0, Operand(1)); | 1329 __ sub(r0, r0, Operand(1)); |
1330 __ pop(); | 1330 __ pop(); |
1331 } | 1331 } |
1332 | 1332 |
1333 // 4. Call the callable. | 1333 // 4. Call the callable. |
1334 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1334 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1335 } | 1335 } |
1336 | 1336 |
1337 | 1337 |
1338 static void Generate_PushAppliedArguments(MacroAssembler* masm, | |
1339 const int vectorOffset, | |
1340 const int argumentsOffset, | |
1341 const int indexOffset, | |
1342 const int limitOffset) { | |
1343 Label entry, loop; | |
1344 Register receiver = LoadDescriptor::ReceiverRegister(); | |
1345 Register key = LoadDescriptor::NameRegister(); | |
1346 Register slot = LoadDescriptor::SlotRegister(); | |
1347 Register vector = LoadWithVectorDescriptor::VectorRegister(); | |
1348 | |
1349 __ ldr(key, MemOperand(fp, indexOffset)); | |
1350 __ b(&entry); | |
1351 | |
1352 // Load the current argument from the arguments array. | |
1353 __ bind(&loop); | |
1354 __ ldr(receiver, MemOperand(fp, argumentsOffset)); | |
1355 | |
1356 // Use inline caching to speed up access to arguments. | |
1357 int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); | |
1358 __ mov(slot, Operand(Smi::FromInt(slot_index))); | |
1359 __ ldr(vector, MemOperand(fp, vectorOffset)); | |
1360 Handle<Code> ic = | |
1361 KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); | |
1362 __ Call(ic, RelocInfo::CODE_TARGET); | |
1363 | |
1364 // Push the nth argument. | |
1365 __ push(r0); | |
1366 | |
1367 __ ldr(key, MemOperand(fp, indexOffset)); | |
1368 __ add(key, key, Operand(1 << kSmiTagSize)); | |
1369 __ str(key, MemOperand(fp, indexOffset)); | |
1370 | |
1371 // Test if the copy loop has finished copying all the elements from the | |
1372 // arguments object. | |
1373 __ bind(&entry); | |
1374 __ ldr(r1, MemOperand(fp, limitOffset)); | |
1375 __ cmp(key, r1); | |
1376 __ b(ne, &loop); | |
1377 | |
1378 // On exit, the pushed arguments count is in r0, untagged | |
1379 __ mov(r0, key); | |
1380 __ SmiUntag(r0); | |
1381 } | |
1382 | |
1383 | |
1384 // Used by FunctionApply and ReflectApply | |
1385 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { | |
1386 const int kFormalParameters = targetIsArgument ? 3 : 2; | |
1387 const int kStackSize = kFormalParameters + 1; | |
1388 | |
1389 { | |
1390 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); | |
1391 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; | |
1392 const int kReceiverOffset = kArgumentsOffset + kPointerSize; | |
1393 const int kFunctionOffset = kReceiverOffset + kPointerSize; | |
1394 const int kVectorOffset = | |
1395 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; | |
1396 | |
1397 // Push the vector. | |
1398 __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
1399 __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kFeedbackVectorOffset)); | |
1400 __ Push(r1); | |
1401 | |
1402 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function | |
1403 __ ldr(r1, MemOperand(fp, kArgumentsOffset)); // get the args array | |
1404 __ Push(r0, r1); | |
1405 if (targetIsArgument) { | |
1406 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, | |
1407 CALL_FUNCTION); | |
1408 } else { | |
1409 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); | |
1410 } | |
1411 | |
1412 Generate_CheckStackOverflow(masm, r0, kArgcIsSmiTagged); | |
1413 | |
1414 // Push current limit and index. | |
1415 const int kIndexOffset = kVectorOffset - (2 * kPointerSize); | |
1416 const int kLimitOffset = kVectorOffset - (1 * kPointerSize); | |
1417 __ mov(r1, Operand::Zero()); | |
1418 __ ldr(r2, MemOperand(fp, kReceiverOffset)); | |
1419 __ Push(r0, r1, r2); // limit, initial index and receiver. | |
1420 | |
1421 // Copy all arguments from the array to the stack. | |
1422 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, | |
1423 kIndexOffset, kLimitOffset); | |
1424 | |
1425 // Call the callable. | |
1426 // TODO(bmeurer): This should be a tail call according to ES6. | |
1427 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | |
1428 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
1429 | |
1430 // Tear down the internal frame and remove function, receiver and args. | |
1431 } | |
1432 __ add(sp, sp, Operand(kStackSize * kPointerSize)); | |
1433 __ Jump(lr); | |
1434 } | |
1435 | |
1436 | |
1437 static void Generate_ConstructHelper(MacroAssembler* masm) { | |
1438 const int kFormalParameters = 3; | |
1439 const int kStackSize = kFormalParameters + 1; | |
1440 | |
1441 { | |
1442 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); | |
1443 const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; | |
1444 const int kArgumentsOffset = kNewTargetOffset + kPointerSize; | |
1445 const int kFunctionOffset = kArgumentsOffset + kPointerSize; | |
1446 static const int kVectorOffset = | |
1447 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; | |
1448 | |
1449 // Push the vector. | |
1450 __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
1451 __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kFeedbackVectorOffset)); | |
1452 __ Push(r1); | |
1453 | |
1454 // If newTarget is not supplied, set it to constructor | |
1455 Label validate_arguments; | |
1456 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); | |
1457 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); | |
1458 __ b(ne, &validate_arguments); | |
1459 __ ldr(r0, MemOperand(fp, kFunctionOffset)); | |
1460 __ str(r0, MemOperand(fp, kNewTargetOffset)); | |
1461 | |
1462 // Validate arguments | |
1463 __ bind(&validate_arguments); | |
1464 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function | |
1465 __ push(r0); | |
1466 __ ldr(r0, MemOperand(fp, kArgumentsOffset)); // get the args array | |
1467 __ push(r0); | |
1468 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); // get the new.target | |
1469 __ push(r0); | |
1470 __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, | |
1471 CALL_FUNCTION); | |
1472 | |
1473 Generate_CheckStackOverflow(masm, r0, kArgcIsSmiTagged); | |
1474 | |
1475 // Push current limit and index. | |
1476 const int kIndexOffset = kVectorOffset - (2 * kPointerSize); | |
1477 const int kLimitOffset = kVectorOffset - (1 * kPointerSize); | |
1478 __ push(r0); // limit | |
1479 __ mov(r1, Operand::Zero()); // initial index | |
1480 __ push(r1); | |
1481 // Push the constructor function as callee. | |
1482 __ ldr(r0, MemOperand(fp, kFunctionOffset)); | |
1483 __ push(r0); | |
1484 | |
1485 // Copy all arguments from the array to the stack. | |
1486 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, | |
1487 kIndexOffset, kLimitOffset); | |
1488 | |
1489 // Use undefined feedback vector | |
1490 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | |
1491 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | |
1492 __ ldr(r3, MemOperand(fp, kNewTargetOffset)); | |
1493 | |
1494 // Call the function. | |
1495 __ Call(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | |
1496 | |
1497 // Leave internal frame. | |
1498 } | |
1499 __ add(sp, sp, Operand(kStackSize * kPointerSize)); | |
1500 __ Jump(lr); | |
1501 } | |
1502 | |
1503 | |
1504 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1338 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
1505 Generate_ApplyHelper(masm, false); | 1339 // ----------- S t a t e ------------- |
| 1340 // -- r0 : argc |
| 1341 // -- sp[0] : argArray |
| 1342 // -- sp[4] : thisArg |
| 1343 // -- sp[8] : receiver |
| 1344 // ----------------------------------- |
| 1345 |
| 1346 // 1. Load receiver into r1, argArray into r0 (if present), remove all |
| 1347 // arguments from the stack (including the receiver), and push thisArg (if |
| 1348 // present) instead. |
| 1349 { |
| 1350 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
| 1351 __ mov(r3, r2); |
| 1352 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); // receiver |
| 1353 __ sub(r4, r0, Operand(1), SetCC); |
| 1354 __ ldr(r2, MemOperand(sp, r4, LSL, kPointerSizeLog2), ge); // thisArg |
| 1355 __ sub(r4, r4, Operand(1), SetCC, ge); |
| 1356 __ ldr(r3, MemOperand(sp, r4, LSL, kPointerSizeLog2), ge); // argArray |
| 1357 __ add(sp, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 1358 __ str(r2, MemOperand(sp, 0)); |
| 1359 __ mov(r0, r3); |
| 1360 } |
| 1361 |
| 1362 // ----------- S t a t e ------------- |
| 1363 // -- r0 : argArray |
| 1364 // -- r1 : receiver |
| 1365 // -- sp[0] : thisArg |
| 1366 // ----------------------------------- |
| 1367 |
| 1368 // 2. Make sure the receiver is actually callable. |
| 1369 Label receiver_not_callable; |
| 1370 __ JumpIfSmi(r1, &receiver_not_callable); |
| 1371 __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 1372 __ ldrb(r4, FieldMemOperand(r4, Map::kBitFieldOffset)); |
| 1373 __ tst(r4, Operand(1 << Map::kIsCallable)); |
| 1374 __ b(eq, &receiver_not_callable); |
| 1375 |
| 1376 // 3. Tail call with no arguments if argArray is null or undefined. |
| 1377 Label no_arguments; |
| 1378 __ JumpIfRoot(r0, Heap::kNullValueRootIndex, &no_arguments); |
| 1379 __ JumpIfRoot(r0, Heap::kUndefinedValueRootIndex, &no_arguments); |
| 1380 |
| 1381 // 4a. Apply the receiver to the given argArray (passing undefined for |
| 1382 // new.target). |
| 1383 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
| 1384 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |
| 1385 |
| 1386 // 4b. The argArray is either null or undefined, so we tail call without any |
| 1387 // arguments to the receiver. |
| 1388 __ bind(&no_arguments); |
| 1389 { |
| 1390 __ mov(r0, Operand(0)); |
| 1391 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1392 } |
| 1393 |
| 1394 // 4c. The receiver is not callable, throw an appropriate TypeError. |
| 1395 __ bind(&receiver_not_callable); |
| 1396 { |
| 1397 __ str(r1, MemOperand(sp, 0)); |
| 1398 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1); |
| 1399 } |
1506 } | 1400 } |
1507 | 1401 |
1508 | 1402 |
1509 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 1403 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
1510 Generate_ApplyHelper(masm, true); | 1404 // ----------- S t a t e ------------- |
| 1405 // -- r0 : argc |
| 1406 // -- sp[0] : argumentsList |
| 1407 // -- sp[4] : thisArgument |
| 1408 // -- sp[8] : target |
| 1409 // -- sp[12] : receiver |
| 1410 // ----------------------------------- |
| 1411 |
| 1412 // 1. Load target into r1 (if present), argumentsList into r0 (if present), |
| 1413 // remove all arguments from the stack (including the receiver), and push |
| 1414 // thisArgument (if present) instead. |
| 1415 { |
| 1416 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| 1417 __ mov(r2, r1); |
| 1418 __ mov(r3, r1); |
| 1419 __ sub(r4, r0, Operand(1), SetCC); |
| 1420 __ ldr(r1, MemOperand(sp, r4, LSL, kPointerSizeLog2), ge); // target |
| 1421 __ sub(r4, r4, Operand(1), SetCC, ge); |
| 1422 __ ldr(r2, MemOperand(sp, r4, LSL, kPointerSizeLog2), ge); // thisArgument |
| 1423 __ sub(r4, r4, Operand(1), SetCC, ge); |
| 1424 __ ldr(r3, MemOperand(sp, r4, LSL, kPointerSizeLog2), ge); // argumentsList |
| 1425 __ add(sp, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 1426 __ str(r2, MemOperand(sp, 0)); |
| 1427 __ mov(r0, r3); |
| 1428 } |
| 1429 |
| 1430 // ----------- S t a t e ------------- |
| 1431 // -- r0 : argumentsList |
| 1432 // -- r1 : target |
| 1433 // -- sp[0] : thisArgument |
| 1434 // ----------------------------------- |
| 1435 |
| 1436 // 2. Make sure the target is actually callable. |
| 1437 Label target_not_callable; |
| 1438 __ JumpIfSmi(r1, &target_not_callable); |
| 1439 __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 1440 __ ldrb(r4, FieldMemOperand(r4, Map::kBitFieldOffset)); |
| 1441 __ tst(r4, Operand(1 << Map::kIsCallable)); |
| 1442 __ b(eq, &target_not_callable); |
| 1443 |
| 1444 // 3a. Apply the target to the given argumentsList (passing undefined for |
| 1445 // new.target). |
| 1446 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
| 1447 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |
| 1448 |
| 1449 // 3b. The target is not callable, throw an appropriate TypeError. |
| 1450 __ bind(&target_not_callable); |
| 1451 { |
| 1452 __ str(r1, MemOperand(sp, 0)); |
| 1453 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1); |
| 1454 } |
1511 } | 1455 } |
1512 | 1456 |
1513 | 1457 |
1514 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 1458 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
1515 Generate_ConstructHelper(masm); | 1459 // ----------- S t a t e ------------- |
| 1460 // -- r0 : argc |
| 1461 // -- sp[0] : new.target (optional) |
| 1462 // -- sp[4] : argumentsList |
| 1463 // -- sp[8] : target |
| 1464 // -- sp[12] : receiver |
| 1465 // ----------------------------------- |
| 1466 |
| 1467 // 1. Load target into r1 (if present), argumentsList into r0 (if present), |
| 1468 // new.target into r3 (if present, otherwise use target), remove all |
| 1469 // arguments from the stack (including the receiver), and push thisArgument |
| 1470 // (if present) instead. |
| 1471 { |
| 1472 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| 1473 __ mov(r2, r1); |
| 1474 __ str(r2, MemOperand(sp, r0, LSL, kPointerSizeLog2)); // receiver |
| 1475 __ sub(r4, r0, Operand(1), SetCC); |
| 1476 __ ldr(r1, MemOperand(sp, r4, LSL, kPointerSizeLog2), ge); // target |
| 1477 __ mov(r3, r1); // new.target defaults to target |
| 1478 __ sub(r4, r4, Operand(1), SetCC, ge); |
| 1479 __ ldr(r2, MemOperand(sp, r4, LSL, kPointerSizeLog2), ge); // argumentsList |
| 1480 __ sub(r4, r4, Operand(1), SetCC, ge); |
| 1481 __ ldr(r3, MemOperand(sp, r4, LSL, kPointerSizeLog2), ge); // new.target |
| 1482 __ add(sp, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 1483 __ mov(r0, r2); |
| 1484 } |
| 1485 |
| 1486 // ----------- S t a t e ------------- |
| 1487 // -- r0 : argumentsList |
| 1488 // -- r3 : new.target |
| 1489 // -- r1 : target |
| 1490 // -- sp[0] : receiver (undefined) |
| 1491 // ----------------------------------- |
| 1492 |
| 1493 // 2. Make sure the target is actually a constructor. |
| 1494 Label target_not_constructor; |
| 1495 __ JumpIfSmi(r1, &target_not_constructor); |
| 1496 __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 1497 __ ldrb(r4, FieldMemOperand(r4, Map::kBitFieldOffset)); |
| 1498 __ tst(r4, Operand(1 << Map::kIsConstructor)); |
| 1499 __ b(eq, &target_not_constructor); |
| 1500 |
| 1501 // 3. Make sure the target is actually a constructor. |
| 1502 Label new_target_not_constructor; |
| 1503 __ JumpIfSmi(r3, &new_target_not_constructor); |
| 1504 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| 1505 __ ldrb(r4, FieldMemOperand(r4, Map::kBitFieldOffset)); |
| 1506 __ tst(r4, Operand(1 << Map::kIsConstructor)); |
| 1507 __ b(eq, &new_target_not_constructor); |
| 1508 |
| 1509 // 4a. Construct the target with the given new.target and argumentsList. |
| 1510 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |
| 1511 |
| 1512 // 4b. The target is not a constructor, throw an appropriate TypeError. |
| 1513 __ bind(&target_not_constructor); |
| 1514 { |
| 1515 __ str(r1, MemOperand(sp, 0)); |
| 1516 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1); |
| 1517 } |
| 1518 |
| 1519 // 4c. The new.target is not a constructor, throw an appropriate TypeError. |
| 1520 __ bind(&new_target_not_constructor); |
| 1521 { |
| 1522 __ str(r3, MemOperand(sp, 0)); |
| 1523 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1); |
| 1524 } |
1516 } | 1525 } |
1517 | 1526 |
1518 | 1527 |
1519 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, | 1528 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, |
1520 Label* stack_overflow) { | 1529 Label* stack_overflow) { |
1521 // ----------- S t a t e ------------- | 1530 // ----------- S t a t e ------------- |
1522 // -- r0 : actual number of arguments | 1531 // -- r0 : actual number of arguments |
1523 // -- r1 : function (passed through to callee) | 1532 // -- r1 : function (passed through to callee) |
1524 // -- r2 : expected number of arguments | 1533 // -- r2 : expected number of arguments |
1525 // -- r3 : new target (passed through to callee) | 1534 // -- r3 : new target (passed through to callee) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 __ ldr(r1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + | 1566 __ ldr(r1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + |
1558 kPointerSize))); | 1567 kPointerSize))); |
1559 | 1568 |
1560 __ LeaveFrame(StackFrame::ARGUMENTS_ADAPTOR); | 1569 __ LeaveFrame(StackFrame::ARGUMENTS_ADAPTOR); |
1561 __ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1)); | 1570 __ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1)); |
1562 __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver | 1571 __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver |
1563 } | 1572 } |
1564 | 1573 |
1565 | 1574 |
1566 // static | 1575 // static |
| 1576 void Builtins::Generate_Apply(MacroAssembler* masm) { |
| 1577 // ----------- S t a t e ------------- |
| 1578 // -- r0 : argumentsList |
| 1579 // -- r1 : target |
| 1580 // -- r3 : new.target (checked to be constructor or undefined) |
| 1581 // -- sp[0] : thisArgument |
| 1582 // ----------------------------------- |
| 1583 |
| 1584 // Create the list of arguments from the array-like argumentsList. |
| 1585 { |
| 1586 Label create_arguments, create_array, create_runtime, done_create; |
| 1587 __ JumpIfSmi(r0, &create_runtime); |
| 1588 |
| 1589 // Load the map of argumentsList into r2. |
| 1590 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 1591 |
| 1592 // Load native context into r4. |
| 1593 __ ldr(r4, NativeContextMemOperand()); |
| 1594 |
| 1595 // Check if argumentsList is an (unmodified) arguments object. |
| 1596 __ ldr(ip, ContextMemOperand(r4, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); |
| 1597 __ cmp(ip, r2); |
| 1598 __ b(eq, &create_arguments); |
| 1599 __ ldr(ip, ContextMemOperand(r4, Context::STRICT_ARGUMENTS_MAP_INDEX)); |
| 1600 __ cmp(ip, r2); |
| 1601 __ b(eq, &create_arguments); |
| 1602 |
| 1603 // Check if argumentsList is a fast JSArray. |
| 1604 __ CompareInstanceType(r2, ip, JS_ARRAY_TYPE); |
| 1605 __ b(eq, &create_array); |
| 1606 |
| 1607 // Ask the runtime to create the list (actually a FixedArray). |
| 1608 __ bind(&create_runtime); |
| 1609 { |
| 1610 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 1611 __ Push(r1, r3, r0); |
| 1612 __ CallRuntime(Runtime::kCreateListFromArrayLike, 1); |
| 1613 __ Pop(r1, r3); |
| 1614 __ ldr(r2, FieldMemOperand(r0, FixedArray::kLengthOffset)); |
| 1615 __ SmiUntag(r2); |
| 1616 } |
| 1617 __ jmp(&done_create); |
| 1618 |
| 1619 // Try to create the list from an arguments object. |
| 1620 __ bind(&create_arguments); |
| 1621 __ ldr(r2, |
| 1622 FieldMemOperand(r0, JSObject::kHeaderSize + |
| 1623 Heap::kArgumentsLengthIndex * kPointerSize)); |
| 1624 __ ldr(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 1625 __ ldr(ip, FieldMemOperand(r4, FixedArray::kLengthOffset)); |
| 1626 __ cmp(r2, ip); |
| 1627 __ b(ne, &create_runtime); |
| 1628 __ SmiUntag(r2); |
| 1629 __ mov(r0, r4); |
| 1630 __ b(&done_create); |
| 1631 |
| 1632 // Try to create the list from a JSArray object. |
| 1633 __ bind(&create_array); |
| 1634 __ ldr(r2, FieldMemOperand(r2, Map::kBitField2Offset)); |
| 1635 __ DecodeField<Map::ElementsKindBits>(r2); |
| 1636 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); |
| 1637 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
| 1638 STATIC_ASSERT(FAST_ELEMENTS == 2); |
| 1639 __ cmp(r2, Operand(FAST_ELEMENTS)); |
| 1640 __ b(hi, &create_runtime); |
| 1641 __ cmp(r2, Operand(FAST_HOLEY_SMI_ELEMENTS)); |
| 1642 __ b(eq, &create_runtime); |
| 1643 __ ldr(r2, FieldMemOperand(r0, JSArray::kLengthOffset)); |
| 1644 __ ldr(r0, FieldMemOperand(r0, JSArray::kElementsOffset)); |
| 1645 __ SmiUntag(r2); |
| 1646 |
| 1647 __ bind(&done_create); |
| 1648 } |
| 1649 |
| 1650 // Check for stack overflow. |
| 1651 { |
| 1652 // Check the stack for overflow. We are not trying to catch interruptions |
| 1653 // (i.e. debug break and preemption) here, so check the "real stack limit". |
| 1654 Label done; |
| 1655 __ LoadRoot(ip, Heap::kRealStackLimitRootIndex); |
| 1656 // Make ip the space we have left. The stack might already be overflowed |
| 1657 // here which will cause ip to become negative. |
| 1658 __ sub(ip, sp, ip); |
| 1659 // Check if the arguments will overflow the stack. |
| 1660 __ cmp(ip, Operand(r2, LSL, kPointerSizeLog2)); |
| 1661 __ b(gt, &done); // Signed comparison. |
| 1662 __ TailCallRuntime(Runtime::kThrowStackOverflow, 1, 1); |
| 1663 __ bind(&done); |
| 1664 } |
| 1665 |
| 1666 // ----------- S t a t e ------------- |
| 1667 // -- r1 : target |
| 1668 // -- r0 : args (a FixedArray built from argumentsList) |
| 1669 // -- r2 : len (number of elements to push from args) |
| 1670 // -- r3 : new.target (checked to be constructor or undefined) |
| 1671 // -- sp[0] : thisArgument |
| 1672 // ----------------------------------- |
| 1673 |
| 1674 // Push arguments onto the stack (thisArgument is already on the stack). |
| 1675 { |
| 1676 __ mov(r4, Operand(0)); |
| 1677 Label done, loop; |
| 1678 __ bind(&loop); |
| 1679 __ cmp(r4, r2); |
| 1680 __ b(eq, &done); |
| 1681 __ add(ip, r0, Operand(r4, LSL, kPointerSizeLog2)); |
| 1682 __ ldr(ip, FieldMemOperand(ip, FixedArray::kHeaderSize)); |
| 1683 __ Push(ip); |
| 1684 __ add(r4, r4, Operand(1)); |
| 1685 __ b(&loop); |
| 1686 __ bind(&done); |
| 1687 __ Move(r0, r4); |
| 1688 } |
| 1689 |
| 1690 // Dispatch to Call or Construct depending on whether new.target is undefined. |
| 1691 { |
| 1692 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); |
| 1693 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq); |
| 1694 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 1695 } |
| 1696 } |
| 1697 |
| 1698 |
| 1699 // static |
1567 void Builtins::Generate_CallFunction(MacroAssembler* masm, | 1700 void Builtins::Generate_CallFunction(MacroAssembler* masm, |
1568 ConvertReceiverMode mode) { | 1701 ConvertReceiverMode mode) { |
1569 // ----------- S t a t e ------------- | 1702 // ----------- S t a t e ------------- |
1570 // -- r0 : the number of arguments (not including the receiver) | 1703 // -- r0 : the number of arguments (not including the receiver) |
1571 // -- r1 : the function to call (checked to be a JSFunction) | 1704 // -- r1 : the function to call (checked to be a JSFunction) |
1572 // ----------------------------------- | 1705 // ----------------------------------- |
1573 __ AssertFunction(r1); | 1706 __ AssertFunction(r1); |
1574 | 1707 |
1575 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 1708 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
1576 // Check that the function is not a "classConstructor". | 1709 // Check that the function is not a "classConstructor". |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1951 } | 2084 } |
1952 } | 2085 } |
1953 | 2086 |
1954 | 2087 |
1955 #undef __ | 2088 #undef __ |
1956 | 2089 |
1957 } // namespace internal | 2090 } // namespace internal |
1958 } // namespace v8 | 2091 } // namespace v8 |
1959 | 2092 |
1960 #endif // V8_TARGET_ARCH_ARM | 2093 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |