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 |