| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1369 } | 1369 } |
| 1370 | 1370 |
| 1371 | 1371 |
| 1372 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1372 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 1373 Register result = ToRegister(instr->result()); | 1373 Register result = ToRegister(instr->result()); |
| 1374 Register array = ToRegister(instr->InputAt(0)); | 1374 Register array = ToRegister(instr->InputAt(0)); |
| 1375 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); | 1375 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); |
| 1376 } | 1376 } |
| 1377 | 1377 |
| 1378 | 1378 |
| 1379 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) { | 1379 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { |
| 1380 Register result = ToRegister(instr->result()); | 1380 Register result = ToRegister(instr->result()); |
| 1381 Register array = ToRegister(instr->InputAt(0)); | 1381 Register array = ToRegister(instr->InputAt(0)); |
| 1382 __ ldr(result, FieldMemOperand(array, ExternalArray::kLengthOffset)); | 1382 __ ldr(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset)); |
| 1383 } | |
| 1384 | |
| 1385 | |
| 1386 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | |
| 1387 Register result = ToRegister(instr->result()); | |
| 1388 Register array = ToRegister(instr->InputAt(0)); | |
| 1389 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); | |
| 1390 } | 1383 } |
| 1391 | 1384 |
| 1392 | 1385 |
| 1393 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1386 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
| 1394 Register result = ToRegister(instr->result()); | 1387 Register result = ToRegister(instr->result()); |
| 1395 Register input = ToRegister(instr->InputAt(0)); | 1388 Register input = ToRegister(instr->InputAt(0)); |
| 1396 | 1389 |
| 1397 // Load map into |result|. | 1390 // Load map into |result|. |
| 1398 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); | 1391 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 1399 // Load the map's "bit field 2" into |result|. We only need the first byte, | 1392 // Load the map's "bit field 2" into |result|. We only need the first byte, |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1574 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1567 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1575 | 1568 |
| 1576 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 1569 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
| 1577 // Avoid deopts in the case where we've never executed this path before. | 1570 // Avoid deopts in the case where we've never executed this path before. |
| 1578 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 1571 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
| 1579 | 1572 |
| 1580 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 1573 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
| 1581 // undefined -> false. | 1574 // undefined -> false. |
| 1582 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 1575 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
| 1583 __ b(eq, false_label); | 1576 __ b(eq, false_label); |
| 1584 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1585 // We've seen undefined for the first time -> deopt. | |
| 1586 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | |
| 1587 DeoptimizeIf(eq, instr->environment()); | |
| 1588 } | 1577 } |
| 1589 | |
| 1590 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 1578 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
| 1591 // Boolean -> its value. | 1579 // Boolean -> its value. |
| 1592 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1580 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
| 1593 __ b(eq, true_label); | 1581 __ b(eq, true_label); |
| 1594 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 1582 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
| 1595 __ b(eq, false_label); | 1583 __ b(eq, false_label); |
| 1596 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1597 // We've seen a boolean for the first time -> deopt. | |
| 1598 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | |
| 1599 DeoptimizeIf(eq, instr->environment()); | |
| 1600 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | |
| 1601 DeoptimizeIf(eq, instr->environment()); | |
| 1602 } | 1584 } |
| 1603 | |
| 1604 #if 0 | |
| 1605 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | |
| 1606 // false -> false. | |
| 1607 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | |
| 1608 __ b(eq, false_label); | |
| 1609 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1610 // We've seen a boolean for the first time -> deopt. | |
| 1611 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | |
| 1612 DeoptimizeIf(eq, instr->environment()); | |
| 1613 } | |
| 1614 #endif | |
| 1615 | |
| 1616 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 1585 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
| 1617 // 'null' -> false. | 1586 // 'null' -> false. |
| 1618 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 1587 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
| 1619 __ b(eq, false_label); | 1588 __ b(eq, false_label); |
| 1620 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1621 // We've seen null for the first time -> deopt. | |
| 1622 __ CompareRoot(reg, Heap::kNullValueRootIndex); | |
| 1623 DeoptimizeIf(eq, instr->environment()); | |
| 1624 } | 1589 } |
| 1625 | 1590 |
| 1626 if (expected.Contains(ToBooleanStub::SMI)) { | 1591 if (expected.Contains(ToBooleanStub::SMI)) { |
| 1627 // Smis: 0 -> false, all other -> true. | 1592 // Smis: 0 -> false, all other -> true. |
| 1628 __ cmp(reg, Operand(0)); | 1593 __ cmp(reg, Operand(0)); |
| 1629 __ b(eq, false_label); | 1594 __ b(eq, false_label); |
| 1630 __ JumpIfSmi(reg, true_label); | 1595 __ JumpIfSmi(reg, true_label); |
| 1631 } else if (expected.NeedsMap()) { | 1596 } else if (expected.NeedsMap()) { |
| 1632 // If we need a map later and have a Smi -> deopt. | 1597 // If we need a map later and have a Smi -> deopt. |
| 1633 __ tst(reg, Operand(kSmiTagMask)); | 1598 __ tst(reg, Operand(kSmiTagMask)); |
| 1634 DeoptimizeIf(eq, instr->environment()); | 1599 DeoptimizeIf(eq, instr->environment()); |
| 1635 } | 1600 } |
| 1636 | 1601 |
| 1637 const Register map = scratch0(); | 1602 const Register map = scratch0(); |
| 1638 if (expected.NeedsMap()) { | 1603 if (expected.NeedsMap()) { |
| 1639 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1604 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1640 // Everything with a map could be undetectable, so check this now. | 1605 |
| 1641 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); | 1606 if (expected.CanBeUndetectable()) { |
| 1642 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 1607 // Undetectable -> false. |
| 1643 __ b(ne, false_label); | 1608 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 1609 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 1610 __ b(ne, false_label); |
| 1611 } |
| 1644 } | 1612 } |
| 1645 | 1613 |
| 1646 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 1614 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
| 1647 // spec object -> true. | 1615 // spec object -> true. |
| 1648 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); | 1616 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); |
| 1649 __ b(ge, true_label); | 1617 __ b(ge, true_label); |
| 1650 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1651 // We've seen a spec object for the first time -> deopt. | |
| 1652 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); | |
| 1653 DeoptimizeIf(ge, instr->environment()); | |
| 1654 } | 1618 } |
| 1655 | 1619 |
| 1656 if (expected.Contains(ToBooleanStub::STRING)) { | 1620 if (expected.Contains(ToBooleanStub::STRING)) { |
| 1657 // String value -> false iff empty. | 1621 // String value -> false iff empty. |
| 1658 Label not_string; | 1622 Label not_string; |
| 1659 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | 1623 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
| 1660 __ b(ge, ¬_string); | 1624 __ b(ge, ¬_string); |
| 1661 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); | 1625 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); |
| 1662 __ cmp(ip, Operand(0)); | 1626 __ cmp(ip, Operand(0)); |
| 1663 __ b(ne, true_label); | 1627 __ b(ne, true_label); |
| 1664 __ b(false_label); | 1628 __ b(false_label); |
| 1665 __ bind(¬_string); | 1629 __ bind(¬_string); |
| 1666 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1667 // We've seen a string for the first time -> deopt | |
| 1668 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | |
| 1669 DeoptimizeIf(lt, instr->environment()); | |
| 1670 } | 1630 } |
| 1671 | 1631 |
| 1672 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 1632 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 1673 // heap number -> false iff +0, -0, or NaN. | 1633 // heap number -> false iff +0, -0, or NaN. |
| 1674 DoubleRegister dbl_scratch = double_scratch0(); | 1634 DoubleRegister dbl_scratch = double_scratch0(); |
| 1675 Label not_heap_number; | 1635 Label not_heap_number; |
| 1676 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 1636 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
| 1677 __ b(ne, ¬_heap_number); | 1637 __ b(ne, ¬_heap_number); |
| 1678 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 1638 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
| 1679 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 1639 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
| 1680 __ b(vs, false_label); // NaN -> false. | 1640 __ b(vs, false_label); // NaN -> false. |
| 1681 __ b(eq, false_label); // +0, -0 -> false. | 1641 __ b(eq, false_label); // +0, -0 -> false. |
| 1682 __ b(true_label); | 1642 __ b(true_label); |
| 1683 __ bind(¬_heap_number); | 1643 __ bind(¬_heap_number); |
| 1684 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1685 // We've seen a heap number for the first time -> deopt. | |
| 1686 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | |
| 1687 DeoptimizeIf(eq, instr->environment()); | |
| 1688 } | 1644 } |
| 1689 | 1645 |
| 1690 if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | 1646 // We've seen something for the first time -> deopt. |
| 1691 // internal objects -> true | 1647 DeoptimizeIf(al, instr->environment()); |
| 1692 __ b(true_label); | |
| 1693 } else { | |
| 1694 // We've seen something for the first time -> deopt. | |
| 1695 DeoptimizeIf(al, instr->environment()); | |
| 1696 } | |
| 1697 } | 1648 } |
| 1698 } | 1649 } |
| 1699 } | 1650 } |
| 1700 | 1651 |
| 1701 | 1652 |
| 1702 void LCodeGen::EmitGoto(int block) { | 1653 void LCodeGen::EmitGoto(int block) { |
| 1703 block = chunk_->LookupDestination(block); | 1654 block = chunk_->LookupDestination(block); |
| 1704 int next_block = GetNextEmittedBlock(current_block_); | 1655 int next_block = GetNextEmittedBlock(current_block_); |
| 1705 if (block != next_block) { | 1656 if (block != next_block) { |
| 1706 __ jmp(chunk_->GetAssemblyLabel(block)); | 1657 __ jmp(chunk_->GetAssemblyLabel(block)); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1844 __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1795 __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 1845 __ b(lt, is_not_object); | 1796 __ b(lt, is_not_object); |
| 1846 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1797 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 1847 return le; | 1798 return le; |
| 1848 } | 1799 } |
| 1849 | 1800 |
| 1850 | 1801 |
| 1851 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1802 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 1852 Register reg = ToRegister(instr->InputAt(0)); | 1803 Register reg = ToRegister(instr->InputAt(0)); |
| 1853 Register temp1 = ToRegister(instr->TempAt(0)); | 1804 Register temp1 = ToRegister(instr->TempAt(0)); |
| 1854 Register temp2 = scratch0(); | |
| 1855 | 1805 |
| 1856 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1806 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1857 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1807 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1858 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1808 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1859 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1809 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1860 | 1810 |
| 1861 Condition true_cond = | 1811 Condition true_cond = |
| 1862 EmitIsObject(reg, temp1, false_label, true_label); | 1812 EmitIsObject(reg, temp1, false_label, true_label); |
| 1863 | 1813 |
| 1864 EmitBranch(true_block, false_block, true_cond); | 1814 EmitBranch(true_block, false_block, true_cond); |
| (...skipping 939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2804 | 2754 |
| 2805 void LCodeGen::DoOuterContext(LOuterContext* instr) { | 2755 void LCodeGen::DoOuterContext(LOuterContext* instr) { |
| 2806 Register context = ToRegister(instr->context()); | 2756 Register context = ToRegister(instr->context()); |
| 2807 Register result = ToRegister(instr->result()); | 2757 Register result = ToRegister(instr->result()); |
| 2808 __ ldr(result, | 2758 __ ldr(result, |
| 2809 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 2759 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 2810 } | 2760 } |
| 2811 | 2761 |
| 2812 | 2762 |
| 2813 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 2763 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| 2814 Register context = ToRegister(instr->context()); | |
| 2815 Register result = ToRegister(instr->result()); | 2764 Register result = ToRegister(instr->result()); |
| 2816 __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX)); | 2765 __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX)); |
| 2817 } | 2766 } |
| 2818 | 2767 |
| 2819 | 2768 |
| 2820 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 2769 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
| 2821 Register global = ToRegister(instr->global()); | 2770 Register global = ToRegister(instr->global()); |
| 2822 Register result = ToRegister(instr->result()); | 2771 Register result = ToRegister(instr->result()); |
| 2823 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | 2772 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); |
| 2824 } | 2773 } |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3010 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 2959 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
| 3011 DeoptimizeIf(ne, instr->environment()); | 2960 DeoptimizeIf(ne, instr->environment()); |
| 3012 __ bind(&done); | 2961 __ bind(&done); |
| 3013 } | 2962 } |
| 3014 } | 2963 } |
| 3015 | 2964 |
| 3016 | 2965 |
| 3017 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2966 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 3018 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 2967 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3019 Register result = ToRegister(instr->result()); | 2968 Register result = ToRegister(instr->result()); |
| 3020 Register scratch1 = result; | 2969 Register scratch = scratch0(); |
| 3021 Register scratch2 = scratch0(); | |
| 3022 Label done, check_sign_on_zero; | 2970 Label done, check_sign_on_zero; |
| 3023 | 2971 |
| 3024 // Extract exponent bits. | 2972 // Extract exponent bits. |
| 3025 __ vmov(scratch1, input.high()); | 2973 __ vmov(result, input.high()); |
| 3026 __ ubfx(scratch2, | 2974 __ ubfx(scratch, |
| 3027 scratch1, | 2975 result, |
| 3028 HeapNumber::kExponentShift, | 2976 HeapNumber::kExponentShift, |
| 3029 HeapNumber::kExponentBits); | 2977 HeapNumber::kExponentBits); |
| 3030 | 2978 |
| 3031 // If the number is in ]-0.5, +0.5[, the result is +/- 0. | 2979 // If the number is in ]-0.5, +0.5[, the result is +/- 0. |
| 3032 __ cmp(scratch2, Operand(HeapNumber::kExponentBias - 2)); | 2980 __ cmp(scratch, Operand(HeapNumber::kExponentBias - 2)); |
| 3033 __ mov(result, Operand(0), LeaveCC, le); | 2981 __ mov(result, Operand(0), LeaveCC, le); |
| 3034 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2982 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3035 __ b(le, &check_sign_on_zero); | 2983 __ b(le, &check_sign_on_zero); |
| 3036 } else { | 2984 } else { |
| 3037 __ b(le, &done); | 2985 __ b(le, &done); |
| 3038 } | 2986 } |
| 3039 | 2987 |
| 3040 // The following conversion will not work with numbers | 2988 // The following conversion will not work with numbers |
| 3041 // outside of ]-2^32, 2^32[. | 2989 // outside of ]-2^32, 2^32[. |
| 3042 __ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32)); | 2990 __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32)); |
| 3043 DeoptimizeIf(ge, instr->environment()); | 2991 DeoptimizeIf(ge, instr->environment()); |
| 3044 | 2992 |
| 3045 // Save the original sign for later comparison. | 2993 // Save the original sign for later comparison. |
| 3046 __ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask)); | 2994 __ and_(scratch, result, Operand(HeapNumber::kSignMask)); |
| 3047 | 2995 |
| 3048 __ Vmov(double_scratch0(), 0.5); | 2996 __ Vmov(double_scratch0(), 0.5); |
| 3049 __ vadd(input, input, double_scratch0()); | 2997 __ vadd(input, input, double_scratch0()); |
| 3050 | 2998 |
| 3051 // Check sign of the result: if the sign changed, the input | 2999 // Check sign of the result: if the sign changed, the input |
| 3052 // value was in ]0.5, 0[ and the result should be -0. | 3000 // value was in ]0.5, 0[ and the result should be -0. |
| 3053 __ vmov(scratch1, input.high()); | 3001 __ vmov(result, input.high()); |
| 3054 __ eor(scratch1, scratch1, Operand(scratch2), SetCC); | 3002 __ eor(result, result, Operand(scratch), SetCC); |
| 3055 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3003 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3056 DeoptimizeIf(mi, instr->environment()); | 3004 DeoptimizeIf(mi, instr->environment()); |
| 3057 } else { | 3005 } else { |
| 3058 __ mov(result, Operand(0), LeaveCC, mi); | 3006 __ mov(result, Operand(0), LeaveCC, mi); |
| 3059 __ b(mi, &done); | 3007 __ b(mi, &done); |
| 3060 } | 3008 } |
| 3061 | 3009 |
| 3062 __ EmitVFPTruncate(kRoundToMinusInf, | 3010 __ EmitVFPTruncate(kRoundToMinusInf, |
| 3063 double_scratch0().low(), | 3011 double_scratch0().low(), |
| 3064 input, | 3012 input, |
| 3065 scratch1, | 3013 result, |
| 3066 scratch2); | 3014 scratch); |
| 3067 DeoptimizeIf(ne, instr->environment()); | 3015 DeoptimizeIf(ne, instr->environment()); |
| 3068 __ vmov(result, double_scratch0().low()); | 3016 __ vmov(result, double_scratch0().low()); |
| 3069 | 3017 |
| 3070 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3018 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3071 // Test for -0. | 3019 // Test for -0. |
| 3072 __ cmp(result, Operand(0)); | 3020 __ cmp(result, Operand(0)); |
| 3073 __ b(ne, &done); | 3021 __ b(ne, &done); |
| 3074 __ bind(&check_sign_on_zero); | 3022 __ bind(&check_sign_on_zero); |
| 3075 __ vmov(scratch1, input.high()); | 3023 __ vmov(scratch, input.high()); |
| 3076 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 3024 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
| 3077 DeoptimizeIf(ne, instr->environment()); | 3025 DeoptimizeIf(ne, instr->environment()); |
| 3078 } | 3026 } |
| 3079 __ bind(&done); | 3027 __ bind(&done); |
| 3080 } | 3028 } |
| 3081 | 3029 |
| 3082 | 3030 |
| 3083 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3031 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 3084 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3032 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3085 DoubleRegister result = ToDoubleRegister(instr->result()); | 3033 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3086 __ vsqrt(result, input); | 3034 __ vsqrt(result, input); |
| (...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4013 instr->hydrogen()->deoptimize_on_undefined(), | 3961 instr->hydrogen()->deoptimize_on_undefined(), |
| 4014 instr->environment()); | 3962 instr->environment()); |
| 4015 } | 3963 } |
| 4016 | 3964 |
| 4017 | 3965 |
| 4018 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 3966 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 4019 Register result_reg = ToRegister(instr->result()); | 3967 Register result_reg = ToRegister(instr->result()); |
| 4020 Register scratch1 = scratch0(); | 3968 Register scratch1 = scratch0(); |
| 4021 Register scratch2 = ToRegister(instr->TempAt(0)); | 3969 Register scratch2 = ToRegister(instr->TempAt(0)); |
| 4022 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0)); | 3970 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0)); |
| 4023 DwVfpRegister double_scratch = double_scratch0(); | |
| 4024 SwVfpRegister single_scratch = double_scratch0().low(); | 3971 SwVfpRegister single_scratch = double_scratch0().low(); |
| 4025 | 3972 |
| 4026 Label done; | 3973 Label done; |
| 4027 | 3974 |
| 4028 if (instr->truncating()) { | 3975 if (instr->truncating()) { |
| 4029 Register scratch3 = ToRegister(instr->TempAt(1)); | 3976 Register scratch3 = ToRegister(instr->TempAt(1)); |
| 4030 __ EmitECMATruncate(result_reg, | 3977 __ EmitECMATruncate(result_reg, |
| 4031 double_input, | 3978 double_input, |
| 4032 single_scratch, | 3979 single_scratch, |
| 4033 scratch1, | 3980 scratch1, |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4393 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); | 4340 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); |
| 4394 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 4341 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 4395 final_branch_condition = eq; | 4342 final_branch_condition = eq; |
| 4396 | 4343 |
| 4397 } else if (type_name->Equals(heap()->boolean_symbol())) { | 4344 } else if (type_name->Equals(heap()->boolean_symbol())) { |
| 4398 __ CompareRoot(input, Heap::kTrueValueRootIndex); | 4345 __ CompareRoot(input, Heap::kTrueValueRootIndex); |
| 4399 __ b(eq, true_label); | 4346 __ b(eq, true_label); |
| 4400 __ CompareRoot(input, Heap::kFalseValueRootIndex); | 4347 __ CompareRoot(input, Heap::kFalseValueRootIndex); |
| 4401 final_branch_condition = eq; | 4348 final_branch_condition = eq; |
| 4402 | 4349 |
| 4350 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) { |
| 4351 __ CompareRoot(input, Heap::kNullValueRootIndex); |
| 4352 final_branch_condition = eq; |
| 4353 |
| 4403 } else if (type_name->Equals(heap()->undefined_symbol())) { | 4354 } else if (type_name->Equals(heap()->undefined_symbol())) { |
| 4404 __ CompareRoot(input, Heap::kUndefinedValueRootIndex); | 4355 __ CompareRoot(input, Heap::kUndefinedValueRootIndex); |
| 4405 __ b(eq, true_label); | 4356 __ b(eq, true_label); |
| 4406 __ JumpIfSmi(input, false_label); | 4357 __ JumpIfSmi(input, false_label); |
| 4407 // Check for undetectable objects => true. | 4358 // Check for undetectable objects => true. |
| 4408 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); | 4359 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 4409 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); | 4360 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); |
| 4410 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 4361 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 4411 final_branch_condition = ne; | 4362 final_branch_condition = ne; |
| 4412 | 4363 |
| 4413 } else if (type_name->Equals(heap()->function_symbol())) { | 4364 } else if (type_name->Equals(heap()->function_symbol())) { |
| 4414 __ JumpIfSmi(input, false_label); | 4365 __ JumpIfSmi(input, false_label); |
| 4415 __ CompareObjectType(input, input, scratch, | 4366 __ CompareObjectType(input, input, scratch, |
| 4416 FIRST_CALLABLE_SPEC_OBJECT_TYPE); | 4367 FIRST_CALLABLE_SPEC_OBJECT_TYPE); |
| 4417 final_branch_condition = ge; | 4368 final_branch_condition = ge; |
| 4418 | 4369 |
| 4419 } else if (type_name->Equals(heap()->object_symbol())) { | 4370 } else if (type_name->Equals(heap()->object_symbol())) { |
| 4420 __ JumpIfSmi(input, false_label); | 4371 __ JumpIfSmi(input, false_label); |
| 4421 __ CompareRoot(input, Heap::kNullValueRootIndex); | 4372 if (!FLAG_harmony_typeof) { |
| 4422 __ b(eq, true_label); | 4373 __ CompareRoot(input, Heap::kNullValueRootIndex); |
| 4374 __ b(eq, true_label); |
| 4375 } |
| 4423 __ CompareObjectType(input, input, scratch, | 4376 __ CompareObjectType(input, input, scratch, |
| 4424 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4377 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 4425 __ b(lt, false_label); | 4378 __ b(lt, false_label); |
| 4426 __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4379 __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 4427 __ b(gt, false_label); | 4380 __ b(gt, false_label); |
| 4428 // Check for undetectable objects => false. | 4381 // Check for undetectable objects => false. |
| 4429 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); | 4382 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); |
| 4430 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 4383 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 4431 final_branch_condition = eq; | 4384 final_branch_condition = eq; |
| 4432 | 4385 |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4576 ASSERT(osr_pc_offset_ == -1); | 4529 ASSERT(osr_pc_offset_ == -1); |
| 4577 osr_pc_offset_ = masm()->pc_offset(); | 4530 osr_pc_offset_ = masm()->pc_offset(); |
| 4578 } | 4531 } |
| 4579 | 4532 |
| 4580 | 4533 |
| 4581 | 4534 |
| 4582 | 4535 |
| 4583 #undef __ | 4536 #undef __ |
| 4584 | 4537 |
| 4585 } } // namespace v8::internal | 4538 } } // namespace v8::internal |
| OLD | NEW |