| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 // Probe the string dictionary in the |elements| register. Jump to the | 108 // Probe the string dictionary in the |elements| register. Jump to the |
| 109 // |done| label if a property with the given name is found. Jump to | 109 // |done| label if a property with the given name is found. Jump to |
| 110 // the |miss| label otherwise. | 110 // the |miss| label otherwise. |
| 111 static void GenerateStringDictionaryProbes(MacroAssembler* masm, | 111 static void GenerateStringDictionaryProbes(MacroAssembler* masm, |
| 112 Label* miss, | 112 Label* miss, |
| 113 Label* done, | 113 Label* done, |
| 114 Register elements, | 114 Register elements, |
| 115 Register name, | 115 Register name, |
| 116 Register scratch1, | 116 Register scratch1, |
| 117 Register scratch2) { | 117 Register scratch2) { |
| 118 // Assert that name contains a string. |
| 119 if (FLAG_debug_code) __ AbortIfNotString(name); |
| 120 |
| 118 // Compute the capacity mask. | 121 // Compute the capacity mask. |
| 119 const int kCapacityOffset = StringDictionary::kHeaderSize + | 122 const int kCapacityOffset = StringDictionary::kHeaderSize + |
| 120 StringDictionary::kCapacityIndex * kPointerSize; | 123 StringDictionary::kCapacityIndex * kPointerSize; |
| 121 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); | 124 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); |
| 122 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int | 125 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int |
| 123 __ sub(scratch1, scratch1, Operand(1)); | 126 __ sub(scratch1, scratch1, Operand(1)); |
| 124 | 127 |
| 125 const int kElementsStartOffset = StringDictionary::kHeaderSize + | 128 const int kElementsStartOffset = StringDictionary::kHeaderSize + |
| 126 StringDictionary::kElementsStartIndex * kPointerSize; | 129 StringDictionary::kElementsStartIndex * kPointerSize; |
| 127 | 130 |
| (...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 __ jmp(&index_smi); | 841 __ jmp(&index_smi); |
| 839 } | 842 } |
| 840 | 843 |
| 841 | 844 |
| 842 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 845 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
| 843 // ----------- S t a t e ------------- | 846 // ----------- S t a t e ------------- |
| 844 // -- r2 : name | 847 // -- r2 : name |
| 845 // -- lr : return address | 848 // -- lr : return address |
| 846 // ----------------------------------- | 849 // ----------------------------------- |
| 847 | 850 |
| 851 // Check if the name is a string. |
| 852 Label miss; |
| 853 __ tst(r2, Operand(kSmiTagMask)); |
| 854 __ b(eq, &miss); |
| 855 __ IsObjectJSStringType(r2, r0, &miss); |
| 856 |
| 848 GenerateCallNormal(masm, argc); | 857 GenerateCallNormal(masm, argc); |
| 858 __ bind(&miss); |
| 849 GenerateMiss(masm, argc); | 859 GenerateMiss(masm, argc); |
| 850 } | 860 } |
| 851 | 861 |
| 852 | 862 |
| 853 // Defined in ic.cc. | 863 // Defined in ic.cc. |
| 854 Object* LoadIC_Miss(Arguments args); | 864 Object* LoadIC_Miss(Arguments args); |
| 855 | 865 |
| 856 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 866 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 857 // ----------- S t a t e ------------- | 867 // ----------- S t a t e ------------- |
| 858 // -- r2 : name | 868 // -- r2 : name |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1386 // ----------------------------------- | 1396 // ----------------------------------- |
| 1387 | 1397 |
| 1388 // Push receiver, key and value for runtime call. | 1398 // Push receiver, key and value for runtime call. |
| 1389 __ Push(r2, r1, r0); | 1399 __ Push(r2, r1, r0); |
| 1390 | 1400 |
| 1391 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1401 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
| 1392 __ TailCallExternalReference(ref, 3, 1); | 1402 __ TailCallExternalReference(ref, 3, 1); |
| 1393 } | 1403 } |
| 1394 | 1404 |
| 1395 | 1405 |
| 1396 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | 1406 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
| 1407 StrictModeFlag strict_mode) { |
| 1397 // ---------- S t a t e -------------- | 1408 // ---------- S t a t e -------------- |
| 1398 // -- r0 : value | 1409 // -- r0 : value |
| 1399 // -- r1 : key | 1410 // -- r1 : key |
| 1400 // -- r2 : receiver | 1411 // -- r2 : receiver |
| 1401 // -- lr : return address | 1412 // -- lr : return address |
| 1402 // ----------------------------------- | 1413 // ----------------------------------- |
| 1403 | 1414 |
| 1404 // Push receiver, key and value for runtime call. | 1415 // Push receiver, key and value for runtime call. |
| 1405 __ Push(r2, r1, r0); | 1416 __ Push(r2, r1, r0); |
| 1406 | 1417 |
| 1407 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1418 __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes |
| 1419 __ mov(r0, Operand(Smi::FromInt(strict_mode))); // Strict mode. |
| 1420 __ Push(r1, r0); |
| 1421 |
| 1422 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
| 1408 } | 1423 } |
| 1409 | 1424 |
| 1410 | 1425 |
| 1411 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 1426 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
| 1427 StrictModeFlag strict_mode) { |
| 1412 // ---------- S t a t e -------------- | 1428 // ---------- S t a t e -------------- |
| 1413 // -- r0 : value | 1429 // -- r0 : value |
| 1414 // -- r1 : key | 1430 // -- r1 : key |
| 1415 // -- r2 : receiver | 1431 // -- r2 : receiver |
| 1416 // -- lr : return address | 1432 // -- lr : return address |
| 1417 // ----------------------------------- | 1433 // ----------------------------------- |
| 1418 Label slow, fast, array, extra, check_pixel_array; | 1434 Label slow, fast, array, extra, check_pixel_array; |
| 1419 | 1435 |
| 1420 // Register usage. | 1436 // Register usage. |
| 1421 Register value = r0; | 1437 Register value = r0; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1456 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1472 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1457 __ cmp(key, Operand(ip)); | 1473 __ cmp(key, Operand(ip)); |
| 1458 __ b(lo, &fast); | 1474 __ b(lo, &fast); |
| 1459 | 1475 |
| 1460 // Slow case, handle jump to runtime. | 1476 // Slow case, handle jump to runtime. |
| 1461 __ bind(&slow); | 1477 __ bind(&slow); |
| 1462 // Entry registers are intact. | 1478 // Entry registers are intact. |
| 1463 // r0: value. | 1479 // r0: value. |
| 1464 // r1: key. | 1480 // r1: key. |
| 1465 // r2: receiver. | 1481 // r2: receiver. |
| 1466 GenerateRuntimeSetProperty(masm); | 1482 GenerateRuntimeSetProperty(masm, strict_mode); |
| 1467 | 1483 |
| 1468 // Check whether the elements is a pixel array. | 1484 // Check whether the elements is a pixel array. |
| 1469 // r4: elements map. | 1485 // r4: elements map. |
| 1470 __ bind(&check_pixel_array); | 1486 __ bind(&check_pixel_array); |
| 1471 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); | 1487 GenerateFastPixelArrayStore(masm, |
| 1472 __ cmp(r4, ip); | 1488 r2, |
| 1473 __ b(ne, &slow); | 1489 r1, |
| 1474 // Check that the value is a smi. If a conversion is needed call into the | 1490 r0, |
| 1475 // runtime to convert and clamp. | 1491 elements, |
| 1476 __ JumpIfNotSmi(value, &slow); | 1492 r4, |
| 1477 __ mov(r4, Operand(key, ASR, kSmiTagSize)); // Untag the key. | 1493 r5, |
| 1478 __ ldr(ip, FieldMemOperand(elements, PixelArray::kLengthOffset)); | 1494 r6, |
| 1479 __ cmp(r4, Operand(ip)); | 1495 false, |
| 1480 __ b(hs, &slow); | 1496 false, |
| 1481 __ mov(r5, Operand(value, ASR, kSmiTagSize)); // Untag the value. | 1497 NULL, |
| 1482 __ Usat(r5, 8, Operand(r5)); // Clamp the value to [0..255]. | 1498 &slow, |
| 1483 | 1499 &slow, |
| 1484 // Get the pointer to the external array. This clobbers elements. | 1500 &slow); |
| 1485 __ ldr(elements, | |
| 1486 FieldMemOperand(elements, PixelArray::kExternalPointerOffset)); | |
| 1487 __ strb(r5, MemOperand(elements, r4)); // Elements is now external array. | |
| 1488 __ Ret(); | |
| 1489 | 1501 |
| 1490 // Extra capacity case: Check if there is extra capacity to | 1502 // Extra capacity case: Check if there is extra capacity to |
| 1491 // perform the store and update the length. Used for adding one | 1503 // perform the store and update the length. Used for adding one |
| 1492 // element to the array by writing to array[array.length]. | 1504 // element to the array by writing to array[array.length]. |
| 1493 __ bind(&extra); | 1505 __ bind(&extra); |
| 1494 // Condition code from comparing key and array length is still available. | 1506 // Condition code from comparing key and array length is still available. |
| 1495 __ b(ne, &slow); // Only support writing to writing to array[array.length]. | 1507 __ b(ne, &slow); // Only support writing to writing to array[array.length]. |
| 1496 // Check for room in the elements backing store. | 1508 // Check for room in the elements backing store. |
| 1497 // Both the key and the length of FixedArray are smis. | 1509 // Both the key and the length of FixedArray are smis. |
| 1498 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1510 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1529 __ tst(value, Operand(kSmiTagMask)); | 1541 __ tst(value, Operand(kSmiTagMask)); |
| 1530 __ Ret(eq); | 1542 __ Ret(eq); |
| 1531 // Update write barrier for the elements array address. | 1543 // Update write barrier for the elements array address. |
| 1532 __ sub(r4, r5, Operand(elements)); | 1544 __ sub(r4, r5, Operand(elements)); |
| 1533 __ RecordWrite(elements, Operand(r4), r5, r6); | 1545 __ RecordWrite(elements, Operand(r4), r5, r6); |
| 1534 | 1546 |
| 1535 __ Ret(); | 1547 __ Ret(); |
| 1536 } | 1548 } |
| 1537 | 1549 |
| 1538 | 1550 |
| 1539 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1551 void StoreIC::GenerateMegamorphic(MacroAssembler* masm, |
| 1552 StrictModeFlag strict_mode) { |
| 1540 // ----------- S t a t e ------------- | 1553 // ----------- S t a t e ------------- |
| 1541 // -- r0 : value | 1554 // -- r0 : value |
| 1542 // -- r1 : receiver | 1555 // -- r1 : receiver |
| 1543 // -- r2 : name | 1556 // -- r2 : name |
| 1544 // -- lr : return address | 1557 // -- lr : return address |
| 1545 // ----------------------------------- | 1558 // ----------------------------------- |
| 1546 | 1559 |
| 1547 // Get the receiver from the stack and probe the stub cache. | 1560 // Get the receiver from the stack and probe the stub cache. |
| 1548 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, | 1561 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, |
| 1549 NOT_IN_LOOP, | 1562 NOT_IN_LOOP, |
| 1550 MONOMORPHIC); | 1563 MONOMORPHIC, |
| 1564 strict_mode); |
| 1551 | 1565 |
| 1552 Isolate::Current()->stub_cache()->GenerateProbe( | 1566 Isolate::Current()->stub_cache()->GenerateProbe( |
| 1553 masm, flags, r1, r2, r3, r4, r5); | 1567 masm, flags, r1, r2, r3, r4, r5); |
| 1554 | 1568 |
| 1555 // Cache miss: Jump to runtime. | 1569 // Cache miss: Jump to runtime. |
| 1556 GenerateMiss(masm); | 1570 GenerateMiss(masm); |
| 1557 } | 1571 } |
| 1558 | 1572 |
| 1559 | 1573 |
| 1560 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1574 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1636 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5); | 1650 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5); |
| 1637 __ IncrementCounter(COUNTERS->store_normal_hit(), 1, r4, r5); | 1651 __ IncrementCounter(COUNTERS->store_normal_hit(), 1, r4, r5); |
| 1638 __ Ret(); | 1652 __ Ret(); |
| 1639 | 1653 |
| 1640 __ bind(&miss); | 1654 __ bind(&miss); |
| 1641 __ IncrementCounter(COUNTERS->store_normal_miss(), 1, r4, r5); | 1655 __ IncrementCounter(COUNTERS->store_normal_miss(), 1, r4, r5); |
| 1642 GenerateMiss(masm); | 1656 GenerateMiss(masm); |
| 1643 } | 1657 } |
| 1644 | 1658 |
| 1645 | 1659 |
| 1646 void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) { | 1660 void StoreIC::GenerateGlobalProxy(MacroAssembler* masm, |
| 1661 StrictModeFlag strict_mode) { |
| 1647 // ----------- S t a t e ------------- | 1662 // ----------- S t a t e ------------- |
| 1648 // -- r0 : value | 1663 // -- r0 : value |
| 1649 // -- r1 : receiver | 1664 // -- r1 : receiver |
| 1650 // -- r2 : name | 1665 // -- r2 : name |
| 1651 // -- lr : return address | 1666 // -- lr : return address |
| 1652 // ----------------------------------- | 1667 // ----------------------------------- |
| 1653 | 1668 |
| 1654 __ Push(r1, r2, r0); | 1669 __ Push(r1, r2, r0); |
| 1655 | 1670 |
| 1671 __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes |
| 1672 __ mov(r0, Operand(Smi::FromInt(strict_mode))); |
| 1673 __ Push(r1, r0); |
| 1674 |
| 1656 // Do tail-call to runtime routine. | 1675 // Do tail-call to runtime routine. |
| 1657 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1676 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
| 1658 } | 1677 } |
| 1659 | 1678 |
| 1660 | 1679 |
| 1661 #undef __ | 1680 #undef __ |
| 1662 | 1681 |
| 1663 | 1682 |
| 1664 Condition CompareIC::ComputeCondition(Token::Value op) { | 1683 Condition CompareIC::ComputeCondition(Token::Value op) { |
| 1665 switch (op) { | 1684 switch (op) { |
| 1666 case Token::EQ_STRICT: | 1685 case Token::EQ_STRICT: |
| 1667 case Token::EQ: | 1686 case Token::EQ: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1698 set_target(*rewritten); | 1717 set_target(*rewritten); |
| 1699 | 1718 |
| 1700 #ifdef DEBUG | 1719 #ifdef DEBUG |
| 1701 if (FLAG_trace_ic) { | 1720 if (FLAG_trace_ic) { |
| 1702 PrintF("[CompareIC (%s->%s)#%s]\n", | 1721 PrintF("[CompareIC (%s->%s)#%s]\n", |
| 1703 GetStateName(previous_state), | 1722 GetStateName(previous_state), |
| 1704 GetStateName(state), | 1723 GetStateName(state), |
| 1705 Token::Name(op_)); | 1724 Token::Name(op_)); |
| 1706 } | 1725 } |
| 1707 #endif | 1726 #endif |
| 1727 |
| 1728 // Activate inlined smi code. |
| 1729 if (previous_state == UNINITIALIZED) { |
| 1730 PatchInlinedSmiCode(address()); |
| 1731 } |
| 1708 } | 1732 } |
| 1709 | 1733 |
| 1710 | 1734 |
| 1711 void PatchInlinedSmiCode(Address address) { | 1735 void PatchInlinedSmiCode(Address address) { |
| 1712 // Currently there is no smi inlining in the ARM full code generator. | 1736 Address cmp_instruction_address = |
| 1737 address + Assembler::kCallTargetAddressOffset; |
| 1738 |
| 1739 // If the instruction following the call is not a cmp rx, #yyy, nothing |
| 1740 // was inlined. |
| 1741 Instr instr = Assembler::instr_at(cmp_instruction_address); |
| 1742 if (!Assembler::IsCmpImmediate(instr)) { |
| 1743 return; |
| 1744 } |
| 1745 |
| 1746 // The delta to the start of the map check instruction and the |
| 1747 // condition code uses at the patched jump. |
| 1748 int delta = Assembler::GetCmpImmediateRawImmediate(instr); |
| 1749 delta += |
| 1750 Assembler::GetCmpImmediateRegister(instr).code() * kOff12Mask; |
| 1751 // If the delta is 0 the instruction is cmp r0, #0 which also signals that |
| 1752 // nothing was inlined. |
| 1753 if (delta == 0) { |
| 1754 return; |
| 1755 } |
| 1756 |
| 1757 #ifdef DEBUG |
| 1758 if (FLAG_trace_ic) { |
| 1759 PrintF("[ patching ic at %p, cmp=%p, delta=%d\n", |
| 1760 address, cmp_instruction_address, delta); |
| 1761 } |
| 1762 #endif |
| 1763 |
| 1764 Address patch_address = |
| 1765 cmp_instruction_address - delta * Instruction::kInstrSize; |
| 1766 Instr instr_at_patch = Assembler::instr_at(patch_address); |
| 1767 Instr branch_instr = |
| 1768 Assembler::instr_at(patch_address + Instruction::kInstrSize); |
| 1769 ASSERT(Assembler::IsCmpRegister(instr_at_patch)); |
| 1770 ASSERT_EQ(Assembler::GetRn(instr_at_patch).code(), |
| 1771 Assembler::GetRm(instr_at_patch).code()); |
| 1772 ASSERT(Assembler::IsBranch(branch_instr)); |
| 1773 if (Assembler::GetCondition(branch_instr) == eq) { |
| 1774 // This is patching a "jump if not smi" site to be active. |
| 1775 // Changing |
| 1776 // cmp rx, rx |
| 1777 // b eq, <target> |
| 1778 // to |
| 1779 // tst rx, #kSmiTagMask |
| 1780 // b ne, <target> |
| 1781 CodePatcher patcher(patch_address, 2); |
| 1782 Register reg = Assembler::GetRn(instr_at_patch); |
| 1783 patcher.masm()->tst(reg, Operand(kSmiTagMask)); |
| 1784 patcher.EmitCondition(ne); |
| 1785 } else { |
| 1786 ASSERT(Assembler::GetCondition(branch_instr) == ne); |
| 1787 // This is patching a "jump if smi" site to be active. |
| 1788 // Changing |
| 1789 // cmp rx, rx |
| 1790 // b ne, <target> |
| 1791 // to |
| 1792 // tst rx, #kSmiTagMask |
| 1793 // b eq, <target> |
| 1794 CodePatcher patcher(patch_address, 2); |
| 1795 Register reg = Assembler::GetRn(instr_at_patch); |
| 1796 patcher.masm()->tst(reg, Operand(kSmiTagMask)); |
| 1797 patcher.EmitCondition(eq); |
| 1798 } |
| 1713 } | 1799 } |
| 1714 | 1800 |
| 1715 | 1801 |
| 1716 } } // namespace v8::internal | 1802 } } // namespace v8::internal |
| 1717 | 1803 |
| 1718 #endif // V8_TARGET_ARCH_ARM | 1804 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |