| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) { | 851 void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) { |
| 852 if (dst.code() < 16) { | 852 if (dst.code() < 16) { |
| 853 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); | 853 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); |
| 854 vmov(loc.low(), src); | 854 vmov(loc.low(), src); |
| 855 } else { | 855 } else { |
| 856 vmov(dst, VmovIndexLo, src); | 856 vmov(dst, VmovIndexLo, src); |
| 857 } | 857 } |
| 858 } | 858 } |
| 859 | 859 |
| 860 | 860 |
| 861 void MacroAssembler::LoadNumber(Register object, | |
| 862 LowDwVfpRegister dst, | |
| 863 Register heap_number_map, | |
| 864 Register scratch, | |
| 865 Label* not_number) { | |
| 866 Label is_smi, done; | |
| 867 | |
| 868 UntagAndJumpIfSmi(scratch, object, &is_smi); | |
| 869 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); | |
| 870 | |
| 871 vldr(dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | |
| 872 b(&done); | |
| 873 | |
| 874 // Handle loading a double from a smi. | |
| 875 bind(&is_smi); | |
| 876 vmov(dst.high(), scratch); | |
| 877 vcvt_f64_s32(dst, dst.high()); | |
| 878 | |
| 879 bind(&done); | |
| 880 } | |
| 881 | |
| 882 | |
| 883 void MacroAssembler::LoadNumberAsInt32Double(Register object, | |
| 884 DwVfpRegister double_dst, | |
| 885 Register heap_number_map, | |
| 886 Register scratch, | |
| 887 LowDwVfpRegister double_scratch, | |
| 888 Label* not_int32) { | |
| 889 ASSERT(!scratch.is(object)); | |
| 890 ASSERT(!heap_number_map.is(object) && !heap_number_map.is(scratch)); | |
| 891 | |
| 892 Label done, obj_is_not_smi; | |
| 893 | |
| 894 UntagAndJumpIfNotSmi(scratch, object, &obj_is_not_smi); | |
| 895 vmov(double_scratch.low(), scratch); | |
| 896 vcvt_f64_s32(double_dst, double_scratch.low()); | |
| 897 b(&done); | |
| 898 | |
| 899 bind(&obj_is_not_smi); | |
| 900 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_int32); | |
| 901 | |
| 902 // Load the number. | |
| 903 // Load the double value. | |
| 904 vldr(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | |
| 905 | |
| 906 TestDoubleIsInt32(double_dst, double_scratch); | |
| 907 // Jump to not_int32 if the operation did not succeed. | |
| 908 b(ne, not_int32); | |
| 909 | |
| 910 bind(&done); | |
| 911 } | |
| 912 | |
| 913 | |
| 914 void MacroAssembler::LoadNumberAsInt32(Register object, | |
| 915 Register dst, | |
| 916 Register heap_number_map, | |
| 917 Register scratch, | |
| 918 DwVfpRegister double_scratch0, | |
| 919 LowDwVfpRegister double_scratch1, | |
| 920 Label* not_int32) { | |
| 921 ASSERT(!dst.is(object)); | |
| 922 ASSERT(!scratch.is(object)); | |
| 923 | |
| 924 Label done, maybe_undefined; | |
| 925 | |
| 926 UntagAndJumpIfSmi(dst, object, &done); | |
| 927 | |
| 928 JumpIfNotHeapNumber(object, heap_number_map, scratch, &maybe_undefined); | |
| 929 | |
| 930 // Object is a heap number. | |
| 931 // Convert the floating point value to a 32-bit integer. | |
| 932 // Load the double value. | |
| 933 vldr(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); | |
| 934 | |
| 935 TryDoubleToInt32Exact(dst, double_scratch0, double_scratch1); | |
| 936 // Jump to not_int32 if the operation did not succeed. | |
| 937 b(ne, not_int32); | |
| 938 b(&done); | |
| 939 | |
| 940 bind(&maybe_undefined); | |
| 941 CompareRoot(object, Heap::kUndefinedValueRootIndex); | |
| 942 b(ne, not_int32); | |
| 943 // |undefined| is truncated to 0. | |
| 944 mov(dst, Operand(Smi::FromInt(0))); | |
| 945 // Fall through. | |
| 946 | |
| 947 bind(&done); | |
| 948 } | |
| 949 | |
| 950 | |
| 951 void MacroAssembler::Prologue(PrologueFrameMode frame_mode) { | 861 void MacroAssembler::Prologue(PrologueFrameMode frame_mode) { |
| 952 if (frame_mode == BUILD_STUB_FRAME) { | 862 if (frame_mode == BUILD_STUB_FRAME) { |
| 953 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 863 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
| 954 Push(Smi::FromInt(StackFrame::STUB)); | 864 Push(Smi::FromInt(StackFrame::STUB)); |
| 955 // Adjust FP to point to saved FP. | 865 // Adjust FP to point to saved FP. |
| 956 add(fp, sp, Operand(2 * kPointerSize)); | 866 add(fp, sp, Operand(2 * kPointerSize)); |
| 957 } else { | 867 } else { |
| 958 PredictableCodeSizeScope predictible_code_size_scope( | 868 PredictableCodeSizeScope predictible_code_size_scope( |
| 959 this, kNoCodeAgeSequenceLength * Assembler::kInstrSize); | 869 this, kNoCodeAgeSequenceLength * Assembler::kInstrSize); |
| 960 // The following three instructions must remain together and unmodified | 870 // The following three instructions must remain together and unmodified |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1583 | 1493 |
| 1584 ldr(scratch, FieldMemOperand(scratch, token_offset)); | 1494 ldr(scratch, FieldMemOperand(scratch, token_offset)); |
| 1585 ldr(ip, FieldMemOperand(ip, token_offset)); | 1495 ldr(ip, FieldMemOperand(ip, token_offset)); |
| 1586 cmp(scratch, Operand(ip)); | 1496 cmp(scratch, Operand(ip)); |
| 1587 b(ne, miss); | 1497 b(ne, miss); |
| 1588 | 1498 |
| 1589 bind(&same_contexts); | 1499 bind(&same_contexts); |
| 1590 } | 1500 } |
| 1591 | 1501 |
| 1592 | 1502 |
| 1503 // Compute the hash code from the untagged key. This must be kept in sync with |
| 1504 // ComputeIntegerHash in utils.h and KeyedLoadGenericElementStub in |
| 1505 // code-stub-hydrogen.cc |
| 1593 void MacroAssembler::GetNumberHash(Register t0, Register scratch) { | 1506 void MacroAssembler::GetNumberHash(Register t0, Register scratch) { |
| 1594 // First of all we assign the hash seed to scratch. | 1507 // First of all we assign the hash seed to scratch. |
| 1595 LoadRoot(scratch, Heap::kHashSeedRootIndex); | 1508 LoadRoot(scratch, Heap::kHashSeedRootIndex); |
| 1596 SmiUntag(scratch); | 1509 SmiUntag(scratch); |
| 1597 | 1510 |
| 1598 // Xor original key with a seed. | 1511 // Xor original key with a seed. |
| 1599 eor(t0, t0, Operand(scratch)); | 1512 eor(t0, t0, Operand(scratch)); |
| 1600 | 1513 |
| 1601 // Compute the hash code from the untagged key. This must be kept in sync | 1514 // Compute the hash code from the untagged key. This must be kept in sync |
| 1602 // with ComputeIntegerHash in utils.h. | 1515 // with ComputeIntegerHash in utils.h. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1649 Label done; | 1562 Label done; |
| 1650 | 1563 |
| 1651 GetNumberHash(t0, t1); | 1564 GetNumberHash(t0, t1); |
| 1652 | 1565 |
| 1653 // Compute the capacity mask. | 1566 // Compute the capacity mask. |
| 1654 ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); | 1567 ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); |
| 1655 SmiUntag(t1); | 1568 SmiUntag(t1); |
| 1656 sub(t1, t1, Operand(1)); | 1569 sub(t1, t1, Operand(1)); |
| 1657 | 1570 |
| 1658 // Generate an unrolled loop that performs a few probes before giving up. | 1571 // Generate an unrolled loop that performs a few probes before giving up. |
| 1659 static const int kProbes = 4; | 1572 for (int i = 0; i < kNumberDictionaryProbes; i++) { |
| 1660 for (int i = 0; i < kProbes; i++) { | |
| 1661 // Use t2 for index calculations and keep the hash intact in t0. | 1573 // Use t2 for index calculations and keep the hash intact in t0. |
| 1662 mov(t2, t0); | 1574 mov(t2, t0); |
| 1663 // Compute the masked index: (hash + i + i * i) & mask. | 1575 // Compute the masked index: (hash + i + i * i) & mask. |
| 1664 if (i > 0) { | 1576 if (i > 0) { |
| 1665 add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i))); | 1577 add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i))); |
| 1666 } | 1578 } |
| 1667 and_(t2, t2, Operand(t1)); | 1579 and_(t2, t2, Operand(t1)); |
| 1668 | 1580 |
| 1669 // Scale the index by multiplying by the element size. | 1581 // Scale the index by multiplying by the element size. |
| 1670 ASSERT(SeededNumberDictionary::kEntrySize == 3); | 1582 ASSERT(SeededNumberDictionary::kEntrySize == 3); |
| 1671 add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 | 1583 add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 |
| 1672 | 1584 |
| 1673 // Check if the key is identical to the name. | 1585 // Check if the key is identical to the name. |
| 1674 add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); | 1586 add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); |
| 1675 ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset)); | 1587 ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset)); |
| 1676 cmp(key, Operand(ip)); | 1588 cmp(key, Operand(ip)); |
| 1677 if (i != kProbes - 1) { | 1589 if (i != kNumberDictionaryProbes - 1) { |
| 1678 b(eq, &done); | 1590 b(eq, &done); |
| 1679 } else { | 1591 } else { |
| 1680 b(ne, miss); | 1592 b(ne, miss); |
| 1681 } | 1593 } |
| 1682 } | 1594 } |
| 1683 | 1595 |
| 1684 bind(&done); | 1596 bind(&done); |
| 1685 // Check that the value is a normal property. | 1597 // Check that the value is a normal property. |
| 1686 // t2: elements + (index * kPointerSize) | 1598 // t2: elements + (index * kPointerSize) |
| 1687 const int kDetailsOffset = | 1599 const int kDetailsOffset = |
| (...skipping 2362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4050 void CodePatcher::EmitCondition(Condition cond) { | 3962 void CodePatcher::EmitCondition(Condition cond) { |
| 4051 Instr instr = Assembler::instr_at(masm_.pc_); | 3963 Instr instr = Assembler::instr_at(masm_.pc_); |
| 4052 instr = (instr & ~kCondMask) | cond; | 3964 instr = (instr & ~kCondMask) | cond; |
| 4053 masm_.emit(instr); | 3965 masm_.emit(instr); |
| 4054 } | 3966 } |
| 4055 | 3967 |
| 4056 | 3968 |
| 4057 } } // namespace v8::internal | 3969 } } // namespace v8::internal |
| 4058 | 3970 |
| 4059 #endif // V8_TARGET_ARCH_ARM | 3971 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |