| 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 |