OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/crankshaft/x64/lithium-codegen-x64.h" | 7 #include "src/crankshaft/x64/lithium-codegen-x64.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 1975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1986 DCHECK(!info()->IsStub()); | 1986 DCHECK(!info()->IsStub()); |
1987 XMMRegister xmm_scratch = double_scratch0(); | 1987 XMMRegister xmm_scratch = double_scratch0(); |
1988 __ Xorpd(xmm_scratch, xmm_scratch); | 1988 __ Xorpd(xmm_scratch, xmm_scratch); |
1989 __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 1989 __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
1990 EmitBranch(instr, not_equal); | 1990 EmitBranch(instr, not_equal); |
1991 } else if (type.IsString()) { | 1991 } else if (type.IsString()) { |
1992 DCHECK(!info()->IsStub()); | 1992 DCHECK(!info()->IsStub()); |
1993 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 1993 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
1994 EmitBranch(instr, not_equal); | 1994 EmitBranch(instr, not_equal); |
1995 } else { | 1995 } else { |
1996 ToBooleanICStub::Types expected = | 1996 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); |
1997 instr->hydrogen()->expected_input_types(); | |
1998 // Avoid deopts in the case where we've never executed this path before. | 1997 // Avoid deopts in the case where we've never executed this path before. |
1999 if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic(); | 1998 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; |
2000 | 1999 |
2001 if (expected.Contains(ToBooleanICStub::UNDEFINED)) { | 2000 if (expected & ToBooleanHint::kUndefined) { |
2002 // undefined -> false. | 2001 // undefined -> false. |
2003 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 2002 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
2004 __ j(equal, instr->FalseLabel(chunk_)); | 2003 __ j(equal, instr->FalseLabel(chunk_)); |
2005 } | 2004 } |
2006 if (expected.Contains(ToBooleanICStub::BOOLEAN)) { | 2005 if (expected & ToBooleanHint::kBoolean) { |
2007 // true -> true. | 2006 // true -> true. |
2008 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2007 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
2009 __ j(equal, instr->TrueLabel(chunk_)); | 2008 __ j(equal, instr->TrueLabel(chunk_)); |
2010 // false -> false. | 2009 // false -> false. |
2011 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 2010 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
2012 __ j(equal, instr->FalseLabel(chunk_)); | 2011 __ j(equal, instr->FalseLabel(chunk_)); |
2013 } | 2012 } |
2014 if (expected.Contains(ToBooleanICStub::NULL_TYPE)) { | 2013 if (expected & ToBooleanHint::kNull) { |
2015 // 'null' -> false. | 2014 // 'null' -> false. |
2016 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 2015 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
2017 __ j(equal, instr->FalseLabel(chunk_)); | 2016 __ j(equal, instr->FalseLabel(chunk_)); |
2018 } | 2017 } |
2019 | 2018 |
2020 if (expected.Contains(ToBooleanICStub::SMI)) { | 2019 if (expected & ToBooleanHint::kSmallInteger) { |
2021 // Smis: 0 -> false, all other -> true. | 2020 // Smis: 0 -> false, all other -> true. |
2022 __ Cmp(reg, Smi::kZero); | 2021 __ Cmp(reg, Smi::kZero); |
2023 __ j(equal, instr->FalseLabel(chunk_)); | 2022 __ j(equal, instr->FalseLabel(chunk_)); |
2024 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2023 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
2025 } else if (expected.NeedsMap()) { | 2024 } else if (expected & ToBooleanHint::kNeedsMap) { |
2026 // If we need a map later and have a Smi -> deopt. | 2025 // If we need a map later and have a Smi -> deopt. |
2027 __ testb(reg, Immediate(kSmiTagMask)); | 2026 __ testb(reg, Immediate(kSmiTagMask)); |
2028 DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi); | 2027 DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi); |
2029 } | 2028 } |
2030 | 2029 |
2031 const Register map = kScratchRegister; | 2030 const Register map = kScratchRegister; |
2032 if (expected.NeedsMap()) { | 2031 if (expected & ToBooleanHint::kNeedsMap) { |
2033 __ movp(map, FieldOperand(reg, HeapObject::kMapOffset)); | 2032 __ movp(map, FieldOperand(reg, HeapObject::kMapOffset)); |
2034 | 2033 |
2035 if (expected.CanBeUndetectable()) { | 2034 if (expected & ToBooleanHint::kCanBeUndetectable) { |
2036 // Undetectable -> false. | 2035 // Undetectable -> false. |
2037 __ testb(FieldOperand(map, Map::kBitFieldOffset), | 2036 __ testb(FieldOperand(map, Map::kBitFieldOffset), |
2038 Immediate(1 << Map::kIsUndetectable)); | 2037 Immediate(1 << Map::kIsUndetectable)); |
2039 __ j(not_zero, instr->FalseLabel(chunk_)); | 2038 __ j(not_zero, instr->FalseLabel(chunk_)); |
2040 } | 2039 } |
2041 } | 2040 } |
2042 | 2041 |
2043 if (expected.Contains(ToBooleanICStub::SPEC_OBJECT)) { | 2042 if (expected & ToBooleanHint::kReceiver) { |
2044 // spec object -> true. | 2043 // spec object -> true. |
2045 __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE); | 2044 __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE); |
2046 __ j(above_equal, instr->TrueLabel(chunk_)); | 2045 __ j(above_equal, instr->TrueLabel(chunk_)); |
2047 } | 2046 } |
2048 | 2047 |
2049 if (expected.Contains(ToBooleanICStub::STRING)) { | 2048 if (expected & ToBooleanHint::kString) { |
2050 // String value -> false iff empty. | 2049 // String value -> false iff empty. |
2051 Label not_string; | 2050 Label not_string; |
2052 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 2051 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
2053 __ j(above_equal, ¬_string, Label::kNear); | 2052 __ j(above_equal, ¬_string, Label::kNear); |
2054 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2053 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
2055 __ j(not_zero, instr->TrueLabel(chunk_)); | 2054 __ j(not_zero, instr->TrueLabel(chunk_)); |
2056 __ jmp(instr->FalseLabel(chunk_)); | 2055 __ jmp(instr->FalseLabel(chunk_)); |
2057 __ bind(¬_string); | 2056 __ bind(¬_string); |
2058 } | 2057 } |
2059 | 2058 |
2060 if (expected.Contains(ToBooleanICStub::SYMBOL)) { | 2059 if (expected & ToBooleanHint::kSymbol) { |
2061 // Symbol value -> true. | 2060 // Symbol value -> true. |
2062 __ CmpInstanceType(map, SYMBOL_TYPE); | 2061 __ CmpInstanceType(map, SYMBOL_TYPE); |
2063 __ j(equal, instr->TrueLabel(chunk_)); | 2062 __ j(equal, instr->TrueLabel(chunk_)); |
2064 } | 2063 } |
2065 | 2064 |
2066 if (expected.Contains(ToBooleanICStub::SIMD_VALUE)) { | 2065 if (expected & ToBooleanHint::kSimdValue) { |
2067 // SIMD value -> true. | 2066 // SIMD value -> true. |
2068 __ CmpInstanceType(map, SIMD128_VALUE_TYPE); | 2067 __ CmpInstanceType(map, SIMD128_VALUE_TYPE); |
2069 __ j(equal, instr->TrueLabel(chunk_)); | 2068 __ j(equal, instr->TrueLabel(chunk_)); |
2070 } | 2069 } |
2071 | 2070 |
2072 if (expected.Contains(ToBooleanICStub::HEAP_NUMBER)) { | 2071 if (expected & ToBooleanHint::kHeapNumber) { |
2073 // heap number -> false iff +0, -0, or NaN. | 2072 // heap number -> false iff +0, -0, or NaN. |
2074 Label not_heap_number; | 2073 Label not_heap_number; |
2075 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2074 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
2076 __ j(not_equal, ¬_heap_number, Label::kNear); | 2075 __ j(not_equal, ¬_heap_number, Label::kNear); |
2077 XMMRegister xmm_scratch = double_scratch0(); | 2076 XMMRegister xmm_scratch = double_scratch0(); |
2078 __ Xorpd(xmm_scratch, xmm_scratch); | 2077 __ Xorpd(xmm_scratch, xmm_scratch); |
2079 __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 2078 __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
2080 __ j(zero, instr->FalseLabel(chunk_)); | 2079 __ j(zero, instr->FalseLabel(chunk_)); |
2081 __ jmp(instr->TrueLabel(chunk_)); | 2080 __ jmp(instr->TrueLabel(chunk_)); |
2082 __ bind(¬_heap_number); | 2081 __ bind(¬_heap_number); |
2083 } | 2082 } |
2084 | 2083 |
2085 if (!expected.IsGeneric()) { | 2084 if (expected != ToBooleanHint::kAny) { |
2086 // We've seen something for the first time -> deopt. | 2085 // We've seen something for the first time -> deopt. |
2087 // This can only happen if we are not generic already. | 2086 // This can only happen if we are not generic already. |
2088 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kUnexpectedObject); | 2087 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kUnexpectedObject); |
2089 } | 2088 } |
2090 } | 2089 } |
2091 } | 2090 } |
2092 } | 2091 } |
2093 | 2092 |
2094 | 2093 |
2095 void LCodeGen::EmitGoto(int block) { | 2094 void LCodeGen::EmitGoto(int block) { |
(...skipping 3335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5431 __ bind(deferred->exit()); | 5430 __ bind(deferred->exit()); |
5432 __ bind(&done); | 5431 __ bind(&done); |
5433 } | 5432 } |
5434 | 5433 |
5435 #undef __ | 5434 #undef __ |
5436 | 5435 |
5437 } // namespace internal | 5436 } // namespace internal |
5438 } // namespace v8 | 5437 } // namespace v8 |
5439 | 5438 |
5440 #endif // V8_TARGET_ARCH_X64 | 5439 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |