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 |