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