| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
| 4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
| 5 | 5 |
| 6 #include "src/crankshaft/s390/lithium-codegen-s390.h" | 6 #include "src/crankshaft/s390/lithium-codegen-s390.h" |
| 7 | 7 |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.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 } |
| 54 |
| 38 #define __ masm()-> | 55 #define __ masm()-> |
| 39 | 56 |
| 40 bool LCodeGen::GenerateCode() { | 57 bool LCodeGen::GenerateCode() { |
| 41 LPhase phase("Z_Code generation", chunk()); | 58 LPhase phase("Z_Code generation", chunk()); |
| 42 DCHECK(is_unused()); | 59 DCHECK(is_unused()); |
| 43 status_ = GENERATING; | 60 status_ = GENERATING; |
| 44 | 61 |
| 45 // 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 |
| 46 // 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 |
| 47 // the frame (that is done in GeneratePrologue). | 64 // the frame (that is done in GeneratePrologue). |
| (...skipping 2046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2094 __ lzdr(kDoubleRegZero); | 2111 __ lzdr(kDoubleRegZero); |
| 2095 __ cdbr(dbl_scratch, kDoubleRegZero); | 2112 __ cdbr(dbl_scratch, kDoubleRegZero); |
| 2096 Condition lt_gt = static_cast<Condition>(lt | gt); | 2113 Condition lt_gt = static_cast<Condition>(lt | gt); |
| 2097 EmitBranch(instr, lt_gt); | 2114 EmitBranch(instr, lt_gt); |
| 2098 } else if (type.IsString()) { | 2115 } else if (type.IsString()) { |
| 2099 DCHECK(!info()->IsStub()); | 2116 DCHECK(!info()->IsStub()); |
| 2100 __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2117 __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset)); |
| 2101 __ CmpP(ip, Operand::Zero()); | 2118 __ CmpP(ip, Operand::Zero()); |
| 2102 EmitBranch(instr, ne); | 2119 EmitBranch(instr, ne); |
| 2103 } else { | 2120 } else { |
| 2104 ToBooleanICStub::Types expected = | 2121 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); |
| 2105 instr->hydrogen()->expected_input_types(); | |
| 2106 // Avoid deopts in the case where we've never executed this path before. | 2122 // Avoid deopts in the case where we've never executed this path before. |
| 2107 if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic(); | 2123 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; |
| 2108 | 2124 |
| 2109 if (expected.Contains(ToBooleanICStub::UNDEFINED)) { | 2125 if (expected & ToBooleanHint::kUndefined) { |
| 2110 // undefined -> false. | 2126 // undefined -> false. |
| 2111 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 2127 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
| 2112 __ beq(instr->FalseLabel(chunk_)); | 2128 __ beq(instr->FalseLabel(chunk_)); |
| 2113 } | 2129 } |
| 2114 if (expected.Contains(ToBooleanICStub::BOOLEAN)) { | 2130 if (expected & ToBooleanHint::kBoolean) { |
| 2115 // Boolean -> its value. | 2131 // Boolean -> its value. |
| 2116 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2132 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
| 2117 __ beq(instr->TrueLabel(chunk_)); | 2133 __ beq(instr->TrueLabel(chunk_)); |
| 2118 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 2134 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
| 2119 __ beq(instr->FalseLabel(chunk_)); | 2135 __ beq(instr->FalseLabel(chunk_)); |
| 2120 } | 2136 } |
| 2121 if (expected.Contains(ToBooleanICStub::NULL_TYPE)) { | 2137 if (expected & ToBooleanHint::kNull) { |
| 2122 // 'null' -> false. | 2138 // 'null' -> false. |
| 2123 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 2139 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
| 2124 __ beq(instr->FalseLabel(chunk_)); | 2140 __ beq(instr->FalseLabel(chunk_)); |
| 2125 } | 2141 } |
| 2126 | 2142 |
| 2127 if (expected.Contains(ToBooleanICStub::SMI)) { | 2143 if (expected & ToBooleanHint::kSmallInteger) { |
| 2128 // Smis: 0 -> false, all other -> true. | 2144 // Smis: 0 -> false, all other -> true. |
| 2129 __ CmpP(reg, Operand::Zero()); | 2145 __ CmpP(reg, Operand::Zero()); |
| 2130 __ beq(instr->FalseLabel(chunk_)); | 2146 __ beq(instr->FalseLabel(chunk_)); |
| 2131 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2147 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2132 } else if (expected.NeedsMap()) { | 2148 } else if (expected & ToBooleanHint::kNeedsMap) { |
| 2133 // If we need a map later and have a Smi -> deopt. | 2149 // If we need a map later and have a Smi -> deopt. |
| 2134 __ TestIfSmi(reg); | 2150 __ TestIfSmi(reg); |
| 2135 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, cr0); | 2151 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, cr0); |
| 2136 } | 2152 } |
| 2137 | 2153 |
| 2138 const Register map = scratch0(); | 2154 const Register map = scratch0(); |
| 2139 if (expected.NeedsMap()) { | 2155 if (expected & ToBooleanHint::kNeedsMap) { |
| 2140 __ LoadP(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2156 __ LoadP(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2141 | 2157 |
| 2142 if (expected.CanBeUndetectable()) { | 2158 if (expected & ToBooleanHint::kCanBeUndetectable) { |
| 2143 // Undetectable -> false. | 2159 // Undetectable -> false. |
| 2144 __ tm(FieldMemOperand(map, Map::kBitFieldOffset), | 2160 __ tm(FieldMemOperand(map, Map::kBitFieldOffset), |
| 2145 Operand(1 << Map::kIsUndetectable)); | 2161 Operand(1 << Map::kIsUndetectable)); |
| 2146 __ bne(instr->FalseLabel(chunk_)); | 2162 __ bne(instr->FalseLabel(chunk_)); |
| 2147 } | 2163 } |
| 2148 } | 2164 } |
| 2149 | 2165 |
| 2150 if (expected.Contains(ToBooleanICStub::SPEC_OBJECT)) { | 2166 if (expected & ToBooleanHint::kReceiver) { |
| 2151 // spec object -> true. | 2167 // spec object -> true. |
| 2152 __ CompareInstanceType(map, ip, FIRST_JS_RECEIVER_TYPE); | 2168 __ CompareInstanceType(map, ip, FIRST_JS_RECEIVER_TYPE); |
| 2153 __ bge(instr->TrueLabel(chunk_)); | 2169 __ bge(instr->TrueLabel(chunk_)); |
| 2154 } | 2170 } |
| 2155 | 2171 |
| 2156 if (expected.Contains(ToBooleanICStub::STRING)) { | 2172 if (expected & ToBooleanHint::kString) { |
| 2157 // String value -> false iff empty. | 2173 // String value -> false iff empty. |
| 2158 Label not_string; | 2174 Label not_string; |
| 2159 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | 2175 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
| 2160 __ bge(¬_string, Label::kNear); | 2176 __ bge(¬_string, Label::kNear); |
| 2161 __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2177 __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset)); |
| 2162 __ CmpP(ip, Operand::Zero()); | 2178 __ CmpP(ip, Operand::Zero()); |
| 2163 __ bne(instr->TrueLabel(chunk_)); | 2179 __ bne(instr->TrueLabel(chunk_)); |
| 2164 __ b(instr->FalseLabel(chunk_)); | 2180 __ b(instr->FalseLabel(chunk_)); |
| 2165 __ bind(¬_string); | 2181 __ bind(¬_string); |
| 2166 } | 2182 } |
| 2167 | 2183 |
| 2168 if (expected.Contains(ToBooleanICStub::SYMBOL)) { | 2184 if (expected & ToBooleanHint::kSymbol) { |
| 2169 // Symbol value -> true. | 2185 // Symbol value -> true. |
| 2170 __ CompareInstanceType(map, ip, SYMBOL_TYPE); | 2186 __ CompareInstanceType(map, ip, SYMBOL_TYPE); |
| 2171 __ beq(instr->TrueLabel(chunk_)); | 2187 __ beq(instr->TrueLabel(chunk_)); |
| 2172 } | 2188 } |
| 2173 | 2189 |
| 2174 if (expected.Contains(ToBooleanICStub::SIMD_VALUE)) { | 2190 if (expected & ToBooleanHint::kSimdValue) { |
| 2175 // SIMD value -> true. | 2191 // SIMD value -> true. |
| 2176 Label not_simd; | 2192 Label not_simd; |
| 2177 __ CompareInstanceType(map, ip, SIMD128_VALUE_TYPE); | 2193 __ CompareInstanceType(map, ip, SIMD128_VALUE_TYPE); |
| 2178 __ beq(instr->TrueLabel(chunk_)); | 2194 __ beq(instr->TrueLabel(chunk_)); |
| 2179 } | 2195 } |
| 2180 | 2196 |
| 2181 if (expected.Contains(ToBooleanICStub::HEAP_NUMBER)) { | 2197 if (expected & ToBooleanHint::kHeapNumber) { |
| 2182 // heap number -> false iff +0, -0, or NaN. | 2198 // heap number -> false iff +0, -0, or NaN. |
| 2183 Label not_heap_number; | 2199 Label not_heap_number; |
| 2184 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2200 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
| 2185 __ bne(¬_heap_number, Label::kNear); | 2201 __ bne(¬_heap_number, Label::kNear); |
| 2186 __ LoadDouble(dbl_scratch, | 2202 __ LoadDouble(dbl_scratch, |
| 2187 FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2203 FieldMemOperand(reg, HeapNumber::kValueOffset)); |
| 2188 __ lzdr(kDoubleRegZero); | 2204 __ lzdr(kDoubleRegZero); |
| 2189 __ cdbr(dbl_scratch, kDoubleRegZero); | 2205 __ cdbr(dbl_scratch, kDoubleRegZero); |
| 2190 __ bunordered(instr->FalseLabel(chunk_)); // NaN -> false. | 2206 __ bunordered(instr->FalseLabel(chunk_)); // NaN -> false. |
| 2191 __ beq(instr->FalseLabel(chunk_)); // +0, -0 -> false. | 2207 __ beq(instr->FalseLabel(chunk_)); // +0, -0 -> false. |
| 2192 __ b(instr->TrueLabel(chunk_)); | 2208 __ b(instr->TrueLabel(chunk_)); |
| 2193 __ bind(¬_heap_number); | 2209 __ bind(¬_heap_number); |
| 2194 } | 2210 } |
| 2195 | 2211 |
| 2196 if (!expected.IsGeneric()) { | 2212 if (expected != ToBooleanHint::kAny) { |
| 2197 // We've seen something for the first time -> deopt. | 2213 // We've seen something for the first time -> deopt. |
| 2198 // This can only happen if we are not generic already. | 2214 // This can only happen if we are not generic already. |
| 2199 DeoptimizeIf(al, instr, DeoptimizeReason::kUnexpectedObject); | 2215 DeoptimizeIf(al, instr, DeoptimizeReason::kUnexpectedObject); |
| 2200 } | 2216 } |
| 2201 } | 2217 } |
| 2202 } | 2218 } |
| 2203 } | 2219 } |
| 2204 | 2220 |
| 2205 void LCodeGen::EmitGoto(int block) { | 2221 void LCodeGen::EmitGoto(int block) { |
| 2206 if (!IsNextEmittedBlock(block)) { | 2222 if (!IsNextEmittedBlock(block)) { |
| (...skipping 3333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5540 __ LoadP(result, | 5556 __ LoadP(result, |
| 5541 FieldMemOperand(scratch, FixedArray::kHeaderSize - kPointerSize)); | 5557 FieldMemOperand(scratch, FixedArray::kHeaderSize - kPointerSize)); |
| 5542 __ bind(deferred->exit()); | 5558 __ bind(deferred->exit()); |
| 5543 __ bind(&done); | 5559 __ bind(&done); |
| 5544 } | 5560 } |
| 5545 | 5561 |
| 5546 #undef __ | 5562 #undef __ |
| 5547 | 5563 |
| 5548 } // namespace internal | 5564 } // namespace internal |
| 5549 } // namespace v8 | 5565 } // namespace v8 |
| OLD | NEW |