| 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/access-builder.h" | 5 #include "src/compiler/access-builder.h" |
| 6 #include "src/compiler/graph-inl.h" | 6 #include "src/compiler/graph-inl.h" |
| 7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
| 8 #include "src/compiler/js-typed-lowering.h" | 8 #include "src/compiler/js-typed-lowering.h" |
| 9 #include "src/compiler/node-aux-data-inl.h" | 9 #include "src/compiler/node-aux-data-inl.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 // TODO(titzer): move into a GraphEditor? | 26 // TODO(titzer): move into a GraphEditor? |
| 27 static void RelaxEffects(Node* node) { | 27 static void RelaxEffects(Node* node) { |
| 28 NodeProperties::ReplaceWithValue(node, node, NULL); | 28 NodeProperties::ReplaceWithValue(node, node, NULL); |
| 29 } | 29 } |
| 30 | 30 |
| 31 | 31 |
| 32 JSTypedLowering::JSTypedLowering(JSGraph* jsgraph, Zone* zone) | 32 JSTypedLowering::JSTypedLowering(JSGraph* jsgraph, Zone* zone) |
| 33 : jsgraph_(jsgraph), simplified_(graph()->zone()), conversions_(zone) { | 33 : jsgraph_(jsgraph), simplified_(graph()->zone()), conversions_(zone) { |
| 34 Handle<Object> zero = factory()->NewNumber(0.0); | 34 Handle<Object> zero = factory()->NewNumber(0.0); |
| 35 Handle<Object> one = factory()->NewNumber(1.0); | 35 Handle<Object> one = factory()->NewNumber(1.0); |
| 36 zero_range_ = Type::Range(zero, zero, graph()->zone()); | 36 zero_range_ = Type::Range(zero, zero, zone); |
| 37 one_range_ = Type::Range(one, one, graph()->zone()); | 37 one_range_ = Type::Range(one, one, zone); |
| 38 zero_one_range_ = Type::Range(zero, one, zone); |
| 38 Handle<Object> thirtyone = factory()->NewNumber(31.0); | 39 Handle<Object> thirtyone = factory()->NewNumber(31.0); |
| 39 zero_thirtyone_range_ = Type::Range(zero, thirtyone, graph()->zone()); | 40 zero_thirtyone_range_ = Type::Range(zero, thirtyone, zone); |
| 40 // TODO(jarin): Can we have a correctification of the stupid type system? | 41 // TODO(jarin): Can we have a correctification of the stupid type system? |
| 41 // These stupid work-arounds are just stupid! | 42 // These stupid work-arounds are just stupid! |
| 42 shifted_int32_ranges_[0] = Type::Signed32(); | 43 shifted_int32_ranges_[0] = Type::Signed32(); |
| 43 if (SmiValuesAre31Bits()) { | 44 if (SmiValuesAre31Bits()) { |
| 44 shifted_int32_ranges_[1] = Type::SignedSmall(); | 45 shifted_int32_ranges_[1] = Type::SignedSmall(); |
| 45 for (size_t k = 2; k < arraysize(shifted_int32_ranges_); ++k) { | 46 for (size_t k = 2; k < arraysize(shifted_int32_ranges_); ++k) { |
| 46 Handle<Object> min = factory()->NewNumber(kMinInt / (1 << k)); | 47 Handle<Object> min = factory()->NewNumber(kMinInt / (1 << k)); |
| 47 Handle<Object> max = factory()->NewNumber(kMaxInt / (1 << k)); | 48 Handle<Object> max = factory()->NewNumber(kMaxInt / (1 << k)); |
| 48 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); | 49 shifted_int32_ranges_[k] = Type::Range(min, max, zone); |
| 49 } | 50 } |
| 50 } else { | 51 } else { |
| 51 for (size_t k = 1; k < arraysize(shifted_int32_ranges_); ++k) { | 52 for (size_t k = 1; k < arraysize(shifted_int32_ranges_); ++k) { |
| 52 Handle<Object> min = factory()->NewNumber(kMinInt / (1 << k)); | 53 Handle<Object> min = factory()->NewNumber(kMinInt / (1 << k)); |
| 53 Handle<Object> max = factory()->NewNumber(kMaxInt / (1 << k)); | 54 Handle<Object> max = factory()->NewNumber(kMaxInt / (1 << k)); |
| 54 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); | 55 shifted_int32_ranges_[k] = Type::Range(min, max, zone); |
| 55 } | 56 } |
| 56 } | 57 } |
| 57 } | 58 } |
| 58 | 59 |
| 59 | 60 |
| 60 Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) { | 61 Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) { |
| 61 NodeProperties::ReplaceWithValue(old, node, node); | 62 NodeProperties::ReplaceWithValue(old, node, node); |
| 62 return Changed(node); | 63 return Changed(node); |
| 63 } | 64 } |
| 64 | 65 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 } | 105 } |
| 105 | 106 |
| 106 void SwapInputs() { | 107 void SwapInputs() { |
| 107 Node* l = left(); | 108 Node* l = left(); |
| 108 Node* r = right(); | 109 Node* r = right(); |
| 109 node_->ReplaceInput(0, r); | 110 node_->ReplaceInput(0, r); |
| 110 node_->ReplaceInput(1, l); | 111 node_->ReplaceInput(1, l); |
| 111 std::swap(left_type_, right_type_); | 112 std::swap(left_type_, right_type_); |
| 112 } | 113 } |
| 113 | 114 |
| 115 void ReplaceLeftInput(Node* l) { |
| 116 node_->ReplaceInput(0, l); |
| 117 left_type_ = NodeProperties::GetBounds(l).upper; |
| 118 } |
| 119 |
| 114 // Remove all effect and control inputs and outputs to this node and change | 120 // Remove all effect and control inputs and outputs to this node and change |
| 115 // to the pure operator {op}, possibly inserting a boolean inversion. | 121 // to the pure operator {op}, possibly inserting a boolean inversion. |
| 116 Reduction ChangeToPureOperator(const Operator* op, bool invert = false, | 122 Reduction ChangeToPureOperator(const Operator* op, bool invert = false, |
| 117 Type* type = Type::Any()) { | 123 Type* type = Type::Any()) { |
| 118 DCHECK_EQ(0, op->EffectInputCount()); | 124 DCHECK_EQ(0, op->EffectInputCount()); |
| 119 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); | 125 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
| 120 DCHECK_EQ(0, op->ControlInputCount()); | 126 DCHECK_EQ(0, op->ControlInputCount()); |
| 121 DCHECK_EQ(2, op->ValueInputCount()); | 127 DCHECK_LE(1, op->ValueInputCount()); |
| 128 DCHECK_GE(2, op->ValueInputCount()); |
| 122 | 129 |
| 123 // Remove the effects from the node, if any, and update its effect usages. | 130 // Remove the effects from the node, if any, and update its effect usages. |
| 124 if (node_->op()->EffectInputCount() > 0) { | 131 if (node_->op()->EffectInputCount() > 0) { |
| 125 RelaxEffects(node_); | 132 RelaxEffects(node_); |
| 126 } | 133 } |
| 134 // Finally, update the operator to the new one. |
| 135 node_->set_op(op); |
| 127 // Remove the inputs corresponding to context, effect, and control. | 136 // Remove the inputs corresponding to context, effect, and control. |
| 128 NodeProperties::RemoveNonValueInputs(node_); | 137 NodeProperties::RemoveNonValueInputs(node_); |
| 129 // Finally, update the operator to the new one. | |
| 130 node_->set_op(op); | |
| 131 | 138 |
| 132 // TODO(jarin): Replace the explicit typing hack with a call to some method | 139 // TODO(jarin): Replace the explicit typing hack with a call to some method |
| 133 // that encapsulates changing the operator and re-typing. | 140 // that encapsulates changing the operator and re-typing. |
| 134 Bounds const bounds = NodeProperties::GetBounds(node_); | 141 Bounds const bounds = NodeProperties::GetBounds(node_); |
| 135 NodeProperties::SetBounds(node_, Bounds::NarrowUpper(bounds, type, zone())); | 142 NodeProperties::SetBounds(node_, Bounds::NarrowUpper(bounds, type, zone())); |
| 136 | 143 |
| 137 if (invert) { | 144 if (invert) { |
| 138 // Insert an boolean not to invert the value. | 145 // Insert an boolean not to invert the value. |
| 139 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); | 146 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); |
| 140 node_->ReplaceUses(value); | 147 node_->ReplaceUses(value); |
| 141 // Note: ReplaceUses() smashes all uses, so smash it back here. | 148 // Note: ReplaceUses() smashes all uses, so smash it back here. |
| 142 value->ReplaceInput(0, node_); | 149 value->ReplaceInput(0, node_); |
| 143 return lowering_->Replace(value); | 150 return lowering_->Replace(value); |
| 144 } | 151 } |
| 145 return lowering_->Changed(node_); | 152 return lowering_->Changed(node_); |
| 146 } | 153 } |
| 147 | 154 |
| 148 Reduction ChangeToPureOperator(const Operator* op, Type* type) { | 155 Reduction ChangeToPureOperator(const Operator* op, Type* type) { |
| 149 return ChangeToPureOperator(op, false, type); | 156 return ChangeToPureOperator(op, false, type); |
| 150 } | 157 } |
| 151 | 158 |
| 152 bool OneInputIs(Type* t) { return left_type_->Is(t) || right_type_->Is(t); } | 159 Reduction ReplaceWithLeftInput() { |
| 160 // Remove the effects from the node, if any, and update its effect usages. |
| 161 if (node_->op()->EffectInputCount() > 0) { |
| 162 RelaxEffects(node_); |
| 163 } |
| 164 return lowering_->Replace(left()); |
| 165 } |
| 153 | 166 |
| 154 bool BothInputsAre(Type* t) { | 167 bool LeftInputIs(Type* t) { return left_type_->Is(t); } |
| 155 return left_type_->Is(t) && right_type_->Is(t); | 168 bool RightInputIs(Type* t) { return right_type_->Is(t); } |
| 156 } | 169 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } |
| 170 bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); } |
| 157 | 171 |
| 158 bool OneInputCannotBe(Type* t) { | 172 bool OneInputCannotBe(Type* t) { |
| 159 return !left_type_->Maybe(t) || !right_type_->Maybe(t); | 173 return !left_type_->Maybe(t) || !right_type_->Maybe(t); |
| 160 } | 174 } |
| 161 | 175 |
| 162 bool NeitherInputCanBe(Type* t) { | 176 bool NeitherInputCanBe(Type* t) { |
| 163 return !left_type_->Maybe(t) && !right_type_->Maybe(t); | 177 return !left_type_->Maybe(t) && !right_type_->Maybe(t); |
| 164 } | 178 } |
| 165 | 179 |
| 166 Node* effect() { return NodeProperties::GetEffectInput(node_); } | 180 Node* effect() { return NodeProperties::GetEffectInput(node_); } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 // JSAdd(x:string, y) => StringAdd(x, ToString(y)) | 272 // JSAdd(x:string, y) => StringAdd(x, ToString(y)) |
| 259 // JSAdd(x, y:string) => StringAdd(ToString(x), y) | 273 // JSAdd(x, y:string) => StringAdd(ToString(x), y) |
| 260 r.ConvertInputsToString(); | 274 r.ConvertInputsToString(); |
| 261 return r.ChangeToPureOperator(simplified()->StringAdd()); | 275 return r.ChangeToPureOperator(simplified()->StringAdd()); |
| 262 } | 276 } |
| 263 #endif | 277 #endif |
| 264 return NoChange(); | 278 return NoChange(); |
| 265 } | 279 } |
| 266 | 280 |
| 267 | 281 |
| 282 Reduction JSTypedLowering::ReduceJSBitwiseAnd(Node* node) { |
| 283 JSBinopReduction r(this, node); |
| 284 if (r.LeftInputIs(one_range_)) { |
| 285 if (r.RightInputIs(zero_one_range_)) { |
| 286 // JSBitwiseAnd(1, x:[0,1]) => x |
| 287 r.SwapInputs(); |
| 288 return r.ReplaceWithLeftInput(); |
| 289 } else if (r.RightInputIs(Type::Boolean())) { |
| 290 // JSBitwiseAnd(1, x:boolean) => BooleanToNumber(x) |
| 291 r.SwapInputs(); |
| 292 return r.ChangeToPureOperator(simplified()->BooleanToNumber()); |
| 293 } |
| 294 } |
| 295 if (r.RightInputIs(one_range_)) { |
| 296 if (r.LeftInputIs(zero_one_range_)) { |
| 297 // JSBitwiseAnd(x:[0,1], 1) => x |
| 298 return r.ReplaceWithLeftInput(); |
| 299 } else if (r.LeftInputIs(Type::Boolean())) { |
| 300 // JSBitwiseAnd(x:boolean, 1) => BooleanToNumber(x) |
| 301 return r.ChangeToPureOperator(simplified()->BooleanToNumber()); |
| 302 } |
| 303 } |
| 304 if (r.BothInputsAre(Type::Primitive())) { |
| 305 // TODO(titzer): some Smi bitwise operations don't really require going |
| 306 // all the way to int32, which can save tagging/untagging for some |
| 307 // operations |
| 308 // on some platforms. |
| 309 // TODO(turbofan): make this heuristic configurable for code size. |
| 310 r.ConvertInputsToUI32(kSigned, kSigned); |
| 311 return r.ChangeToPureOperator(machine()->Word32And(), Type::Integral32()); |
| 312 } |
| 313 return NoChange(); |
| 314 } |
| 315 |
| 316 |
| 268 Reduction JSTypedLowering::ReduceJSBitwiseOr(Node* node) { | 317 Reduction JSTypedLowering::ReduceJSBitwiseOr(Node* node) { |
| 269 JSBinopReduction r(this, node); | 318 JSBinopReduction r(this, node); |
| 270 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(zero_range_)) { | 319 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(zero_range_)) { |
| 271 // TODO(jarin): Propagate frame state input from non-primitive input node to | 320 // TODO(jarin): Propagate frame state input from non-primitive input node to |
| 272 // JSToNumber node. | 321 // JSToNumber node. |
| 273 // TODO(titzer): some Smi bitwise operations don't really require going | 322 // TODO(titzer): some Smi bitwise operations don't really require going |
| 274 // all the way to int32, which can save tagging/untagging for some | 323 // all the way to int32, which can save tagging/untagging for some |
| 275 // operations | 324 // operations |
| 276 // on some platforms. | 325 // on some platforms. |
| 277 // TODO(turbofan): make this heuristic configurable for code size. | 326 // TODO(turbofan): make this heuristic configurable for code size. |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 case IrOpcode::kJSLessThan: // fall through | 929 case IrOpcode::kJSLessThan: // fall through |
| 881 case IrOpcode::kJSGreaterThan: // fall through | 930 case IrOpcode::kJSGreaterThan: // fall through |
| 882 case IrOpcode::kJSLessThanOrEqual: // fall through | 931 case IrOpcode::kJSLessThanOrEqual: // fall through |
| 883 case IrOpcode::kJSGreaterThanOrEqual: | 932 case IrOpcode::kJSGreaterThanOrEqual: |
| 884 return ReduceJSComparison(node); | 933 return ReduceJSComparison(node); |
| 885 case IrOpcode::kJSBitwiseOr: | 934 case IrOpcode::kJSBitwiseOr: |
| 886 return ReduceJSBitwiseOr(node); | 935 return ReduceJSBitwiseOr(node); |
| 887 case IrOpcode::kJSBitwiseXor: | 936 case IrOpcode::kJSBitwiseXor: |
| 888 return ReduceInt32Binop(node, machine()->Word32Xor()); | 937 return ReduceInt32Binop(node, machine()->Word32Xor()); |
| 889 case IrOpcode::kJSBitwiseAnd: | 938 case IrOpcode::kJSBitwiseAnd: |
| 890 return ReduceInt32Binop(node, machine()->Word32And()); | 939 return ReduceJSBitwiseAnd(node); |
| 891 case IrOpcode::kJSShiftLeft: | 940 case IrOpcode::kJSShiftLeft: |
| 892 return ReduceUI32Shift(node, kSigned, machine()->Word32Shl()); | 941 return ReduceUI32Shift(node, kSigned, machine()->Word32Shl()); |
| 893 case IrOpcode::kJSShiftRight: | 942 case IrOpcode::kJSShiftRight: |
| 894 return ReduceUI32Shift(node, kSigned, machine()->Word32Sar()); | 943 return ReduceUI32Shift(node, kSigned, machine()->Word32Sar()); |
| 895 case IrOpcode::kJSShiftRightLogical: | 944 case IrOpcode::kJSShiftRightLogical: |
| 896 return ReduceUI32Shift(node, kUnsigned, machine()->Word32Shr()); | 945 return ReduceUI32Shift(node, kUnsigned, machine()->Word32Shr()); |
| 897 case IrOpcode::kJSAdd: | 946 case IrOpcode::kJSAdd: |
| 898 return ReduceJSAdd(node); | 947 return ReduceJSAdd(node); |
| 899 case IrOpcode::kJSSubtract: | 948 case IrOpcode::kJSSubtract: |
| 900 return ReduceNumberBinop(node, simplified()->NumberSubtract()); | 949 return ReduceNumberBinop(node, simplified()->NumberSubtract()); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 986 } | 1035 } |
| 987 | 1036 |
| 988 | 1037 |
| 989 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1038 MachineOperatorBuilder* JSTypedLowering::machine() const { |
| 990 return jsgraph()->machine(); | 1039 return jsgraph()->machine(); |
| 991 } | 1040 } |
| 992 | 1041 |
| 993 } // namespace compiler | 1042 } // namespace compiler |
| 994 } // namespace internal | 1043 } // namespace internal |
| 995 } // namespace v8 | 1044 } // namespace v8 |
| OLD | NEW |