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/compiler/change-lowering.h" | 5 #include "src/compiler/change-lowering.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/compiler/diamond.h" | 8 #include "src/compiler/diamond.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
11 #include "src/compiler/machine-operator.h" | 11 #include "src/compiler/machine-operator.h" |
| 12 #include "src/compiler/node-properties-inl.h" |
12 | 13 |
13 namespace v8 { | 14 namespace v8 { |
14 namespace internal { | 15 namespace internal { |
15 namespace compiler { | 16 namespace compiler { |
16 | 17 |
17 ChangeLowering::~ChangeLowering() {} | 18 ChangeLowering::~ChangeLowering() {} |
18 | 19 |
19 | 20 |
20 Reduction ChangeLowering::Reduce(Node* node) { | 21 Reduction ChangeLowering::Reduce(Node* node) { |
21 Node* control = graph()->start(); | 22 Node* control = graph()->start(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 Node* effect = graph()->NewNode(common()->ValueEffect(1), value); | 79 Node* effect = graph()->NewNode(common()->ValueEffect(1), value); |
79 Node* heap_number = graph()->NewNode(common()->Call(descriptor), target, | 80 Node* heap_number = graph()->NewNode(common()->Call(descriptor), target, |
80 context, effect, control); | 81 context, effect, control); |
81 Node* store = graph()->NewNode( | 82 Node* store = graph()->NewNode( |
82 machine()->Store(StoreRepresentation(kMachFloat64, kNoWriteBarrier)), | 83 machine()->Store(StoreRepresentation(kMachFloat64, kNoWriteBarrier)), |
83 heap_number, HeapNumberValueIndexConstant(), value, heap_number, control); | 84 heap_number, HeapNumberValueIndexConstant(), value, heap_number, control); |
84 return graph()->NewNode(common()->Finish(1), heap_number, store); | 85 return graph()->NewNode(common()->Finish(1), heap_number, store); |
85 } | 86 } |
86 | 87 |
87 | 88 |
| 89 Node* ChangeLowering::ChangeInt32ToFloat64(Node* value) { |
| 90 return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value); |
| 91 } |
| 92 |
| 93 |
| 94 Node* ChangeLowering::ChangeSmiToFloat64(Node* value) { |
| 95 return ChangeInt32ToFloat64(ChangeSmiToInt32(value)); |
| 96 } |
| 97 |
| 98 |
88 Node* ChangeLowering::ChangeSmiToInt32(Node* value) { | 99 Node* ChangeLowering::ChangeSmiToInt32(Node* value) { |
89 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); | 100 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); |
90 if (machine()->Is64()) { | 101 if (machine()->Is64()) { |
91 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); | 102 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); |
92 } | 103 } |
93 return value; | 104 return value; |
94 } | 105 } |
95 | 106 |
96 | 107 |
| 108 Node* ChangeLowering::ChangeUint32ToFloat64(Node* value) { |
| 109 return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value); |
| 110 } |
| 111 |
| 112 |
| 113 Node* ChangeLowering::ChangeUint32ToSmi(Node* value) { |
| 114 if (machine()->Is64()) { |
| 115 value = graph()->NewNode(machine()->ChangeUint32ToUint64(), value); |
| 116 } |
| 117 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()); |
| 118 } |
| 119 |
| 120 |
97 Node* ChangeLowering::LoadHeapNumberValue(Node* value, Node* control) { | 121 Node* ChangeLowering::LoadHeapNumberValue(Node* value, Node* control) { |
98 return graph()->NewNode(machine()->Load(kMachFloat64), value, | 122 return graph()->NewNode(machine()->Load(kMachFloat64), value, |
99 HeapNumberValueIndexConstant(), graph()->start(), | 123 HeapNumberValueIndexConstant(), graph()->start(), |
100 control); | 124 control); |
101 } | 125 } |
102 | 126 |
103 | 127 |
| 128 Node* ChangeLowering::TestNotSmi(Node* value) { |
| 129 STATIC_ASSERT(kSmiTag == 0); |
| 130 STATIC_ASSERT(kSmiTagMask == 1); |
| 131 return graph()->NewNode(machine()->WordAnd(), value, |
| 132 jsgraph()->IntPtrConstant(kSmiTagMask)); |
| 133 } |
| 134 |
| 135 |
| 136 Node* ChangeLowering::Uint32LessThanOrEqual(Node* lhs, Node* rhs) { |
| 137 return graph()->NewNode(machine()->Uint32LessThanOrEqual(), lhs, rhs); |
| 138 } |
| 139 |
| 140 |
104 Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) { | 141 Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) { |
105 MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged); | 142 MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged); |
106 return Replace(graph()->NewNode(common()->Select(type), val, | 143 return Replace(graph()->NewNode(common()->Select(type), val, |
107 jsgraph()->TrueConstant(), | 144 jsgraph()->TrueConstant(), |
108 jsgraph()->FalseConstant())); | 145 jsgraph()->FalseConstant())); |
109 } | 146 } |
110 | 147 |
111 | 148 |
112 Reduction ChangeLowering::ChangeBoolToBit(Node* val) { | 149 Reduction ChangeLowering::ChangeBoolToBit(Node* val) { |
113 return Replace( | 150 return Replace( |
114 graph()->NewNode(machine()->WordEqual(), val, jsgraph()->TrueConstant())); | 151 graph()->NewNode(machine()->WordEqual(), val, jsgraph()->TrueConstant())); |
115 } | 152 } |
116 | 153 |
117 | 154 |
118 Reduction ChangeLowering::ChangeFloat64ToTagged(Node* val, Node* control) { | 155 Reduction ChangeLowering::ChangeFloat64ToTagged(Node* val, Node* control) { |
119 return Replace(AllocateHeapNumberWithValue(val, control)); | 156 return Replace(AllocateHeapNumberWithValue(val, control)); |
120 } | 157 } |
121 | 158 |
122 | 159 |
123 Reduction ChangeLowering::ChangeInt32ToTagged(Node* val, Node* control) { | 160 Reduction ChangeLowering::ChangeInt32ToTagged(Node* value, Node* control) { |
124 if (machine()->Is64()) { | 161 if (machine()->Is64()) { |
125 return Replace( | 162 return Replace(graph()->NewNode( |
126 graph()->NewNode(machine()->Word64Shl(), | 163 machine()->Word64Shl(), |
127 graph()->NewNode(machine()->ChangeInt32ToInt64(), val), | 164 graph()->NewNode(machine()->ChangeInt32ToInt64(), value), |
128 SmiShiftBitsConstant())); | 165 SmiShiftBitsConstant())); |
129 } | 166 } |
130 | 167 |
131 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), val, val); | 168 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value); |
132 Node* ovf = graph()->NewNode(common()->Projection(1), add); | 169 Node* ovf = graph()->NewNode(common()->Projection(1), add); |
133 | 170 |
134 Diamond d(graph(), common(), ovf, BranchHint::kFalse); | 171 Diamond d(graph(), common(), ovf, BranchHint::kFalse); |
135 d.Chain(control); | 172 d.Chain(control); |
136 Node* heap_number = AllocateHeapNumberWithValue( | 173 return Replace( |
137 graph()->NewNode(machine()->ChangeInt32ToFloat64(), val), d.if_true); | 174 d.Phi(kMachAnyTagged, |
138 Node* smi = graph()->NewNode(common()->Projection(0), add); | 175 AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), d.if_true), |
139 return Replace(d.Phi(kMachAnyTagged, heap_number, smi)); | 176 graph()->NewNode(common()->Projection(0), add))); |
140 } | 177 } |
141 | 178 |
142 | 179 |
143 Reduction ChangeLowering::ChangeTaggedToUI32(Node* val, Node* control, | 180 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control, |
144 Signedness signedness) { | 181 Signedness signedness) { |
145 STATIC_ASSERT(kSmiTag == 0); | 182 const MachineType type = (signedness == kSigned) ? kMachInt32 : kMachUint32; |
146 STATIC_ASSERT(kSmiTagMask == 1); | |
147 | |
148 Node* tag = graph()->NewNode(machine()->WordAnd(), val, | |
149 jsgraph()->IntPtrConstant(kSmiTagMask)); | |
150 | |
151 Diamond d(graph(), common(), tag, BranchHint::kFalse); | |
152 d.Chain(control); | |
153 const Operator* op = (signedness == kSigned) | 183 const Operator* op = (signedness == kSigned) |
154 ? machine()->ChangeFloat64ToInt32() | 184 ? machine()->ChangeFloat64ToInt32() |
155 : machine()->ChangeFloat64ToUint32(); | 185 : machine()->ChangeFloat64ToUint32(); |
156 Node* load = graph()->NewNode(op, LoadHeapNumberValue(val, d.if_true)); | 186 Diamond d(graph(), common(), TestNotSmi(value), BranchHint::kFalse); |
157 Node* number = ChangeSmiToInt32(val); | 187 d.Chain(control); |
158 | |
159 return Replace( | 188 return Replace( |
160 d.Phi((signedness == kSigned) ? kMachInt32 : kMachUint32, load, number)); | 189 d.Phi(type, graph()->NewNode(op, LoadHeapNumberValue(value, d.if_true)), |
| 190 ChangeSmiToInt32(value))); |
161 } | 191 } |
162 | 192 |
163 | 193 |
164 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* val, Node* control) { | 194 namespace { |
165 STATIC_ASSERT(kSmiTag == 0); | |
166 STATIC_ASSERT(kSmiTagMask == 1); | |
167 | 195 |
168 Node* tag = graph()->NewNode(machine()->WordAnd(), val, | 196 bool CanCover(Node* value, IrOpcode::Value opcode) { |
169 jsgraph()->IntPtrConstant(kSmiTagMask)); | 197 if (value->opcode() != opcode) return false; |
170 Diamond d(graph(), common(), tag, BranchHint::kFalse); | 198 bool first = true; |
| 199 for (auto i = value->uses().begin(); i != value->uses().end(); ++i) { |
| 200 if (NodeProperties::IsEffectEdge(i.edge())) continue; |
| 201 DCHECK(NodeProperties::IsValueEdge(i.edge())); |
| 202 if (!first) return false; |
| 203 first = false; |
| 204 } |
| 205 return true; |
| 206 } |
| 207 |
| 208 } // namespace |
| 209 |
| 210 |
| 211 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) { |
| 212 if (CanCover(value, IrOpcode::kJSToNumber)) { |
| 213 // ChangeTaggedToFloat64(JSToNumber(x)) => |
| 214 // if IsSmi(x) then ChangeSmiToFloat64(x) |
| 215 // else let y = JSToNumber(x) in |
| 216 // if IsSmi(y) then ChangeSmiToFloat64(y) |
| 217 // else LoadHeapNumberValue(y) |
| 218 Node* const object = NodeProperties::GetValueInput(value, 0); |
| 219 Node* const context = NodeProperties::GetContextInput(value); |
| 220 Node* const effect = NodeProperties::GetEffectInput(value); |
| 221 Node* const control = NodeProperties::GetControlInput(value); |
| 222 |
| 223 Diamond d1(graph(), common(), TestNotSmi(object), BranchHint::kFalse); |
| 224 d1.Chain(control); |
| 225 |
| 226 Node* number = |
| 227 graph()->NewNode(value->op(), object, context, effect, d1.if_true); |
| 228 Diamond d2(graph(), common(), TestNotSmi(number)); |
| 229 d2.Nest(d1, true); |
| 230 Node* phi2 = d2.Phi(kMachFloat64, LoadHeapNumberValue(number, d2.if_true), |
| 231 ChangeSmiToFloat64(number)); |
| 232 |
| 233 Node* phi1 = d1.Phi(kMachFloat64, phi2, ChangeSmiToFloat64(object)); |
| 234 Node* ephi1 = d1.EffectPhi(number, effect); |
| 235 |
| 236 for (auto i = value->uses().begin(); i != value->uses().end();) { |
| 237 if (NodeProperties::IsEffectEdge(i.edge())) { |
| 238 i.UpdateToAndIncrement(ephi1); |
| 239 } else { |
| 240 ++i; |
| 241 } |
| 242 } |
| 243 return Replace(phi1); |
| 244 } |
| 245 |
| 246 Diamond d(graph(), common(), TestNotSmi(value), BranchHint::kFalse); |
171 d.Chain(control); | 247 d.Chain(control); |
172 Node* load = LoadHeapNumberValue(val, d.if_true); | 248 Node* load = LoadHeapNumberValue(value, d.if_true); |
173 Node* number = graph()->NewNode(machine()->ChangeInt32ToFloat64(), | 249 Node* number = ChangeSmiToFloat64(value); |
174 ChangeSmiToInt32(val)); | |
175 | |
176 return Replace(d.Phi(kMachFloat64, load, number)); | 250 return Replace(d.Phi(kMachFloat64, load, number)); |
177 } | 251 } |
178 | 252 |
179 | 253 |
180 Reduction ChangeLowering::ChangeUint32ToTagged(Node* val, Node* control) { | 254 Reduction ChangeLowering::ChangeUint32ToTagged(Node* value, Node* control) { |
181 STATIC_ASSERT(kSmiTag == 0); | 255 Diamond d(graph(), common(), |
182 STATIC_ASSERT(kSmiTagMask == 1); | 256 Uint32LessThanOrEqual(value, SmiMaxValueConstant()), |
183 | 257 BranchHint::kTrue); |
184 Node* cmp = graph()->NewNode(machine()->Uint32LessThanOrEqual(), val, | |
185 SmiMaxValueConstant()); | |
186 Diamond d(graph(), common(), cmp, BranchHint::kTrue); | |
187 d.Chain(control); | 258 d.Chain(control); |
188 Node* smi = graph()->NewNode( | 259 return Replace(d.Phi( |
189 machine()->WordShl(), | 260 kMachAnyTagged, ChangeUint32ToSmi(value), |
190 machine()->Is64() | 261 AllocateHeapNumberWithValue(ChangeUint32ToFloat64(value), d.if_false))); |
191 ? graph()->NewNode(machine()->ChangeUint32ToUint64(), val) | |
192 : val, | |
193 SmiShiftBitsConstant()); | |
194 | |
195 Node* heap_number = AllocateHeapNumberWithValue( | |
196 graph()->NewNode(machine()->ChangeUint32ToFloat64(), val), d.if_false); | |
197 | |
198 return Replace(d.Phi(kMachAnyTagged, smi, heap_number)); | |
199 } | 262 } |
200 | 263 |
201 | 264 |
202 Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); } | 265 Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); } |
203 | 266 |
204 | 267 |
205 Graph* ChangeLowering::graph() const { return jsgraph()->graph(); } | 268 Graph* ChangeLowering::graph() const { return jsgraph()->graph(); } |
206 | 269 |
207 | 270 |
208 CommonOperatorBuilder* ChangeLowering::common() const { | 271 CommonOperatorBuilder* ChangeLowering::common() const { |
209 return jsgraph()->common(); | 272 return jsgraph()->common(); |
210 } | 273 } |
211 | 274 |
212 | 275 |
213 MachineOperatorBuilder* ChangeLowering::machine() const { | 276 MachineOperatorBuilder* ChangeLowering::machine() const { |
214 return jsgraph()->machine(); | 277 return jsgraph()->machine(); |
215 } | 278 } |
216 | 279 |
217 } // namespace compiler | 280 } // namespace compiler |
218 } // namespace internal | 281 } // namespace internal |
219 } // namespace v8 | 282 } // namespace v8 |
OLD | NEW |