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 2040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2051 // Test the double value. Zero and NaN are false. | 2051 // Test the double value. Zero and NaN are false. |
2052 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2052 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
2053 __ cmp(r0, r0, vs); // If NaN, set the Z flag. (NaN) | 2053 __ cmp(r0, r0, vs); // If NaN, set the Z flag. (NaN) |
2054 EmitBranch(instr, ne); | 2054 EmitBranch(instr, ne); |
2055 } else if (type.IsString()) { | 2055 } else if (type.IsString()) { |
2056 DCHECK(!info()->IsStub()); | 2056 DCHECK(!info()->IsStub()); |
2057 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2057 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); |
2058 __ cmp(ip, Operand::Zero()); | 2058 __ cmp(ip, Operand::Zero()); |
2059 EmitBranch(instr, ne); | 2059 EmitBranch(instr, ne); |
2060 } else { | 2060 } else { |
2061 ToBooleanICStub::Types expected = | 2061 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); |
2062 instr->hydrogen()->expected_input_types(); | |
2063 // Avoid deopts in the case where we've never executed this path before. | 2062 // Avoid deopts in the case where we've never executed this path before. |
2064 if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic(); | 2063 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; |
2065 | 2064 |
2066 if (expected.Contains(ToBooleanICStub::UNDEFINED)) { | 2065 if (expected & ToBooleanHint::kUndefined) { |
2067 // undefined -> false. | 2066 // undefined -> false. |
2068 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 2067 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
2069 __ b(eq, instr->FalseLabel(chunk_)); | 2068 __ b(eq, instr->FalseLabel(chunk_)); |
2070 } | 2069 } |
2071 if (expected.Contains(ToBooleanICStub::BOOLEAN)) { | 2070 if (expected & ToBooleanHint::kBoolean) { |
2072 // Boolean -> its value. | 2071 // Boolean -> its value. |
2073 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2072 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
2074 __ b(eq, instr->TrueLabel(chunk_)); | 2073 __ b(eq, instr->TrueLabel(chunk_)); |
2075 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 2074 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
2076 __ b(eq, instr->FalseLabel(chunk_)); | 2075 __ b(eq, instr->FalseLabel(chunk_)); |
2077 } | 2076 } |
2078 if (expected.Contains(ToBooleanICStub::NULL_TYPE)) { | 2077 if (expected & ToBooleanHint::kNull) { |
2079 // 'null' -> false. | 2078 // 'null' -> false. |
2080 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 2079 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
2081 __ b(eq, instr->FalseLabel(chunk_)); | 2080 __ b(eq, instr->FalseLabel(chunk_)); |
2082 } | 2081 } |
2083 | 2082 |
2084 if (expected.Contains(ToBooleanICStub::SMI)) { | 2083 if (expected & ToBooleanHint::kSmallInteger) { |
2085 // Smis: 0 -> false, all other -> true. | 2084 // Smis: 0 -> false, all other -> true. |
2086 __ cmp(reg, Operand::Zero()); | 2085 __ cmp(reg, Operand::Zero()); |
2087 __ b(eq, instr->FalseLabel(chunk_)); | 2086 __ b(eq, instr->FalseLabel(chunk_)); |
2088 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2087 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
2089 } else if (expected.NeedsMap()) { | 2088 } else if (expected & ToBooleanHint::kNeedsMap) { |
2090 // If we need a map later and have a Smi -> deopt. | 2089 // If we need a map later and have a Smi -> deopt. |
2091 __ SmiTst(reg); | 2090 __ SmiTst(reg); |
2092 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi); | 2091 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi); |
2093 } | 2092 } |
2094 | 2093 |
2095 const Register map = scratch0(); | 2094 const Register map = scratch0(); |
2096 if (expected.NeedsMap()) { | 2095 if (expected & ToBooleanHint::kNeedsMap) { |
2097 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2096 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2098 | 2097 |
2099 if (expected.CanBeUndetectable()) { | 2098 if (expected & ToBooleanHint::kCanBeUndetectable) { |
2100 // Undetectable -> false. | 2099 // Undetectable -> false. |
2101 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); | 2100 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
2102 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 2101 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
2103 __ b(ne, instr->FalseLabel(chunk_)); | 2102 __ b(ne, instr->FalseLabel(chunk_)); |
2104 } | 2103 } |
2105 } | 2104 } |
2106 | 2105 |
2107 if (expected.Contains(ToBooleanICStub::SPEC_OBJECT)) { | 2106 if (expected & ToBooleanHint::kReceiver) { |
2108 // spec object -> true. | 2107 // spec object -> true. |
2109 __ CompareInstanceType(map, ip, FIRST_JS_RECEIVER_TYPE); | 2108 __ CompareInstanceType(map, ip, FIRST_JS_RECEIVER_TYPE); |
2110 __ b(ge, instr->TrueLabel(chunk_)); | 2109 __ b(ge, instr->TrueLabel(chunk_)); |
2111 } | 2110 } |
2112 | 2111 |
2113 if (expected.Contains(ToBooleanICStub::STRING)) { | 2112 if (expected & ToBooleanHint::kString) { |
2114 // String value -> false iff empty. | 2113 // String value -> false iff empty. |
2115 Label not_string; | 2114 Label not_string; |
2116 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | 2115 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
2117 __ b(ge, ¬_string); | 2116 __ b(ge, ¬_string); |
2118 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2117 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); |
2119 __ cmp(ip, Operand::Zero()); | 2118 __ cmp(ip, Operand::Zero()); |
2120 __ b(ne, instr->TrueLabel(chunk_)); | 2119 __ b(ne, instr->TrueLabel(chunk_)); |
2121 __ b(instr->FalseLabel(chunk_)); | 2120 __ b(instr->FalseLabel(chunk_)); |
2122 __ bind(¬_string); | 2121 __ bind(¬_string); |
2123 } | 2122 } |
2124 | 2123 |
2125 if (expected.Contains(ToBooleanICStub::SYMBOL)) { | 2124 if (expected & ToBooleanHint::kSymbol) { |
2126 // Symbol value -> true. | 2125 // Symbol value -> true. |
2127 __ CompareInstanceType(map, ip, SYMBOL_TYPE); | 2126 __ CompareInstanceType(map, ip, SYMBOL_TYPE); |
2128 __ b(eq, instr->TrueLabel(chunk_)); | 2127 __ b(eq, instr->TrueLabel(chunk_)); |
2129 } | 2128 } |
2130 | 2129 |
2131 if (expected.Contains(ToBooleanICStub::SIMD_VALUE)) { | 2130 if (expected & ToBooleanHint::kSimdValue) { |
2132 // SIMD value -> true. | 2131 // SIMD value -> true. |
2133 __ CompareInstanceType(map, ip, SIMD128_VALUE_TYPE); | 2132 __ CompareInstanceType(map, ip, SIMD128_VALUE_TYPE); |
2134 __ b(eq, instr->TrueLabel(chunk_)); | 2133 __ b(eq, instr->TrueLabel(chunk_)); |
2135 } | 2134 } |
2136 | 2135 |
2137 if (expected.Contains(ToBooleanICStub::HEAP_NUMBER)) { | 2136 if (expected & ToBooleanHint::kHeapNumber) { |
2138 // heap number -> false iff +0, -0, or NaN. | 2137 // heap number -> false iff +0, -0, or NaN. |
2139 DwVfpRegister dbl_scratch = double_scratch0(); | 2138 DwVfpRegister dbl_scratch = double_scratch0(); |
2140 Label not_heap_number; | 2139 Label not_heap_number; |
2141 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2140 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
2142 __ b(ne, ¬_heap_number); | 2141 __ b(ne, ¬_heap_number); |
2143 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2142 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
2144 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2143 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
2145 __ cmp(r0, r0, vs); // NaN -> false. | 2144 __ cmp(r0, r0, vs); // NaN -> false. |
2146 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false. | 2145 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false. |
2147 __ b(instr->TrueLabel(chunk_)); | 2146 __ b(instr->TrueLabel(chunk_)); |
2148 __ bind(¬_heap_number); | 2147 __ bind(¬_heap_number); |
2149 } | 2148 } |
2150 | 2149 |
2151 if (!expected.IsGeneric()) { | 2150 if (expected != ToBooleanHint::kAny) { |
2152 // We've seen something for the first time -> deopt. | 2151 // We've seen something for the first time -> deopt. |
2153 // This can only happen if we are not generic already. | 2152 // This can only happen if we are not generic already. |
2154 DeoptimizeIf(al, instr, DeoptimizeReason::kUnexpectedObject); | 2153 DeoptimizeIf(al, instr, DeoptimizeReason::kUnexpectedObject); |
2155 } | 2154 } |
2156 } | 2155 } |
2157 } | 2156 } |
2158 } | 2157 } |
2159 | 2158 |
2160 | 2159 |
2161 void LCodeGen::EmitGoto(int block) { | 2160 void LCodeGen::EmitGoto(int block) { |
(...skipping 3222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5384 __ ldr(result, FieldMemOperand(scratch, | 5383 __ ldr(result, FieldMemOperand(scratch, |
5385 FixedArray::kHeaderSize - kPointerSize)); | 5384 FixedArray::kHeaderSize - kPointerSize)); |
5386 __ bind(deferred->exit()); | 5385 __ bind(deferred->exit()); |
5387 __ bind(&done); | 5386 __ bind(&done); |
5388 } | 5387 } |
5389 | 5388 |
5390 #undef __ | 5389 #undef __ |
5391 | 5390 |
5392 } // namespace internal | 5391 } // namespace internal |
5393 } // namespace v8 | 5392 } // namespace v8 |
OLD | NEW |