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