Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(640)

Side by Side Diff: src/compiler/js-typed-lowering.cc

Issue 426233002: Land the Fan (disabled) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "src/compiler/graph-inl.h"
6 #include "src/compiler/js-typed-lowering.h"
7 #include "src/compiler/node-aux-data-inl.h"
8 #include "src/compiler/node-properties-inl.h"
9 #include "src/types.h"
10
11 namespace v8 {
12 namespace internal {
13 namespace compiler {
14
15 // TODO(turbofan): js-typed-lowering improvements possible
16 // - immediately put in type bounds for all new nodes
17 // - relax effects from generic but not-side-effecting operations
18 // - relax effects for ToNumber(mixed)
19
20 // Replace value uses of {node} with {value} and effect uses of {node} with
21 // {effect}. If {effect == NULL}, then use the effect input to {node}.
22 // TODO(titzer): move into a GraphEditor?
23 static void ReplaceUses(Node* node, Node* value, Node* effect) {
24 if (value == effect) {
25 // Effect and value updates are the same; no special iteration needed.
26 if (value != node) node->ReplaceUses(value);
27 return;
28 }
29
30 if (effect == NULL) effect = NodeProperties::GetEffectInput(node);
31
32 // The iteration requires distinguishing between value and effect edges.
33 UseIter iter = node->uses().begin();
34 while (iter != node->uses().end()) {
35 if (NodeProperties::IsEffectEdge(iter.edge())) {
36 iter = iter.UpdateToAndIncrement(effect);
37 } else {
38 iter = iter.UpdateToAndIncrement(value);
39 }
40 }
41 }
42
43
44 // Relax the effects of {node} by immediately replacing effect uses of {node}
45 // with the effect input to {node}.
46 // TODO(turbofan): replace the effect input to {node} with {graph->start()}.
47 // TODO(titzer): move into a GraphEditor?
48 static void RelaxEffects(Node* node) {
49 ReplaceUses(node, node, NULL);
50 }
51
52
53 Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) {
54 ReplaceUses(old, node, node);
55 return Reducer::Changed(node);
56 }
57
58
59 // A helper class to simplify the process of reducing a single binop node with a
60 // JSOperator. This class manages the rewriting of context, control, and effect
61 // dependencies during lowering of a binop and contains numerous helper
62 // functions for matching the types of inputs to an operation.
63 class JSBinopReduction {
64 public:
65 JSBinopReduction(JSTypedLowering* lowering, Node* node)
66 : lowering_(lowering),
67 node_(node),
68 left_type_(NodeProperties::GetBounds(node->InputAt(0)).upper),
69 right_type_(NodeProperties::GetBounds(node->InputAt(1)).upper) {}
70
71 void ConvertInputsToNumber() {
72 node_->ReplaceInput(0, ConvertToNumber(left()));
73 node_->ReplaceInput(1, ConvertToNumber(right()));
74 }
75
76 void ConvertInputsToInt32(bool left_signed, bool right_signed) {
77 node_->ReplaceInput(0, ConvertToI32(left_signed, left()));
78 node_->ReplaceInput(1, ConvertToI32(right_signed, right()));
79 }
80
81 void ConvertInputsToString() {
82 node_->ReplaceInput(0, ConvertToString(left()));
83 node_->ReplaceInput(1, ConvertToString(right()));
84 }
85
86 // Convert inputs for bitwise shift operation (ES5 spec 11.7).
87 void ConvertInputsForShift(bool left_signed) {
88 node_->ReplaceInput(0, ConvertToI32(left_signed, left()));
89 Node* rnum = ConvertToI32(false, right());
90 node_->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rnum,
91 jsgraph()->Int32Constant(0x1F)));
92 }
93
94 void SwapInputs() {
95 Node* l = left();
96 Node* r = right();
97 node_->ReplaceInput(0, r);
98 node_->ReplaceInput(1, l);
99 std::swap(left_type_, right_type_);
100 }
101
102 // Remove all effect and control inputs and outputs to this node and change
103 // to the pure operator {op}, possibly inserting a boolean inversion.
104 Reduction ChangeToPureOperator(Operator* op, bool invert = false) {
105 ASSERT_EQ(0, OperatorProperties::GetEffectInputCount(op));
106 ASSERT_EQ(false, OperatorProperties::HasContextInput(op));
107 ASSERT_EQ(0, OperatorProperties::GetControlInputCount(op));
108 ASSERT_EQ(2, OperatorProperties::GetValueInputCount(op));
109
110 // Remove the effects from the node, if any, and update its effect usages.
111 if (OperatorProperties::GetEffectInputCount(node_->op()) > 0) {
112 RelaxEffects(node_);
113 }
114 // Remove the inputs corresponding to context, effect, and control.
115 NodeProperties::RemoveNonValueInputs(node_);
116 // Finally, update the operator to the new one.
117 node_->set_op(op);
118
119 if (invert) {
120 // Insert an boolean not to invert the value.
121 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
122 node_->ReplaceUses(value);
123 // Note: ReplaceUses() smashes all uses, so smash it back here.
124 value->ReplaceInput(0, node_);
125 return lowering_->ReplaceWith(value);
126 }
127 return lowering_->Changed(node_);
128 }
129
130 bool OneInputIs(Type* t) {
131 return left_type_->Is(t) || right_type_->Is(t);
132 }
133
134 bool BothInputsAre(Type* t) {
135 return left_type_->Is(t) && right_type_->Is(t);
136 }
137
138 bool OneInputCannotBe(Type* t) {
139 return !left_type_->Maybe(t) || !right_type_->Maybe(t);
140 }
141
142 bool NeitherInputCanBe(Type* t) {
143 return !left_type_->Maybe(t) && !right_type_->Maybe(t);
144 }
145
146 Node* effect() {
147 return NodeProperties::GetEffectInput(node_);
148 }
149 Node* control() {
150 return NodeProperties::GetControlInput(node_);
151 }
152 Node* context() {
153 return NodeProperties::GetContextInput(node_);
154 }
155 Node* left() {
156 return NodeProperties::GetValueInput(node_, 0);
157 }
158 Node* right() {
159 return NodeProperties::GetValueInput(node_, 1);
160 }
161 Type* left_type() {
162 return left_type_;
163 }
164 Type* right_type() {
165 return right_type_;
166 }
167
168 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
169 Graph* graph() { return lowering_->graph(); }
170 JSGraph* jsgraph() { return lowering_->jsgraph(); }
171 JSOperatorBuilder* javascript() { return lowering_->javascript(); }
172 MachineOperatorBuilder* machine() { return lowering_->machine(); }
173
174 private:
175 JSTypedLowering* lowering_; // The containing lowering instance.
176 Node* node_; // The original node.
177 Type* left_type_; // Cache of the left input's type.
178 Type* right_type_; // Cache of the right input's type.
179
180 Node* ConvertToString(Node* node) {
181 // Avoid introducing too many eager ToString() operations.
182 Reduction reduced = lowering_->ReduceJSToStringInput(node);
183 if (reduced.Changed()) return reduced.replacement();
184 Node* n = graph()->NewNode(javascript()->ToString(), node, context(),
185 effect(), control());
186 update_effect(n);
187 return n;
188 }
189
190 Node* ConvertToNumber(Node* node) {
191 // Avoid introducing too many eager ToNumber() operations.
192 Reduction reduced = lowering_->ReduceJSToNumberInput(node);
193 if (reduced.Changed()) return reduced.replacement();
194 Node* n = graph()->NewNode(javascript()->ToNumber(), node, context(),
195 effect(), control());
196 update_effect(n);
197 return n;
198 }
199
200 // Try to narrowing a double or number operation to an Int32 operation.
201 bool TryNarrowingToI32(Type* type, Node* node) {
202 switch (node->opcode()) {
203 case IrOpcode::kFloat64Add:
204 case IrOpcode::kNumberAdd: {
205 JSBinopReduction r(lowering_, node);
206 if (r.BothInputsAre(Type::Integral32())) {
207 node->set_op(lowering_->machine()->Int32Add());
208 // TODO(titzer): narrow bounds instead of overwriting.
209 NodeProperties::SetBounds(node, Bounds(type));
210 return true;
211 }
212 }
213 case IrOpcode::kFloat64Sub:
214 case IrOpcode::kNumberSubtract: {
215 JSBinopReduction r(lowering_, node);
216 if (r.BothInputsAre(Type::Integral32())) {
217 node->set_op(lowering_->machine()->Int32Sub());
218 // TODO(titzer): narrow bounds instead of overwriting.
219 NodeProperties::SetBounds(node, Bounds(type));
220 return true;
221 }
222 }
223 default:
224 return false;
225 }
226 }
227
228 Node* ConvertToI32(bool is_signed, Node* node) {
229 Type* type = is_signed ? Type::Signed32() : Type::Unsigned32();
230 if (node->OwnedBy(node_)) {
231 // If this node {node_} has the only edge to {node}, then try narrowing
232 // its operation to an Int32 add or subtract.
233 if (TryNarrowingToI32(type, node)) return node;
234 } else {
235 // Otherwise, {node} has multiple uses. Leave it as is and let the
236 // further lowering passes deal with it, which use a full backwards
237 // fixpoint.
238 }
239
240 // Avoid introducing too many eager NumberToXXnt32() operations.
241 node = ConvertToNumber(node);
242 Type* input_type = NodeProperties::GetBounds(node).upper;
243
244 if (input_type->Is(type)) return node; // already in the value range.
245
246 Operator* op = is_signed ? simplified()->NumberToInt32()
247 : simplified()->NumberToUint32();
248 Node* n = graph()->NewNode(op, node);
249 return n;
250 }
251
252 void update_effect(Node* effect) {
253 NodeProperties::ReplaceEffectInput(node_, effect);
254 }
255 };
256
257
258 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
259 JSBinopReduction r(this, node);
260 if (r.OneInputIs(Type::String())) {
261 r.ConvertInputsToString();
262 return r.ChangeToPureOperator(simplified()->StringAdd());
263 } else if (r.NeitherInputCanBe(Type::String())) {
264 r.ConvertInputsToNumber();
265 return r.ChangeToPureOperator(simplified()->NumberAdd());
266 }
267 return NoChange();
268 }
269
270
271 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, Operator* numberOp) {
272 JSBinopReduction r(this, node);
273 if (r.OneInputIs(Type::Primitive())) {
274 // If at least one input is a primitive, then insert appropriate conversions
275 // to number and reduce this operator to the given numeric one.
276 // TODO(turbofan): make this heuristic configurable for code size.
277 r.ConvertInputsToNumber();
278 return r.ChangeToPureOperator(numberOp);
279 }
280 // TODO(turbofan): relax/remove the effects of this operator in other cases.
281 return NoChange();
282 }
283
284
285 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed,
286 bool right_signed, Operator* intOp) {
287 JSBinopReduction r(this, node);
288 // TODO(titzer): some Smi bitwise operations don't really require going
289 // all the way to int32, which can save tagging/untagging for some operations
290 // on some platforms.
291 // TODO(turbofan): make this heuristic configurable for code size.
292 r.ConvertInputsToInt32(left_signed, right_signed);
293 return r.ChangeToPureOperator(intOp);
294 }
295
296
297 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed,
298 Operator* shift_op) {
299 JSBinopReduction r(this, node);
300 r.ConvertInputsForShift(left_signed);
301 return r.ChangeToPureOperator(shift_op);
302 }
303
304
305 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
306 JSBinopReduction r(this, node);
307 if (r.BothInputsAre(Type::String())) {
308 // If both inputs are definitely strings, perform a string comparison.
309 Operator* stringOp;
310 switch (node->opcode()) {
311 case IrOpcode::kJSLessThan:
312 stringOp = simplified()->StringLessThan();
313 break;
314 case IrOpcode::kJSGreaterThan:
315 stringOp = simplified()->StringLessThan();
316 r.SwapInputs(); // a > b => b < a
317 break;
318 case IrOpcode::kJSLessThanOrEqual:
319 stringOp = simplified()->StringLessThanOrEqual();
320 break;
321 case IrOpcode::kJSGreaterThanOrEqual:
322 stringOp = simplified()->StringLessThanOrEqual();
323 r.SwapInputs(); // a >= b => b <= a
324 break;
325 default:
326 return NoChange();
327 }
328 return r.ChangeToPureOperator(stringOp);
329 } else if (r.OneInputCannotBe(Type::String())) {
330 // If one input cannot be a string, then emit a number comparison.
331 Operator* less_than;
332 Operator* less_than_or_equal;
333 if (r.BothInputsAre(Type::Unsigned32())) {
334 less_than = machine()->Uint32LessThan();
335 less_than_or_equal = machine()->Uint32LessThanOrEqual();
336 } else if (r.BothInputsAre(Type::Signed32())) {
337 less_than = machine()->Int32LessThan();
338 less_than_or_equal = machine()->Int32LessThanOrEqual();
339 } else {
340 // TODO(turbofan): mixed signed/unsigned int32 comparisons.
341 r.ConvertInputsToNumber();
342 less_than = simplified()->NumberLessThan();
343 less_than_or_equal = simplified()->NumberLessThanOrEqual();
344 }
345 Operator* comparison;
346 switch (node->opcode()) {
347 case IrOpcode::kJSLessThan:
348 comparison = less_than;
349 break;
350 case IrOpcode::kJSGreaterThan:
351 comparison = less_than;
352 r.SwapInputs(); // a > b => b < a
353 break;
354 case IrOpcode::kJSLessThanOrEqual:
355 comparison = less_than_or_equal;
356 break;
357 case IrOpcode::kJSGreaterThanOrEqual:
358 comparison = less_than_or_equal;
359 r.SwapInputs(); // a >= b => b <= a
360 break;
361 default:
362 return NoChange();
363 }
364 return r.ChangeToPureOperator(comparison);
365 }
366 // TODO(turbofan): relax/remove effects of this operator in other cases.
367 return NoChange(); // Keep a generic comparison.
368 }
369
370
371 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
372 JSBinopReduction r(this, node);
373
374 if (r.BothInputsAre(Type::Number())) {
375 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
376 }
377 if (r.BothInputsAre(Type::String())) {
378 return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
379 }
380 if (r.BothInputsAre(Type::Receiver())) {
381 return r.ChangeToPureOperator(
382 simplified()->ReferenceEqual(Type::Receiver()), invert);
383 }
384 // TODO(turbofan): js-typed-lowering of Equal(undefined)
385 // TODO(turbofan): js-typed-lowering of Equal(null)
386 // TODO(turbofan): js-typed-lowering of Equal(boolean)
387 return NoChange();
388 }
389
390
391 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
392 JSBinopReduction r(this, node);
393 if (r.left() == r.right()) {
394 // x === x is always true if x != NaN
395 if (!r.left_type()->Maybe(Type::NaN())) {
396 return ReplaceEagerly(node, invert ? jsgraph()->FalseConstant()
397 : jsgraph()->TrueConstant());
398 }
399 }
400 if (!r.left_type()->Maybe(r.right_type())) {
401 // Type intersection is empty; === is always false unless both
402 // inputs could be strings (one internalized and one not).
403 if (r.OneInputCannotBe(Type::String())) {
404 return ReplaceEagerly(node, invert ? jsgraph()->TrueConstant()
405 : jsgraph()->FalseConstant());
406 }
407 }
408 if (r.OneInputIs(Type::Undefined())) {
409 return r.ChangeToPureOperator(
410 simplified()->ReferenceEqual(Type::Undefined()), invert);
411 }
412 if (r.OneInputIs(Type::Null())) {
413 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()),
414 invert);
415 }
416 if (r.OneInputIs(Type::Boolean())) {
417 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
418 invert);
419 }
420 if (r.OneInputIs(Type::Object())) {
421 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Object()),
422 invert);
423 }
424 if (r.OneInputIs(Type::Receiver())) {
425 return r.ChangeToPureOperator(
426 simplified()->ReferenceEqual(Type::Receiver()), invert);
427 }
428 if (r.BothInputsAre(Type::String())) {
429 return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
430 }
431 if (r.BothInputsAre(Type::Number())) {
432 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
433 }
434 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
435 return NoChange();
436 }
437
438
439 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
440 if (input->opcode() == IrOpcode::kJSToNumber) {
441 // Recursively try to reduce the input first.
442 Reduction result = ReduceJSToNumberInput(input->InputAt(0));
443 if (result.Changed()) {
444 RelaxEffects(input);
445 return result;
446 }
447 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x)
448 }
449 Type* input_type = NodeProperties::GetBounds(input).upper;
450 if (input_type->Is(Type::Number())) {
451 // JSToNumber(number) => x
452 return Changed(input);
453 }
454 if (input_type->Is(Type::Undefined())) {
455 // JSToNumber(undefined) => #NaN
456 return ReplaceWith(jsgraph()->NaNConstant());
457 }
458 if (input_type->Is(Type::Null())) {
459 // JSToNumber(null) => #0
460 return ReplaceWith(jsgraph()->ZeroConstant());
461 }
462 // TODO(turbofan): js-typed-lowering of ToNumber(boolean)
463 // TODO(turbofan): js-typed-lowering of ToNumber(string)
464 return NoChange();
465 }
466
467
468 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
469 if (input->opcode() == IrOpcode::kJSToString) {
470 // Recursively try to reduce the input first.
471 Reduction result = ReduceJSToStringInput(input->InputAt(0));
472 if (result.Changed()) {
473 RelaxEffects(input);
474 return result;
475 }
476 return Changed(input); // JSToString(JSToString(x)) => JSToString(x)
477 }
478 Type* input_type = NodeProperties::GetBounds(input).upper;
479 if (input_type->Is(Type::String())) {
480 return Changed(input); // JSToString(string) => x
481 }
482 if (input_type->Is(Type::Undefined())) {
483 return ReplaceWith(jsgraph()->HeapConstant(
484 graph()->zone()->isolate()->factory()->undefined_string()));
485 }
486 if (input_type->Is(Type::Null())) {
487 return ReplaceWith(jsgraph()->HeapConstant(
488 graph()->zone()->isolate()->factory()->null_string()));
489 }
490 // TODO(turbofan): js-typed-lowering of ToString(boolean)
491 // TODO(turbofan): js-typed-lowering of ToString(number)
492 return NoChange();
493 }
494
495
496 Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) {
497 if (input->opcode() == IrOpcode::kJSToBoolean) {
498 // Recursively try to reduce the input first.
499 Reduction result = ReduceJSToBooleanInput(input->InputAt(0));
500 if (result.Changed()) {
501 RelaxEffects(input);
502 return result;
503 }
504 return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x)
505 }
506 Type* input_type = NodeProperties::GetBounds(input).upper;
507 if (input_type->Is(Type::Boolean())) {
508 return Changed(input); // JSToBoolean(boolean) => x
509 }
510 if (input_type->Is(Type::Undefined())) {
511 // JSToBoolean(undefined) => #false
512 return ReplaceWith(jsgraph()->FalseConstant());
513 }
514 if (input_type->Is(Type::Null())) {
515 // JSToBoolean(null) => #false
516 return ReplaceWith(jsgraph()->FalseConstant());
517 }
518 if (input_type->Is(Type::DetectableReceiver())) {
519 // JSToBoolean(detectable) => #true
520 return ReplaceWith(jsgraph()->TrueConstant());
521 }
522 if (input_type->Is(Type::Undetectable())) {
523 // JSToBoolean(undetectable) => #false
524 return ReplaceWith(jsgraph()->FalseConstant());
525 }
526 if (input_type->Is(Type::Number())) {
527 // JSToBoolean(number) => BooleanNot(NumberEqual(x, #0))
528 Node* cmp = graph()->NewNode(simplified()->NumberEqual(), input,
529 jsgraph()->ZeroConstant());
530 Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
531 ReplaceEagerly(input, inv);
532 // TODO(titzer): Ugly. ReplaceEagerly smashes all uses. Smash it back here.
533 cmp->ReplaceInput(0, input);
534 return Changed(inv);
535 }
536 // TODO(turbofan): js-typed-lowering of ToBoolean(string)
537 return NoChange();
538 }
539
540
541 static Reduction ReplaceWithReduction(Node* node, Reduction reduction) {
542 if (reduction.Changed()) {
543 ReplaceUses(node, reduction.replacement(), NULL);
544 return reduction;
545 }
546 return Reducer::NoChange();
547 }
548
549
550 Reduction JSTypedLowering::Reduce(Node* node) {
551 switch (node->opcode()) {
552 case IrOpcode::kJSEqual:
553 return ReduceJSEqual(node, false);
554 case IrOpcode::kJSNotEqual:
555 return ReduceJSEqual(node, true);
556 case IrOpcode::kJSStrictEqual:
557 return ReduceJSStrictEqual(node, false);
558 case IrOpcode::kJSStrictNotEqual:
559 return ReduceJSStrictEqual(node, true);
560 case IrOpcode::kJSLessThan: // fall through
561 case IrOpcode::kJSGreaterThan: // fall through
562 case IrOpcode::kJSLessThanOrEqual: // fall through
563 case IrOpcode::kJSGreaterThanOrEqual:
564 return ReduceJSComparison(node);
565 case IrOpcode::kJSBitwiseOr:
566 return ReduceI32Binop(node, true, true, machine()->Word32Or());
567 case IrOpcode::kJSBitwiseXor:
568 return ReduceI32Binop(node, true, true, machine()->Word32Xor());
569 case IrOpcode::kJSBitwiseAnd:
570 return ReduceI32Binop(node, true, true, machine()->Word32And());
571 case IrOpcode::kJSShiftLeft:
572 return ReduceI32Shift(node, true, machine()->Word32Shl());
573 case IrOpcode::kJSShiftRight:
574 return ReduceI32Shift(node, true, machine()->Word32Sar());
575 case IrOpcode::kJSShiftRightLogical:
576 return ReduceI32Shift(node, false, machine()->Word32Shr());
577 case IrOpcode::kJSAdd:
578 return ReduceJSAdd(node);
579 case IrOpcode::kJSSubtract:
580 return ReduceNumberBinop(node, simplified()->NumberSubtract());
581 case IrOpcode::kJSMultiply:
582 return ReduceNumberBinop(node, simplified()->NumberMultiply());
583 case IrOpcode::kJSDivide:
584 return ReduceNumberBinop(node, simplified()->NumberDivide());
585 case IrOpcode::kJSModulus:
586 return ReduceNumberBinop(node, simplified()->NumberModulus());
587 case IrOpcode::kJSUnaryNot: {
588 Reduction result = ReduceJSToBooleanInput(node->InputAt(0));
589 Node* value;
590 if (result.Changed()) {
591 // !x => BooleanNot(x)
592 value =
593 graph()->NewNode(simplified()->BooleanNot(), result.replacement());
594 ReplaceUses(node, value, NULL);
595 return Changed(value);
596 } else {
597 // !x => BooleanNot(JSToBoolean(x))
598 value = graph()->NewNode(simplified()->BooleanNot(), node);
599 node->set_op(javascript()->ToBoolean());
600 ReplaceUses(node, value, node);
601 // Note: ReplaceUses() smashes all uses, so smash it back here.
602 value->ReplaceInput(0, node);
603 return ReplaceWith(value);
604 }
605 }
606 case IrOpcode::kJSToBoolean:
607 return ReplaceWithReduction(node,
608 ReduceJSToBooleanInput(node->InputAt(0)));
609 case IrOpcode::kJSToNumber:
610 return ReplaceWithReduction(node,
611 ReduceJSToNumberInput(node->InputAt(0)));
612 case IrOpcode::kJSToString:
613 return ReplaceWithReduction(node,
614 ReduceJSToStringInput(node->InputAt(0)));
615 default: break;
616 }
617 return NoChange();
618 }
619
620 } } } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/linkage.h » ('j') | src/lithium-inl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698