| 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 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 6 | 6 |
| 7 #include "src/crankshaft/x87/lithium-codegen-x87.h" | 7 #include "src/crankshaft/x87/lithium-codegen-x87.h" |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 2107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2118 } else if (type.IsJSArray()) { | 2118 } else if (type.IsJSArray()) { |
| 2119 DCHECK(!info()->IsStub()); | 2119 DCHECK(!info()->IsStub()); |
| 2120 EmitBranch(instr, no_condition); | 2120 EmitBranch(instr, no_condition); |
| 2121 } else if (type.IsHeapNumber()) { | 2121 } else if (type.IsHeapNumber()) { |
| 2122 UNREACHABLE(); | 2122 UNREACHABLE(); |
| 2123 } else if (type.IsString()) { | 2123 } else if (type.IsString()) { |
| 2124 DCHECK(!info()->IsStub()); | 2124 DCHECK(!info()->IsStub()); |
| 2125 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2125 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 2126 EmitBranch(instr, not_equal); | 2126 EmitBranch(instr, not_equal); |
| 2127 } else { | 2127 } else { |
| 2128 ToBooleanICStub::Types expected = | 2128 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); |
| 2129 instr->hydrogen()->expected_input_types(); | 2129 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; |
| 2130 if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic(); | |
| 2131 | 2130 |
| 2132 if (expected.Contains(ToBooleanICStub::UNDEFINED)) { | 2131 if (expected & ToBooleanHint::kUndefined) { |
| 2133 // undefined -> false. | 2132 // undefined -> false. |
| 2134 __ cmp(reg, factory()->undefined_value()); | 2133 __ cmp(reg, factory()->undefined_value()); |
| 2135 __ j(equal, instr->FalseLabel(chunk_)); | 2134 __ j(equal, instr->FalseLabel(chunk_)); |
| 2136 } | 2135 } |
| 2137 if (expected.Contains(ToBooleanICStub::BOOLEAN)) { | 2136 if (expected & ToBooleanHint::kBoolean) { |
| 2138 // true -> true. | 2137 // true -> true. |
| 2139 __ cmp(reg, factory()->true_value()); | 2138 __ cmp(reg, factory()->true_value()); |
| 2140 __ j(equal, instr->TrueLabel(chunk_)); | 2139 __ j(equal, instr->TrueLabel(chunk_)); |
| 2141 // false -> false. | 2140 // false -> false. |
| 2142 __ cmp(reg, factory()->false_value()); | 2141 __ cmp(reg, factory()->false_value()); |
| 2143 __ j(equal, instr->FalseLabel(chunk_)); | 2142 __ j(equal, instr->FalseLabel(chunk_)); |
| 2144 } | 2143 } |
| 2145 if (expected.Contains(ToBooleanICStub::NULL_TYPE)) { | 2144 if (expected & ToBooleanHint::kNull) { |
| 2146 // 'null' -> false. | 2145 // 'null' -> false. |
| 2147 __ cmp(reg, factory()->null_value()); | 2146 __ cmp(reg, factory()->null_value()); |
| 2148 __ j(equal, instr->FalseLabel(chunk_)); | 2147 __ j(equal, instr->FalseLabel(chunk_)); |
| 2149 } | 2148 } |
| 2150 | 2149 |
| 2151 if (expected.Contains(ToBooleanICStub::SMI)) { | 2150 if (expected & ToBooleanHint::kSmallInteger) { |
| 2152 // Smis: 0 -> false, all other -> true. | 2151 // Smis: 0 -> false, all other -> true. |
| 2153 __ test(reg, Operand(reg)); | 2152 __ test(reg, Operand(reg)); |
| 2154 __ j(equal, instr->FalseLabel(chunk_)); | 2153 __ j(equal, instr->FalseLabel(chunk_)); |
| 2155 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2154 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2156 } else if (expected.NeedsMap()) { | 2155 } else if (expected & ToBooleanHint::kNeedsMap) { |
| 2157 // If we need a map later and have a Smi -> deopt. | 2156 // If we need a map later and have a Smi -> deopt. |
| 2158 __ test(reg, Immediate(kSmiTagMask)); | 2157 __ test(reg, Immediate(kSmiTagMask)); |
| 2159 DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi); | 2158 DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi); |
| 2160 } | 2159 } |
| 2161 | 2160 |
| 2162 Register map = no_reg; // Keep the compiler happy. | 2161 Register map = no_reg; // Keep the compiler happy. |
| 2163 if (expected.NeedsMap()) { | 2162 if (expected & ToBooleanHint::kNeedsMap) { |
| 2164 map = ToRegister(instr->temp()); | 2163 map = ToRegister(instr->temp()); |
| 2165 DCHECK(!map.is(reg)); | 2164 DCHECK(!map.is(reg)); |
| 2166 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | 2165 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
| 2167 | 2166 |
| 2168 if (expected.CanBeUndetectable()) { | 2167 if (expected & ToBooleanHint::kCanBeUndetectable) { |
| 2169 // Undetectable -> false. | 2168 // Undetectable -> false. |
| 2170 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | 2169 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
| 2171 Immediate(1 << Map::kIsUndetectable)); | 2170 Immediate(1 << Map::kIsUndetectable)); |
| 2172 __ j(not_zero, instr->FalseLabel(chunk_)); | 2171 __ j(not_zero, instr->FalseLabel(chunk_)); |
| 2173 } | 2172 } |
| 2174 } | 2173 } |
| 2175 | 2174 |
| 2176 if (expected.Contains(ToBooleanICStub::SPEC_OBJECT)) { | 2175 if (expected & ToBooleanHint::kReceiver) { |
| 2177 // spec object -> true. | 2176 // spec object -> true. |
| 2178 __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE); | 2177 __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE); |
| 2179 __ j(above_equal, instr->TrueLabel(chunk_)); | 2178 __ j(above_equal, instr->TrueLabel(chunk_)); |
| 2180 } | 2179 } |
| 2181 | 2180 |
| 2182 if (expected.Contains(ToBooleanICStub::STRING)) { | 2181 if (expected & ToBooleanHint::kString) { |
| 2183 // String value -> false iff empty. | 2182 // String value -> false iff empty. |
| 2184 Label not_string; | 2183 Label not_string; |
| 2185 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 2184 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
| 2186 __ j(above_equal, ¬_string, Label::kNear); | 2185 __ j(above_equal, ¬_string, Label::kNear); |
| 2187 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2186 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 2188 __ j(not_zero, instr->TrueLabel(chunk_)); | 2187 __ j(not_zero, instr->TrueLabel(chunk_)); |
| 2189 __ jmp(instr->FalseLabel(chunk_)); | 2188 __ jmp(instr->FalseLabel(chunk_)); |
| 2190 __ bind(¬_string); | 2189 __ bind(¬_string); |
| 2191 } | 2190 } |
| 2192 | 2191 |
| 2193 if (expected.Contains(ToBooleanICStub::SYMBOL)) { | 2192 if (expected & ToBooleanHint::kSymbol) { |
| 2194 // Symbol value -> true. | 2193 // Symbol value -> true. |
| 2195 __ CmpInstanceType(map, SYMBOL_TYPE); | 2194 __ CmpInstanceType(map, SYMBOL_TYPE); |
| 2196 __ j(equal, instr->TrueLabel(chunk_)); | 2195 __ j(equal, instr->TrueLabel(chunk_)); |
| 2197 } | 2196 } |
| 2198 | 2197 |
| 2199 if (expected.Contains(ToBooleanICStub::SIMD_VALUE)) { | 2198 if (expected & ToBooleanHint::kSimdValue) { |
| 2200 // SIMD value -> true. | 2199 // SIMD value -> true. |
| 2201 __ CmpInstanceType(map, SIMD128_VALUE_TYPE); | 2200 __ CmpInstanceType(map, SIMD128_VALUE_TYPE); |
| 2202 __ j(equal, instr->TrueLabel(chunk_)); | 2201 __ j(equal, instr->TrueLabel(chunk_)); |
| 2203 } | 2202 } |
| 2204 | 2203 |
| 2205 if (expected.Contains(ToBooleanICStub::HEAP_NUMBER)) { | 2204 if (expected & ToBooleanHint::kHeapNumber) { |
| 2206 // heap number -> false iff +0, -0, or NaN. | 2205 // heap number -> false iff +0, -0, or NaN. |
| 2207 Label not_heap_number; | 2206 Label not_heap_number; |
| 2208 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 2207 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 2209 factory()->heap_number_map()); | 2208 factory()->heap_number_map()); |
| 2210 __ j(not_equal, ¬_heap_number, Label::kNear); | 2209 __ j(not_equal, ¬_heap_number, Label::kNear); |
| 2211 __ fldz(); | 2210 __ fldz(); |
| 2212 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 2211 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 2213 __ FCmp(); | 2212 __ FCmp(); |
| 2214 __ j(zero, instr->FalseLabel(chunk_)); | 2213 __ j(zero, instr->FalseLabel(chunk_)); |
| 2215 __ jmp(instr->TrueLabel(chunk_)); | 2214 __ jmp(instr->TrueLabel(chunk_)); |
| 2216 __ bind(¬_heap_number); | 2215 __ bind(¬_heap_number); |
| 2217 } | 2216 } |
| 2218 | 2217 |
| 2219 if (!expected.IsGeneric()) { | 2218 if (expected != ToBooleanHint::kAny) { |
| 2220 // We've seen something for the first time -> deopt. | 2219 // We've seen something for the first time -> deopt. |
| 2221 // This can only happen if we are not generic already. | 2220 // This can only happen if we are not generic already. |
| 2222 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kUnexpectedObject); | 2221 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kUnexpectedObject); |
| 2223 } | 2222 } |
| 2224 } | 2223 } |
| 2225 } | 2224 } |
| 2226 } | 2225 } |
| 2227 | 2226 |
| 2228 | 2227 |
| 2229 void LCodeGen::EmitGoto(int block) { | 2228 void LCodeGen::EmitGoto(int block) { |
| (...skipping 3411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5641 __ bind(deferred->exit()); | 5640 __ bind(deferred->exit()); |
| 5642 __ bind(&done); | 5641 __ bind(&done); |
| 5643 } | 5642 } |
| 5644 | 5643 |
| 5645 #undef __ | 5644 #undef __ |
| 5646 | 5645 |
| 5647 } // namespace internal | 5646 } // namespace internal |
| 5648 } // namespace v8 | 5647 } // namespace v8 |
| 5649 | 5648 |
| 5650 #endif // V8_TARGET_ARCH_X87 | 5649 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |