OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/ppc/lithium-codegen-ppc.h" | 5 #include "src/crankshaft/ppc/lithium-codegen-ppc.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/hydrogen-osr.h" | 10 #include "src/crankshaft/hydrogen-osr.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 void AfterCall() const override { | 28 void AfterCall() const override { |
29 codegen_->RecordSafepoint(pointers_, deopt_mode_); | 29 codegen_->RecordSafepoint(pointers_, deopt_mode_); |
30 } | 30 } |
31 | 31 |
32 private: | 32 private: |
33 LCodeGen* codegen_; | 33 LCodeGen* codegen_; |
34 LPointerMap* pointers_; | 34 LPointerMap* pointers_; |
35 Safepoint::DeoptMode deopt_mode_; | 35 Safepoint::DeoptMode deopt_mode_; |
36 }; | 36 }; |
37 | 37 |
| 38 LCodeGen::PushSafepointRegistersScope::PushSafepointRegistersScope( |
| 39 LCodeGen* codegen) |
| 40 : codegen_(codegen) { |
| 41 DCHECK(codegen_->info()->is_calling()); |
| 42 DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kSimple); |
| 43 codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters; |
| 44 StoreRegistersStateStub stub(codegen_->isolate()); |
| 45 codegen_->masm_->CallStub(&stub); |
| 46 } |
| 47 |
| 48 LCodeGen::PushSafepointRegistersScope::~PushSafepointRegistersScope() { |
| 49 DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters); |
| 50 RestoreRegistersStateStub stub(codegen_->isolate()); |
| 51 codegen_->masm_->CallStub(&stub); |
| 52 codegen_->expected_safepoint_kind_ = Safepoint::kSimple; |
| 53 } |
38 | 54 |
39 #define __ masm()-> | 55 #define __ masm()-> |
40 | 56 |
41 bool LCodeGen::GenerateCode() { | 57 bool LCodeGen::GenerateCode() { |
42 LPhase phase("Z_Code generation", chunk()); | 58 LPhase phase("Z_Code generation", chunk()); |
43 DCHECK(is_unused()); | 59 DCHECK(is_unused()); |
44 status_ = GENERATING; | 60 status_ = GENERATING; |
45 | 61 |
46 // Open a frame scope to indicate that there is a frame on the stack. The | 62 // Open a frame scope to indicate that there is a frame on the stack. The |
47 // NONE indicates that the scope shouldn't actually generate code to set up | 63 // NONE indicates that the scope shouldn't actually generate code to set up |
(...skipping 2044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2092 __ fcmpu(dbl_scratch, kDoubleRegZero, cr7); | 2108 __ fcmpu(dbl_scratch, kDoubleRegZero, cr7); |
2093 __ mfcr(r0); | 2109 __ mfcr(r0); |
2094 __ andi(r0, r0, Operand(crZOrNaNBits)); | 2110 __ andi(r0, r0, Operand(crZOrNaNBits)); |
2095 EmitBranch(instr, eq, cr0); | 2111 EmitBranch(instr, eq, cr0); |
2096 } else if (type.IsString()) { | 2112 } else if (type.IsString()) { |
2097 DCHECK(!info()->IsStub()); | 2113 DCHECK(!info()->IsStub()); |
2098 __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2114 __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset)); |
2099 __ cmpi(ip, Operand::Zero()); | 2115 __ cmpi(ip, Operand::Zero()); |
2100 EmitBranch(instr, ne); | 2116 EmitBranch(instr, ne); |
2101 } else { | 2117 } else { |
2102 ToBooleanICStub::Types expected = | 2118 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); |
2103 instr->hydrogen()->expected_input_types(); | |
2104 // Avoid deopts in the case where we've never executed this path before. | 2119 // Avoid deopts in the case where we've never executed this path before. |
2105 if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic(); | 2120 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; |
2106 | 2121 |
2107 if (expected.Contains(ToBooleanICStub::UNDEFINED)) { | 2122 if (expected & ToBooleanHint::kUndefined) { |
2108 // undefined -> false. | 2123 // undefined -> false. |
2109 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 2124 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
2110 __ beq(instr->FalseLabel(chunk_)); | 2125 __ beq(instr->FalseLabel(chunk_)); |
2111 } | 2126 } |
2112 if (expected.Contains(ToBooleanICStub::BOOLEAN)) { | 2127 if (expected & ToBooleanHint::kBoolean) { |
2113 // Boolean -> its value. | 2128 // Boolean -> its value. |
2114 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2129 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
2115 __ beq(instr->TrueLabel(chunk_)); | 2130 __ beq(instr->TrueLabel(chunk_)); |
2116 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 2131 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
2117 __ beq(instr->FalseLabel(chunk_)); | 2132 __ beq(instr->FalseLabel(chunk_)); |
2118 } | 2133 } |
2119 if (expected.Contains(ToBooleanICStub::NULL_TYPE)) { | 2134 if (expected & ToBooleanHint::kNull) { |
2120 // 'null' -> false. | 2135 // 'null' -> false. |
2121 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 2136 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
2122 __ beq(instr->FalseLabel(chunk_)); | 2137 __ beq(instr->FalseLabel(chunk_)); |
2123 } | 2138 } |
2124 | 2139 |
2125 if (expected.Contains(ToBooleanICStub::SMI)) { | 2140 if (expected & ToBooleanHint::kSmallInteger) { |
2126 // Smis: 0 -> false, all other -> true. | 2141 // Smis: 0 -> false, all other -> true. |
2127 __ cmpi(reg, Operand::Zero()); | 2142 __ cmpi(reg, Operand::Zero()); |
2128 __ beq(instr->FalseLabel(chunk_)); | 2143 __ beq(instr->FalseLabel(chunk_)); |
2129 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2144 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
2130 } else if (expected.NeedsMap()) { | 2145 } else if (expected & ToBooleanHint::kNeedsMap) { |
2131 // If we need a map later and have a Smi -> deopt. | 2146 // If we need a map later and have a Smi -> deopt. |
2132 __ TestIfSmi(reg, r0); | 2147 __ TestIfSmi(reg, r0); |
2133 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, cr0); | 2148 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, cr0); |
2134 } | 2149 } |
2135 | 2150 |
2136 const Register map = scratch0(); | 2151 const Register map = scratch0(); |
2137 if (expected.NeedsMap()) { | 2152 if (expected & ToBooleanHint::kNeedsMap) { |
2138 __ LoadP(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2153 __ LoadP(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2139 | 2154 |
2140 if (expected.CanBeUndetectable()) { | 2155 if (expected & ToBooleanHint::kCanBeUndetectable) { |
2141 // Undetectable -> false. | 2156 // Undetectable -> false. |
2142 __ lbz(ip, FieldMemOperand(map, Map::kBitFieldOffset)); | 2157 __ lbz(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
2143 __ TestBit(ip, Map::kIsUndetectable, r0); | 2158 __ TestBit(ip, Map::kIsUndetectable, r0); |
2144 __ bne(instr->FalseLabel(chunk_), cr0); | 2159 __ bne(instr->FalseLabel(chunk_), cr0); |
2145 } | 2160 } |
2146 } | 2161 } |
2147 | 2162 |
2148 if (expected.Contains(ToBooleanICStub::SPEC_OBJECT)) { | 2163 if (expected & ToBooleanHint::kReceiver) { |
2149 // spec object -> true. | 2164 // spec object -> true. |
2150 __ CompareInstanceType(map, ip, FIRST_JS_RECEIVER_TYPE); | 2165 __ CompareInstanceType(map, ip, FIRST_JS_RECEIVER_TYPE); |
2151 __ bge(instr->TrueLabel(chunk_)); | 2166 __ bge(instr->TrueLabel(chunk_)); |
2152 } | 2167 } |
2153 | 2168 |
2154 if (expected.Contains(ToBooleanICStub::STRING)) { | 2169 if (expected & ToBooleanHint::kString) { |
2155 // String value -> false iff empty. | 2170 // String value -> false iff empty. |
2156 Label not_string; | 2171 Label not_string; |
2157 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | 2172 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
2158 __ bge(¬_string); | 2173 __ bge(¬_string); |
2159 __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2174 __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset)); |
2160 __ cmpi(ip, Operand::Zero()); | 2175 __ cmpi(ip, Operand::Zero()); |
2161 __ bne(instr->TrueLabel(chunk_)); | 2176 __ bne(instr->TrueLabel(chunk_)); |
2162 __ b(instr->FalseLabel(chunk_)); | 2177 __ b(instr->FalseLabel(chunk_)); |
2163 __ bind(¬_string); | 2178 __ bind(¬_string); |
2164 } | 2179 } |
2165 | 2180 |
2166 if (expected.Contains(ToBooleanICStub::SYMBOL)) { | 2181 if (expected & ToBooleanHint::kSymbol) { |
2167 // Symbol value -> true. | 2182 // Symbol value -> true. |
2168 __ CompareInstanceType(map, ip, SYMBOL_TYPE); | 2183 __ CompareInstanceType(map, ip, SYMBOL_TYPE); |
2169 __ beq(instr->TrueLabel(chunk_)); | 2184 __ beq(instr->TrueLabel(chunk_)); |
2170 } | 2185 } |
2171 | 2186 |
2172 if (expected.Contains(ToBooleanICStub::SIMD_VALUE)) { | 2187 if (expected & ToBooleanHint::kSimdValue) { |
2173 // SIMD value -> true. | 2188 // SIMD value -> true. |
2174 Label not_simd; | 2189 Label not_simd; |
2175 __ CompareInstanceType(map, ip, SIMD128_VALUE_TYPE); | 2190 __ CompareInstanceType(map, ip, SIMD128_VALUE_TYPE); |
2176 __ beq(instr->TrueLabel(chunk_)); | 2191 __ beq(instr->TrueLabel(chunk_)); |
2177 } | 2192 } |
2178 | 2193 |
2179 if (expected.Contains(ToBooleanICStub::HEAP_NUMBER)) { | 2194 if (expected & ToBooleanHint::kHeapNumber) { |
2180 // heap number -> false iff +0, -0, or NaN. | 2195 // heap number -> false iff +0, -0, or NaN. |
2181 Label not_heap_number; | 2196 Label not_heap_number; |
2182 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2197 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
2183 __ bne(¬_heap_number); | 2198 __ bne(¬_heap_number); |
2184 __ lfd(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2199 __ lfd(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
2185 // Test the double value. Zero and NaN are false. | 2200 // Test the double value. Zero and NaN are false. |
2186 __ fcmpu(dbl_scratch, kDoubleRegZero, cr7); | 2201 __ fcmpu(dbl_scratch, kDoubleRegZero, cr7); |
2187 __ mfcr(r0); | 2202 __ mfcr(r0); |
2188 __ andi(r0, r0, Operand(crZOrNaNBits)); | 2203 __ andi(r0, r0, Operand(crZOrNaNBits)); |
2189 __ bne(instr->FalseLabel(chunk_), cr0); | 2204 __ bne(instr->FalseLabel(chunk_), cr0); |
2190 __ b(instr->TrueLabel(chunk_)); | 2205 __ b(instr->TrueLabel(chunk_)); |
2191 __ bind(¬_heap_number); | 2206 __ bind(¬_heap_number); |
2192 } | 2207 } |
2193 | 2208 |
2194 if (!expected.IsGeneric()) { | 2209 if (expected != ToBooleanHint::kAny) { |
2195 // We've seen something for the first time -> deopt. | 2210 // We've seen something for the first time -> deopt. |
2196 // This can only happen if we are not generic already. | 2211 // This can only happen if we are not generic already. |
2197 DeoptimizeIf(al, instr, DeoptimizeReason::kUnexpectedObject); | 2212 DeoptimizeIf(al, instr, DeoptimizeReason::kUnexpectedObject); |
2198 } | 2213 } |
2199 } | 2214 } |
2200 } | 2215 } |
2201 } | 2216 } |
2202 | 2217 |
2203 | 2218 |
2204 void LCodeGen::EmitGoto(int block) { | 2219 void LCodeGen::EmitGoto(int block) { |
(...skipping 3433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5638 __ LoadP(result, | 5653 __ LoadP(result, |
5639 FieldMemOperand(scratch, FixedArray::kHeaderSize - kPointerSize)); | 5654 FieldMemOperand(scratch, FixedArray::kHeaderSize - kPointerSize)); |
5640 __ bind(deferred->exit()); | 5655 __ bind(deferred->exit()); |
5641 __ bind(&done); | 5656 __ bind(&done); |
5642 } | 5657 } |
5643 | 5658 |
5644 #undef __ | 5659 #undef __ |
5645 | 5660 |
5646 } // namespace internal | 5661 } // namespace internal |
5647 } // namespace v8 | 5662 } // namespace v8 |
OLD | NEW |