| 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 #include "src/crankshaft/arm/lithium-codegen-arm.h" | 5 #include "src/crankshaft/arm/lithium-codegen-arm.h" |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/crankshaft/arm/lithium-gap-resolver-arm.h" | 10 #include "src/crankshaft/arm/lithium-gap-resolver-arm.h" |
| (...skipping 2052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2063 // Test the double value. Zero and NaN are false. | 2063 // Test the double value. Zero and NaN are false. |
| 2064 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2064 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
| 2065 __ cmp(r0, r0, vs); // If NaN, set the Z flag. (NaN) | 2065 __ cmp(r0, r0, vs); // If NaN, set the Z flag. (NaN) |
| 2066 EmitBranch(instr, ne); | 2066 EmitBranch(instr, ne); |
| 2067 } else if (type.IsString()) { | 2067 } else if (type.IsString()) { |
| 2068 DCHECK(!info()->IsStub()); | 2068 DCHECK(!info()->IsStub()); |
| 2069 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2069 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); |
| 2070 __ cmp(ip, Operand::Zero()); | 2070 __ cmp(ip, Operand::Zero()); |
| 2071 EmitBranch(instr, ne); | 2071 EmitBranch(instr, ne); |
| 2072 } else { | 2072 } else { |
| 2073 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 2073 ToBooleanICStub::Types expected = |
| 2074 instr->hydrogen()->expected_input_types(); |
| 2074 // Avoid deopts in the case where we've never executed this path before. | 2075 // Avoid deopts in the case where we've never executed this path before. |
| 2075 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); | 2076 if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic(); |
| 2076 | 2077 |
| 2077 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 2078 if (expected.Contains(ToBooleanICStub::UNDEFINED)) { |
| 2078 // undefined -> false. | 2079 // undefined -> false. |
| 2079 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 2080 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
| 2080 __ b(eq, instr->FalseLabel(chunk_)); | 2081 __ b(eq, instr->FalseLabel(chunk_)); |
| 2081 } | 2082 } |
| 2082 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 2083 if (expected.Contains(ToBooleanICStub::BOOLEAN)) { |
| 2083 // Boolean -> its value. | 2084 // Boolean -> its value. |
| 2084 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2085 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
| 2085 __ b(eq, instr->TrueLabel(chunk_)); | 2086 __ b(eq, instr->TrueLabel(chunk_)); |
| 2086 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 2087 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
| 2087 __ b(eq, instr->FalseLabel(chunk_)); | 2088 __ b(eq, instr->FalseLabel(chunk_)); |
| 2088 } | 2089 } |
| 2089 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 2090 if (expected.Contains(ToBooleanICStub::NULL_TYPE)) { |
| 2090 // 'null' -> false. | 2091 // 'null' -> false. |
| 2091 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 2092 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
| 2092 __ b(eq, instr->FalseLabel(chunk_)); | 2093 __ b(eq, instr->FalseLabel(chunk_)); |
| 2093 } | 2094 } |
| 2094 | 2095 |
| 2095 if (expected.Contains(ToBooleanStub::SMI)) { | 2096 if (expected.Contains(ToBooleanICStub::SMI)) { |
| 2096 // Smis: 0 -> false, all other -> true. | 2097 // Smis: 0 -> false, all other -> true. |
| 2097 __ cmp(reg, Operand::Zero()); | 2098 __ cmp(reg, Operand::Zero()); |
| 2098 __ b(eq, instr->FalseLabel(chunk_)); | 2099 __ b(eq, instr->FalseLabel(chunk_)); |
| 2099 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2100 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2100 } else if (expected.NeedsMap()) { | 2101 } else if (expected.NeedsMap()) { |
| 2101 // If we need a map later and have a Smi -> deopt. | 2102 // If we need a map later and have a Smi -> deopt. |
| 2102 __ SmiTst(reg); | 2103 __ SmiTst(reg); |
| 2103 DeoptimizeIf(eq, instr, Deoptimizer::kSmi); | 2104 DeoptimizeIf(eq, instr, Deoptimizer::kSmi); |
| 2104 } | 2105 } |
| 2105 | 2106 |
| 2106 const Register map = scratch0(); | 2107 const Register map = scratch0(); |
| 2107 if (expected.NeedsMap()) { | 2108 if (expected.NeedsMap()) { |
| 2108 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2109 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2109 | 2110 |
| 2110 if (expected.CanBeUndetectable()) { | 2111 if (expected.CanBeUndetectable()) { |
| 2111 // Undetectable -> false. | 2112 // Undetectable -> false. |
| 2112 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); | 2113 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 2113 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 2114 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 2114 __ b(ne, instr->FalseLabel(chunk_)); | 2115 __ b(ne, instr->FalseLabel(chunk_)); |
| 2115 } | 2116 } |
| 2116 } | 2117 } |
| 2117 | 2118 |
| 2118 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 2119 if (expected.Contains(ToBooleanICStub::SPEC_OBJECT)) { |
| 2119 // spec object -> true. | 2120 // spec object -> true. |
| 2120 __ CompareInstanceType(map, ip, FIRST_JS_RECEIVER_TYPE); | 2121 __ CompareInstanceType(map, ip, FIRST_JS_RECEIVER_TYPE); |
| 2121 __ b(ge, instr->TrueLabel(chunk_)); | 2122 __ b(ge, instr->TrueLabel(chunk_)); |
| 2122 } | 2123 } |
| 2123 | 2124 |
| 2124 if (expected.Contains(ToBooleanStub::STRING)) { | 2125 if (expected.Contains(ToBooleanICStub::STRING)) { |
| 2125 // String value -> false iff empty. | 2126 // String value -> false iff empty. |
| 2126 Label not_string; | 2127 Label not_string; |
| 2127 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | 2128 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
| 2128 __ b(ge, ¬_string); | 2129 __ b(ge, ¬_string); |
| 2129 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2130 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); |
| 2130 __ cmp(ip, Operand::Zero()); | 2131 __ cmp(ip, Operand::Zero()); |
| 2131 __ b(ne, instr->TrueLabel(chunk_)); | 2132 __ b(ne, instr->TrueLabel(chunk_)); |
| 2132 __ b(instr->FalseLabel(chunk_)); | 2133 __ b(instr->FalseLabel(chunk_)); |
| 2133 __ bind(¬_string); | 2134 __ bind(¬_string); |
| 2134 } | 2135 } |
| 2135 | 2136 |
| 2136 if (expected.Contains(ToBooleanStub::SYMBOL)) { | 2137 if (expected.Contains(ToBooleanICStub::SYMBOL)) { |
| 2137 // Symbol value -> true. | 2138 // Symbol value -> true. |
| 2138 __ CompareInstanceType(map, ip, SYMBOL_TYPE); | 2139 __ CompareInstanceType(map, ip, SYMBOL_TYPE); |
| 2139 __ b(eq, instr->TrueLabel(chunk_)); | 2140 __ b(eq, instr->TrueLabel(chunk_)); |
| 2140 } | 2141 } |
| 2141 | 2142 |
| 2142 if (expected.Contains(ToBooleanStub::SIMD_VALUE)) { | 2143 if (expected.Contains(ToBooleanICStub::SIMD_VALUE)) { |
| 2143 // SIMD value -> true. | 2144 // SIMD value -> true. |
| 2144 __ CompareInstanceType(map, ip, SIMD128_VALUE_TYPE); | 2145 __ CompareInstanceType(map, ip, SIMD128_VALUE_TYPE); |
| 2145 __ b(eq, instr->TrueLabel(chunk_)); | 2146 __ b(eq, instr->TrueLabel(chunk_)); |
| 2146 } | 2147 } |
| 2147 | 2148 |
| 2148 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2149 if (expected.Contains(ToBooleanICStub::HEAP_NUMBER)) { |
| 2149 // heap number -> false iff +0, -0, or NaN. | 2150 // heap number -> false iff +0, -0, or NaN. |
| 2150 DwVfpRegister dbl_scratch = double_scratch0(); | 2151 DwVfpRegister dbl_scratch = double_scratch0(); |
| 2151 Label not_heap_number; | 2152 Label not_heap_number; |
| 2152 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2153 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
| 2153 __ b(ne, ¬_heap_number); | 2154 __ b(ne, ¬_heap_number); |
| 2154 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2155 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
| 2155 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2156 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
| 2156 __ cmp(r0, r0, vs); // NaN -> false. | 2157 __ cmp(r0, r0, vs); // NaN -> false. |
| 2157 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false. | 2158 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false. |
| 2158 __ b(instr->TrueLabel(chunk_)); | 2159 __ b(instr->TrueLabel(chunk_)); |
| (...skipping 3311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5470 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { | 5471 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { |
| 5471 Register context = ToRegister(instr->context()); | 5472 Register context = ToRegister(instr->context()); |
| 5472 __ str(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 5473 __ str(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 5473 } | 5474 } |
| 5474 | 5475 |
| 5475 | 5476 |
| 5476 #undef __ | 5477 #undef __ |
| 5477 | 5478 |
| 5478 } // namespace internal | 5479 } // namespace internal |
| 5479 } // namespace v8 | 5480 } // namespace v8 |
| OLD | NEW |