| 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/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 1475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1486 | 1486 |
| 1487 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 1487 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
| 1488 // by calling the runtime system. | 1488 // by calling the runtime system. |
| 1489 __ bind(&slow); | 1489 __ bind(&slow); |
| 1490 __ push(r1); | 1490 __ push(r1); |
| 1491 __ TailCallRuntime(Runtime::kArguments, 1, 1); | 1491 __ TailCallRuntime(Runtime::kArguments, 1, 1); |
| 1492 } | 1492 } |
| 1493 | 1493 |
| 1494 | 1494 |
| 1495 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { | 1495 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { |
| 1496 // sp[0] : number of parameters | 1496 // r1 : function |
| 1497 // sp[4] : receiver displacement | 1497 // r2 : number of parameters (tagged) |
| 1498 // sp[8] : function | 1498 // r3 : parameters pointer |
| 1499 |
| 1500 DCHECK(r1.is(ArgumentsAccessNewDescriptor::function())); |
| 1501 DCHECK(r2.is(ArgumentsAccessNewDescriptor::parameter_count())); |
| 1502 DCHECK(r3.is(ArgumentsAccessNewDescriptor::parameter_pointer())); |
| 1499 | 1503 |
| 1500 // Check if the calling frame is an arguments adaptor frame. | 1504 // Check if the calling frame is an arguments adaptor frame. |
| 1501 Label runtime; | 1505 Label runtime; |
| 1502 __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1506 __ ldr(r4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1503 __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset)); | 1507 __ ldr(r0, MemOperand(r4, StandardFrameConstants::kContextOffset)); |
| 1504 __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1508 __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1505 __ b(ne, &runtime); | 1509 __ b(ne, &runtime); |
| 1506 | 1510 |
| 1507 // Patch the arguments.length and the parameters pointer in the current frame. | 1511 // Patch the arguments.length and the parameters pointer in the current frame. |
| 1508 __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1512 __ ldr(r2, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 1509 __ str(r2, MemOperand(sp, 0 * kPointerSize)); | 1513 __ add(r4, r4, Operand(r2, LSL, 1)); |
| 1510 __ add(r3, r3, Operand(r2, LSL, 1)); | 1514 __ add(r3, r4, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 1511 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); | |
| 1512 __ str(r3, MemOperand(sp, 1 * kPointerSize)); | |
| 1513 | 1515 |
| 1514 __ bind(&runtime); | 1516 __ bind(&runtime); |
| 1517 __ Push(r1, r3, r2); |
| 1515 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); | 1518 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); |
| 1516 } | 1519 } |
| 1517 | 1520 |
| 1518 | 1521 |
| 1519 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { | 1522 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { |
| 1520 // Stack layout: | 1523 // r1 : function |
| 1521 // sp[0] : number of parameters (tagged) | 1524 // r2 : number of parameters (tagged) |
| 1522 // sp[4] : address of receiver argument | 1525 // r3 : parameters pointer |
| 1523 // sp[8] : function | |
| 1524 // Registers used over whole function: | 1526 // Registers used over whole function: |
| 1525 // r6 : allocated object (tagged) | 1527 // r5 : arguments count (tagged) |
| 1526 // r9 : mapped parameter count (tagged) | 1528 // r6 : mapped parameter count (tagged) |
| 1527 | 1529 |
| 1528 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); | 1530 DCHECK(r1.is(ArgumentsAccessNewDescriptor::function())); |
| 1529 // r1 = parameter count (tagged) | 1531 DCHECK(r2.is(ArgumentsAccessNewDescriptor::parameter_count())); |
| 1532 DCHECK(r3.is(ArgumentsAccessNewDescriptor::parameter_pointer())); |
| 1530 | 1533 |
| 1531 // Check if the calling frame is an arguments adaptor frame. | 1534 // Check if the calling frame is an arguments adaptor frame. |
| 1532 Label runtime; | 1535 Label adaptor_frame, try_allocate, runtime; |
| 1533 Label adaptor_frame, try_allocate; | 1536 __ ldr(r4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1534 __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1537 __ ldr(r0, MemOperand(r4, StandardFrameConstants::kContextOffset)); |
| 1535 __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset)); | 1538 __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1536 __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
| 1537 __ b(eq, &adaptor_frame); | 1539 __ b(eq, &adaptor_frame); |
| 1538 | 1540 |
| 1539 // No adaptor, parameter count = argument count. | 1541 // No adaptor, parameter count = argument count. |
| 1540 __ mov(r2, r1); | 1542 __ mov(r5, r2); |
| 1543 __ mov(r6, r2); |
| 1541 __ b(&try_allocate); | 1544 __ b(&try_allocate); |
| 1542 | 1545 |
| 1543 // We have an adaptor frame. Patch the parameters pointer. | 1546 // We have an adaptor frame. Patch the parameters pointer. |
| 1544 __ bind(&adaptor_frame); | 1547 __ bind(&adaptor_frame); |
| 1545 __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1548 __ ldr(r5, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 1546 __ add(r3, r3, Operand(r2, LSL, 1)); | 1549 __ add(r4, r4, Operand(r5, LSL, 1)); |
| 1547 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); | 1550 __ add(r3, r4, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 1548 __ str(r3, MemOperand(sp, 1 * kPointerSize)); | |
| 1549 | 1551 |
| 1550 // r1 = parameter count (tagged) | 1552 // r5 = argument count (tagged) |
| 1551 // r2 = argument count (tagged) | 1553 // r6 = parameter count (tagged) |
| 1552 // Compute the mapped parameter count = min(r1, r2) in r1. | 1554 // Compute the mapped parameter count = min(r6, r5) in r6. |
| 1553 __ cmp(r1, Operand(r2)); | 1555 __ mov(r6, r2); |
| 1554 __ mov(r1, Operand(r2), LeaveCC, gt); | 1556 __ cmp(r6, Operand(r5)); |
| 1557 __ mov(r6, Operand(r5), LeaveCC, gt); |
| 1555 | 1558 |
| 1556 __ bind(&try_allocate); | 1559 __ bind(&try_allocate); |
| 1557 | 1560 |
| 1558 // Compute the sizes of backing store, parameter map, and arguments object. | 1561 // Compute the sizes of backing store, parameter map, and arguments object. |
| 1559 // 1. Parameter map, has 2 extra words containing context and backing store. | 1562 // 1. Parameter map, has 2 extra words containing context and backing store. |
| 1560 const int kParameterMapHeaderSize = | 1563 const int kParameterMapHeaderSize = |
| 1561 FixedArray::kHeaderSize + 2 * kPointerSize; | 1564 FixedArray::kHeaderSize + 2 * kPointerSize; |
| 1562 // If there are no mapped parameters, we do not need the parameter_map. | 1565 // If there are no mapped parameters, we do not need the parameter_map. |
| 1563 __ cmp(r1, Operand(Smi::FromInt(0))); | 1566 __ cmp(r6, Operand(Smi::FromInt(0))); |
| 1564 __ mov(r9, Operand::Zero(), LeaveCC, eq); | 1567 __ mov(r9, Operand::Zero(), LeaveCC, eq); |
| 1565 __ mov(r9, Operand(r1, LSL, 1), LeaveCC, ne); | 1568 __ mov(r9, Operand(r6, LSL, 1), LeaveCC, ne); |
| 1566 __ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne); | 1569 __ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne); |
| 1567 | 1570 |
| 1568 // 2. Backing store. | 1571 // 2. Backing store. |
| 1569 __ add(r9, r9, Operand(r2, LSL, 1)); | 1572 __ add(r9, r9, Operand(r5, LSL, 1)); |
| 1570 __ add(r9, r9, Operand(FixedArray::kHeaderSize)); | 1573 __ add(r9, r9, Operand(FixedArray::kHeaderSize)); |
| 1571 | 1574 |
| 1572 // 3. Arguments object. | 1575 // 3. Arguments object. |
| 1573 __ add(r9, r9, Operand(Heap::kSloppyArgumentsObjectSize)); | 1576 __ add(r9, r9, Operand(Heap::kSloppyArgumentsObjectSize)); |
| 1574 | 1577 |
| 1575 // Do the allocation of all three objects in one go. | 1578 // Do the allocation of all three objects in one go. |
| 1576 __ Allocate(r9, r0, r3, r4, &runtime, TAG_OBJECT); | 1579 __ Allocate(r9, r0, r4, r9, &runtime, TAG_OBJECT); |
| 1577 | 1580 |
| 1578 // r0 = address of new object(s) (tagged) | 1581 // r0 = address of new object(s) (tagged) |
| 1579 // r2 = argument count (smi-tagged) | 1582 // r2 = argument count (smi-tagged) |
| 1580 // Get the arguments boilerplate from the current native context into r4. | 1583 // Get the arguments boilerplate from the current native context into r4. |
| 1581 const int kNormalOffset = | 1584 const int kNormalOffset = |
| 1582 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); | 1585 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); |
| 1583 const int kAliasedOffset = | 1586 const int kAliasedOffset = |
| 1584 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); | 1587 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); |
| 1585 | 1588 |
| 1586 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1589 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 1587 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); | 1590 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); |
| 1588 __ cmp(r1, Operand::Zero()); | 1591 __ cmp(r6, Operand::Zero()); |
| 1589 __ ldr(r4, MemOperand(r4, kNormalOffset), eq); | 1592 __ ldr(r4, MemOperand(r4, kNormalOffset), eq); |
| 1590 __ ldr(r4, MemOperand(r4, kAliasedOffset), ne); | 1593 __ ldr(r4, MemOperand(r4, kAliasedOffset), ne); |
| 1591 | 1594 |
| 1592 // r0 = address of new object (tagged) | 1595 // r0 = address of new object (tagged) |
| 1593 // r1 = mapped parameter count (tagged) | |
| 1594 // r2 = argument count (smi-tagged) | 1596 // r2 = argument count (smi-tagged) |
| 1595 // r4 = address of arguments map (tagged) | 1597 // r4 = address of arguments map (tagged) |
| 1598 // r6 = mapped parameter count (tagged) |
| 1596 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); | 1599 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); |
| 1597 __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); | 1600 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); |
| 1598 __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | 1601 __ str(r9, FieldMemOperand(r0, JSObject::kPropertiesOffset)); |
| 1599 __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); | 1602 __ str(r9, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 1600 | 1603 |
| 1601 // Set up the callee in-object property. | 1604 // Set up the callee in-object property. |
| 1602 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | 1605 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); |
| 1603 __ ldr(r3, MemOperand(sp, 2 * kPointerSize)); | 1606 __ AssertNotSmi(r1); |
| 1604 __ AssertNotSmi(r3); | |
| 1605 const int kCalleeOffset = JSObject::kHeaderSize + | 1607 const int kCalleeOffset = JSObject::kHeaderSize + |
| 1606 Heap::kArgumentsCalleeIndex * kPointerSize; | 1608 Heap::kArgumentsCalleeIndex * kPointerSize; |
| 1607 __ str(r3, FieldMemOperand(r0, kCalleeOffset)); | 1609 __ str(r1, FieldMemOperand(r0, kCalleeOffset)); |
| 1608 | 1610 |
| 1609 // Use the length (smi tagged) and set that as an in-object property too. | 1611 // Use the length (smi tagged) and set that as an in-object property too. |
| 1610 __ AssertSmi(r2); | 1612 __ AssertSmi(r5); |
| 1611 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 1613 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 1612 const int kLengthOffset = JSObject::kHeaderSize + | 1614 const int kLengthOffset = JSObject::kHeaderSize + |
| 1613 Heap::kArgumentsLengthIndex * kPointerSize; | 1615 Heap::kArgumentsLengthIndex * kPointerSize; |
| 1614 __ str(r2, FieldMemOperand(r0, kLengthOffset)); | 1616 __ str(r5, FieldMemOperand(r0, kLengthOffset)); |
| 1615 | 1617 |
| 1616 // Set up the elements pointer in the allocated arguments object. | 1618 // Set up the elements pointer in the allocated arguments object. |
| 1617 // If we allocated a parameter map, r4 will point there, otherwise | 1619 // If we allocated a parameter map, r4 will point there, otherwise |
| 1618 // it will point to the backing store. | 1620 // it will point to the backing store. |
| 1619 __ add(r4, r0, Operand(Heap::kSloppyArgumentsObjectSize)); | 1621 __ add(r4, r0, Operand(Heap::kSloppyArgumentsObjectSize)); |
| 1620 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); | 1622 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 1621 | 1623 |
| 1622 // r0 = address of new object (tagged) | 1624 // r0 = address of new object (tagged) |
| 1623 // r1 = mapped parameter count (tagged) | |
| 1624 // r2 = argument count (tagged) | 1625 // r2 = argument count (tagged) |
| 1625 // r4 = address of parameter map or backing store (tagged) | 1626 // r4 = address of parameter map or backing store (tagged) |
| 1627 // r6 = mapped parameter count (tagged) |
| 1626 // Initialize parameter map. If there are no mapped arguments, we're done. | 1628 // Initialize parameter map. If there are no mapped arguments, we're done. |
| 1627 Label skip_parameter_map; | 1629 Label skip_parameter_map; |
| 1628 __ cmp(r1, Operand(Smi::FromInt(0))); | 1630 __ cmp(r6, Operand(Smi::FromInt(0))); |
| 1629 // Move backing store address to r3, because it is | 1631 // Move backing store address to r1, because it is |
| 1630 // expected there when filling in the unmapped arguments. | 1632 // expected there when filling in the unmapped arguments. |
| 1631 __ mov(r3, r4, LeaveCC, eq); | 1633 __ mov(r1, r4, LeaveCC, eq); |
| 1632 __ b(eq, &skip_parameter_map); | 1634 __ b(eq, &skip_parameter_map); |
| 1633 | 1635 |
| 1634 __ LoadRoot(r6, Heap::kSloppyArgumentsElementsMapRootIndex); | 1636 __ LoadRoot(r5, Heap::kSloppyArgumentsElementsMapRootIndex); |
| 1635 __ str(r6, FieldMemOperand(r4, FixedArray::kMapOffset)); | 1637 __ str(r5, FieldMemOperand(r4, FixedArray::kMapOffset)); |
| 1636 __ add(r6, r1, Operand(Smi::FromInt(2))); | 1638 __ add(r5, r6, Operand(Smi::FromInt(2))); |
| 1637 __ str(r6, FieldMemOperand(r4, FixedArray::kLengthOffset)); | 1639 __ str(r5, FieldMemOperand(r4, FixedArray::kLengthOffset)); |
| 1638 __ str(cp, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize)); | 1640 __ str(cp, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize)); |
| 1639 __ add(r6, r4, Operand(r1, LSL, 1)); | 1641 __ add(r5, r4, Operand(r6, LSL, 1)); |
| 1640 __ add(r6, r6, Operand(kParameterMapHeaderSize)); | 1642 __ add(r5, r5, Operand(kParameterMapHeaderSize)); |
| 1641 __ str(r6, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize)); | 1643 __ str(r5, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize)); |
| 1642 | 1644 |
| 1643 // Copy the parameter slots and the holes in the arguments. | 1645 // Copy the parameter slots and the holes in the arguments. |
| 1644 // We need to fill in mapped_parameter_count slots. They index the context, | 1646 // We need to fill in mapped_parameter_count slots. They index the context, |
| 1645 // where parameters are stored in reverse order, at | 1647 // where parameters are stored in reverse order, at |
| 1646 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | 1648 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 |
| 1647 // The mapped parameter thus need to get indices | 1649 // The mapped parameter thus need to get indices |
| 1648 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | 1650 // MIN_CONTEXT_SLOTS+parameter_count-1 .. |
| 1649 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | 1651 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count |
| 1650 // We loop from right to left. | 1652 // We loop from right to left. |
| 1651 Label parameters_loop, parameters_test; | 1653 Label parameters_loop, parameters_test; |
| 1652 __ mov(r6, r1); | 1654 __ mov(r5, r6); |
| 1653 __ ldr(r9, MemOperand(sp, 0 * kPointerSize)); | 1655 __ add(r9, r2, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); |
| 1654 __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); | 1656 __ sub(r9, r9, Operand(r6)); |
| 1655 __ sub(r9, r9, Operand(r1)); | 1657 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 1656 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); | 1658 __ add(r1, r4, Operand(r5, LSL, 1)); |
| 1657 __ add(r3, r4, Operand(r6, LSL, 1)); | 1659 __ add(r1, r1, Operand(kParameterMapHeaderSize)); |
| 1658 __ add(r3, r3, Operand(kParameterMapHeaderSize)); | |
| 1659 | 1660 |
| 1660 // r6 = loop variable (tagged) | 1661 // r1 = address of backing store (tagged) |
| 1661 // r1 = mapping index (tagged) | |
| 1662 // r3 = address of backing store (tagged) | |
| 1663 // r4 = address of parameter map (tagged), which is also the address of new | 1662 // r4 = address of parameter map (tagged), which is also the address of new |
| 1664 // object + Heap::kSloppyArgumentsObjectSize (tagged) | 1663 // object + Heap::kSloppyArgumentsObjectSize (tagged) |
| 1665 // r0 = temporary scratch (a.o., for address calculation) | 1664 // r0 = temporary scratch (a.o., for address calculation) |
| 1666 // r5 = the hole value | 1665 // r5 = loop variable (tagged) |
| 1666 // ip = the hole value |
| 1667 __ jmp(¶meters_test); | 1667 __ jmp(¶meters_test); |
| 1668 | 1668 |
| 1669 __ bind(¶meters_loop); | 1669 __ bind(¶meters_loop); |
| 1670 __ sub(r6, r6, Operand(Smi::FromInt(1))); | 1670 __ sub(r5, r5, Operand(Smi::FromInt(1))); |
| 1671 __ mov(r0, Operand(r6, LSL, 1)); | 1671 __ mov(r0, Operand(r5, LSL, 1)); |
| 1672 __ add(r0, r0, Operand(kParameterMapHeaderSize - kHeapObjectTag)); | 1672 __ add(r0, r0, Operand(kParameterMapHeaderSize - kHeapObjectTag)); |
| 1673 __ str(r9, MemOperand(r4, r0)); | 1673 __ str(r9, MemOperand(r4, r0)); |
| 1674 __ sub(r0, r0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); | 1674 __ sub(r0, r0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); |
| 1675 __ str(r5, MemOperand(r3, r0)); | 1675 __ str(ip, MemOperand(r1, r0)); |
| 1676 __ add(r9, r9, Operand(Smi::FromInt(1))); | 1676 __ add(r9, r9, Operand(Smi::FromInt(1))); |
| 1677 __ bind(¶meters_test); | 1677 __ bind(¶meters_test); |
| 1678 __ cmp(r6, Operand(Smi::FromInt(0))); | 1678 __ cmp(r5, Operand(Smi::FromInt(0))); |
| 1679 __ b(ne, ¶meters_loop); | 1679 __ b(ne, ¶meters_loop); |
| 1680 | 1680 |
| 1681 // Restore r0 = new object (tagged) | 1681 // Restore r0 = new object (tagged) and r5 = argument count (tagged). |
| 1682 __ sub(r0, r4, Operand(Heap::kSloppyArgumentsObjectSize)); | 1682 __ sub(r0, r4, Operand(Heap::kSloppyArgumentsObjectSize)); |
| 1683 __ ldr(r5, FieldMemOperand(r0, kLengthOffset)); |
| 1683 | 1684 |
| 1684 __ bind(&skip_parameter_map); | 1685 __ bind(&skip_parameter_map); |
| 1685 // r0 = address of new object (tagged) | 1686 // r0 = address of new object (tagged) |
| 1686 // r2 = argument count (tagged) | 1687 // r1 = address of backing store (tagged) |
| 1687 // r3 = address of backing store (tagged) | 1688 // r5 = argument count (tagged) |
| 1688 // r5 = scratch | 1689 // r6 = mapped parameter count (tagged) |
| 1690 // r9 = scratch |
| 1689 // Copy arguments header and remaining slots (if there are any). | 1691 // Copy arguments header and remaining slots (if there are any). |
| 1690 __ LoadRoot(r5, Heap::kFixedArrayMapRootIndex); | 1692 __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex); |
| 1691 __ str(r5, FieldMemOperand(r3, FixedArray::kMapOffset)); | 1693 __ str(r9, FieldMemOperand(r1, FixedArray::kMapOffset)); |
| 1692 __ str(r2, FieldMemOperand(r3, FixedArray::kLengthOffset)); | 1694 __ str(r5, FieldMemOperand(r1, FixedArray::kLengthOffset)); |
| 1693 | 1695 |
| 1694 Label arguments_loop, arguments_test; | 1696 Label arguments_loop, arguments_test; |
| 1695 __ mov(r9, r1); | 1697 __ sub(r3, r3, Operand(r6, LSL, 1)); |
| 1696 __ ldr(r4, MemOperand(sp, 1 * kPointerSize)); | |
| 1697 __ sub(r4, r4, Operand(r9, LSL, 1)); | |
| 1698 __ jmp(&arguments_test); | 1698 __ jmp(&arguments_test); |
| 1699 | 1699 |
| 1700 __ bind(&arguments_loop); | 1700 __ bind(&arguments_loop); |
| 1701 __ sub(r4, r4, Operand(kPointerSize)); | 1701 __ sub(r3, r3, Operand(kPointerSize)); |
| 1702 __ ldr(r6, MemOperand(r4, 0)); | 1702 __ ldr(r4, MemOperand(r3, 0)); |
| 1703 __ add(r5, r3, Operand(r9, LSL, 1)); | 1703 __ add(r9, r1, Operand(r6, LSL, 1)); |
| 1704 __ str(r6, FieldMemOperand(r5, FixedArray::kHeaderSize)); | 1704 __ str(r4, FieldMemOperand(r9, FixedArray::kHeaderSize)); |
| 1705 __ add(r9, r9, Operand(Smi::FromInt(1))); | 1705 __ add(r6, r6, Operand(Smi::FromInt(1))); |
| 1706 | 1706 |
| 1707 __ bind(&arguments_test); | 1707 __ bind(&arguments_test); |
| 1708 __ cmp(r9, Operand(r2)); | 1708 __ cmp(r6, Operand(r5)); |
| 1709 __ b(lt, &arguments_loop); | 1709 __ b(lt, &arguments_loop); |
| 1710 | 1710 |
| 1711 // Return and remove the on-stack parameters. | 1711 // Return. |
| 1712 __ add(sp, sp, Operand(3 * kPointerSize)); | |
| 1713 __ Ret(); | 1712 __ Ret(); |
| 1714 | 1713 |
| 1715 // Do the runtime call to allocate the arguments object. | 1714 // Do the runtime call to allocate the arguments object. |
| 1716 // r0 = address of new object (tagged) | 1715 // r0 = address of new object (tagged) |
| 1717 // r2 = argument count (tagged) | 1716 // r5 = argument count (tagged) |
| 1718 __ bind(&runtime); | 1717 __ bind(&runtime); |
| 1719 __ str(r2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count. | 1718 __ Push(r1, r3, r5); |
| 1720 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); | 1719 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); |
| 1721 } | 1720 } |
| 1722 | 1721 |
| 1723 | 1722 |
| 1724 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { | 1723 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { |
| 1725 // Return address is in lr. | 1724 // Return address is in lr. |
| 1726 Label slow; | 1725 Label slow; |
| 1727 | 1726 |
| 1728 Register receiver = LoadDescriptor::ReceiverRegister(); | 1727 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 1729 Register key = LoadDescriptor::NameRegister(); | 1728 Register key = LoadDescriptor::NameRegister(); |
| 1730 | 1729 |
| 1731 // Check that the key is an array index, that is Uint32. | 1730 // Check that the key is an array index, that is Uint32. |
| 1732 __ NonNegativeSmiTst(key); | 1731 __ NonNegativeSmiTst(key); |
| 1733 __ b(ne, &slow); | 1732 __ b(ne, &slow); |
| 1734 | 1733 |
| 1735 // Everything is fine, call runtime. | 1734 // Everything is fine, call runtime. |
| 1736 __ Push(receiver, key); // Receiver, key. | 1735 __ Push(receiver, key); // Receiver, key. |
| 1737 | 1736 |
| 1738 // Perform tail call to the entry. | 1737 // Perform tail call to the entry. |
| 1739 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor, 2, 1); | 1738 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor, 2, 1); |
| 1740 | 1739 |
| 1741 __ bind(&slow); | 1740 __ bind(&slow); |
| 1742 PropertyAccessCompiler::TailCallBuiltin( | 1741 PropertyAccessCompiler::TailCallBuiltin( |
| 1743 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 1742 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
| 1744 } | 1743 } |
| 1745 | 1744 |
| 1746 | 1745 |
| 1747 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | 1746 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { |
| 1748 // sp[0] : number of parameters | 1747 // r1 : function |
| 1749 // sp[4] : receiver displacement | 1748 // r2 : number of parameters (tagged) |
| 1750 // sp[8] : function | 1749 // r3 : parameters pointer |
| 1750 |
| 1751 DCHECK(r1.is(ArgumentsAccessNewDescriptor::function())); |
| 1752 DCHECK(r2.is(ArgumentsAccessNewDescriptor::parameter_count())); |
| 1753 DCHECK(r3.is(ArgumentsAccessNewDescriptor::parameter_pointer())); |
| 1754 |
| 1751 // Check if the calling frame is an arguments adaptor frame. | 1755 // Check if the calling frame is an arguments adaptor frame. |
| 1752 Label adaptor_frame, try_allocate, runtime; | 1756 Label try_allocate, runtime; |
| 1753 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1757 __ ldr(r4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1754 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 1758 __ ldr(r0, MemOperand(r4, StandardFrameConstants::kContextOffset)); |
| 1755 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1759 __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1756 __ b(eq, &adaptor_frame); | 1760 __ b(ne, &try_allocate); |
| 1757 | |
| 1758 // Get the length from the frame. | |
| 1759 __ ldr(r1, MemOperand(sp, 0)); | |
| 1760 __ b(&try_allocate); | |
| 1761 | 1761 |
| 1762 // Patch the arguments.length and the parameters pointer. | 1762 // Patch the arguments.length and the parameters pointer. |
| 1763 __ bind(&adaptor_frame); | 1763 __ ldr(r2, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 1764 __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1764 __ add(r4, r4, Operand::PointerOffsetFromSmiKey(r2)); |
| 1765 __ str(r1, MemOperand(sp, 0)); | 1765 __ add(r3, r4, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 1766 __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1)); | |
| 1767 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); | |
| 1768 __ str(r3, MemOperand(sp, 1 * kPointerSize)); | |
| 1769 | 1766 |
| 1770 // Try the new space allocation. Start out with computing the size | 1767 // Try the new space allocation. Start out with computing the size |
| 1771 // of the arguments object and the elements array in words. | 1768 // of the arguments object and the elements array in words. |
| 1772 Label add_arguments_object; | 1769 Label add_arguments_object; |
| 1773 __ bind(&try_allocate); | 1770 __ bind(&try_allocate); |
| 1774 __ SmiUntag(r1, SetCC); | 1771 __ SmiUntag(r9, r2, SetCC); |
| 1775 __ b(eq, &add_arguments_object); | 1772 __ b(eq, &add_arguments_object); |
| 1776 __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize)); | 1773 __ add(r9, r9, Operand(FixedArray::kHeaderSize / kPointerSize)); |
| 1777 __ bind(&add_arguments_object); | 1774 __ bind(&add_arguments_object); |
| 1778 __ add(r1, r1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); | 1775 __ add(r9, r9, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); |
| 1779 | 1776 |
| 1780 // Do the allocation of both objects in one go. | 1777 // Do the allocation of both objects in one go. |
| 1781 __ Allocate(r1, r0, r2, r3, &runtime, | 1778 __ Allocate(r9, r0, r4, r5, &runtime, |
| 1782 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); | 1779 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); |
| 1783 | 1780 |
| 1784 // Get the arguments boilerplate from the current native context. | 1781 // Get the arguments boilerplate from the current native context. |
| 1785 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1782 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 1786 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); | 1783 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); |
| 1787 __ ldr(r4, MemOperand( | 1784 __ ldr(r4, MemOperand( |
| 1788 r4, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX))); | 1785 r4, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX))); |
| 1789 | 1786 |
| 1790 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); | 1787 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); |
| 1791 __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); | 1788 __ LoadRoot(r5, Heap::kEmptyFixedArrayRootIndex); |
| 1792 __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | 1789 __ str(r5, FieldMemOperand(r0, JSObject::kPropertiesOffset)); |
| 1793 __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); | 1790 __ str(r5, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 1794 | 1791 |
| 1795 // Get the length (smi tagged) and set that as an in-object property too. | 1792 // Get the length (smi tagged) and set that as an in-object property too. |
| 1796 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 1793 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 1797 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); | 1794 __ AssertSmi(r2); |
| 1798 __ AssertSmi(r1); | 1795 __ str(r2, |
| 1799 __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize + | 1796 FieldMemOperand(r0, JSObject::kHeaderSize + |
| 1800 Heap::kArgumentsLengthIndex * kPointerSize)); | 1797 Heap::kArgumentsLengthIndex * kPointerSize)); |
| 1801 | 1798 |
| 1802 // If there are no actual arguments, we're done. | 1799 // If there are no actual arguments, we're done. |
| 1803 Label done; | 1800 Label done; |
| 1804 __ cmp(r1, Operand::Zero()); | 1801 __ cmp(r2, Operand::Zero()); |
| 1805 __ b(eq, &done); | 1802 __ b(eq, &done); |
| 1806 | 1803 |
| 1807 // Get the parameters pointer from the stack. | |
| 1808 __ ldr(r2, MemOperand(sp, 1 * kPointerSize)); | |
| 1809 | |
| 1810 // Set up the elements pointer in the allocated arguments object and | 1804 // Set up the elements pointer in the allocated arguments object and |
| 1811 // initialize the header in the elements fixed array. | 1805 // initialize the header in the elements fixed array. |
| 1812 __ add(r4, r0, Operand(Heap::kStrictArgumentsObjectSize)); | 1806 __ add(r4, r0, Operand(Heap::kStrictArgumentsObjectSize)); |
| 1813 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); | 1807 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 1814 __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex); | 1808 __ LoadRoot(r5, Heap::kFixedArrayMapRootIndex); |
| 1815 __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset)); | 1809 __ str(r5, FieldMemOperand(r4, FixedArray::kMapOffset)); |
| 1816 __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset)); | 1810 __ str(r2, FieldMemOperand(r4, FixedArray::kLengthOffset)); |
| 1817 __ SmiUntag(r1); | 1811 __ SmiUntag(r2); |
| 1818 | 1812 |
| 1819 // Copy the fixed array slots. | 1813 // Copy the fixed array slots. |
| 1820 Label loop; | 1814 Label loop; |
| 1821 // Set up r4 to point to the first array slot. | 1815 // Set up r4 to point to the first array slot. |
| 1822 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1816 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 1823 __ bind(&loop); | 1817 __ bind(&loop); |
| 1824 // Pre-decrement r2 with kPointerSize on each iteration. | 1818 // Pre-decrement r3 with kPointerSize on each iteration. |
| 1825 // Pre-decrement in order to skip receiver. | 1819 // Pre-decrement in order to skip receiver. |
| 1826 __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex)); | 1820 __ ldr(r5, MemOperand(r3, kPointerSize, NegPreIndex)); |
| 1827 // Post-increment r4 with kPointerSize on each iteration. | 1821 // Post-increment r4 with kPointerSize on each iteration. |
| 1828 __ str(r3, MemOperand(r4, kPointerSize, PostIndex)); | 1822 __ str(r5, MemOperand(r4, kPointerSize, PostIndex)); |
| 1829 __ sub(r1, r1, Operand(1)); | 1823 __ sub(r2, r2, Operand(1)); |
| 1830 __ cmp(r1, Operand::Zero()); | 1824 __ cmp(r2, Operand::Zero()); |
| 1831 __ b(ne, &loop); | 1825 __ b(ne, &loop); |
| 1832 | 1826 |
| 1833 // Return and remove the on-stack parameters. | 1827 // Return. |
| 1834 __ bind(&done); | 1828 __ bind(&done); |
| 1835 __ add(sp, sp, Operand(3 * kPointerSize)); | |
| 1836 __ Ret(); | 1829 __ Ret(); |
| 1837 | 1830 |
| 1838 // Do the runtime call to allocate the arguments object. | 1831 // Do the runtime call to allocate the arguments object. |
| 1839 __ bind(&runtime); | 1832 __ bind(&runtime); |
| 1833 __ Push(r1, r3, r2); |
| 1840 __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); | 1834 __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); |
| 1841 } | 1835 } |
| 1842 | 1836 |
| 1843 | 1837 |
| 1844 void RegExpExecStub::Generate(MacroAssembler* masm) { | 1838 void RegExpExecStub::Generate(MacroAssembler* masm) { |
| 1845 // Just jump directly to runtime if native RegExp is not selected at compile | 1839 // Just jump directly to runtime if native RegExp is not selected at compile |
| 1846 // time or if regexp entry in generated code is turned off runtime switch or | 1840 // time or if regexp entry in generated code is turned off runtime switch or |
| 1847 // at compilation. | 1841 // at compilation. |
| 1848 #ifdef V8_INTERPRETED_REGEXP | 1842 #ifdef V8_INTERPRETED_REGEXP |
| 1849 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 1843 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| (...skipping 3698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5548 MemOperand(fp, 6 * kPointerSize), NULL); | 5542 MemOperand(fp, 6 * kPointerSize), NULL); |
| 5549 } | 5543 } |
| 5550 | 5544 |
| 5551 | 5545 |
| 5552 #undef __ | 5546 #undef __ |
| 5553 | 5547 |
| 5554 } // namespace internal | 5548 } // namespace internal |
| 5555 } // namespace v8 | 5549 } // namespace v8 |
| 5556 | 5550 |
| 5557 #endif // V8_TARGET_ARCH_ARM | 5551 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |