| 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 11 matching lines...) Expand all Loading... |
| 22 | 22 |
| 23 // Relax the effects of {node} by immediately replacing effect uses of {node} | 23 // Relax the effects of {node} by immediately replacing effect uses of {node} |
| 24 // with the effect input to {node}. | 24 // with the effect input to {node}. |
| 25 // TODO(turbofan): replace the effect input to {node} with {graph->start()}. | 25 // TODO(turbofan): replace the effect input to {node} with {graph->start()}. |
| 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) | 32 JSTypedLowering::JSTypedLowering(JSGraph* jsgraph, Zone* zone) |
| 33 : jsgraph_(jsgraph), simplified_(jsgraph->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, graph()->zone()); |
| 37 one_range_ = Type::Range(one, one, graph()->zone()); | 37 one_range_ = Type::Range(one, one, graph()->zone()); |
| 38 Handle<Object> thirtyone = factory()->NewNumber(31.0); | 38 Handle<Object> thirtyone = factory()->NewNumber(31.0); |
| 39 zero_thirtyone_range_ = Type::Range(zero, thirtyone, graph()->zone()); | 39 zero_thirtyone_range_ = Type::Range(zero, thirtyone, graph()->zone()); |
| 40 // 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? |
| 41 // These stupid work-arounds are just stupid! | 41 // These stupid work-arounds are just stupid! |
| 42 shifted_int32_ranges_[0] = Type::Signed32(); | 42 shifted_int32_ranges_[0] = Type::Signed32(); |
| 43 if (SmiValuesAre31Bits()) { | 43 if (SmiValuesAre31Bits()) { |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 // Avoid introducing too many eager ToString() operations. | 188 // Avoid introducing too many eager ToString() operations. |
| 189 Reduction reduced = lowering_->ReduceJSToStringInput(node); | 189 Reduction reduced = lowering_->ReduceJSToStringInput(node); |
| 190 if (reduced.Changed()) return reduced.replacement(); | 190 if (reduced.Changed()) return reduced.replacement(); |
| 191 Node* n = graph()->NewNode(javascript()->ToString(), node, context(), | 191 Node* n = graph()->NewNode(javascript()->ToString(), node, context(), |
| 192 effect(), control()); | 192 effect(), control()); |
| 193 update_effect(n); | 193 update_effect(n); |
| 194 return n; | 194 return n; |
| 195 } | 195 } |
| 196 | 196 |
| 197 Node* ConvertToNumber(Node* node) { | 197 Node* ConvertToNumber(Node* node) { |
| 198 // Avoid introducing too many eager ToNumber() operations. | 198 if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) { |
| 199 Reduction reduced = lowering_->ReduceJSToNumberInput(node); | 199 return lowering_->ConvertToNumber(node); |
| 200 if (reduced.Changed()) return reduced.replacement(); | 200 } |
| 201 Node* n = graph()->NewNode(javascript()->ToNumber(), node, context(), | 201 Node* n = graph()->NewNode(javascript()->ToNumber(), node, context(), |
| 202 effect(), control()); | 202 effect(), control()); |
| 203 update_effect(n); | 203 update_effect(n); |
| 204 return n; | 204 return n; |
| 205 } | 205 } |
| 206 | 206 |
| 207 Node* ConvertToUI32(Node* node, Signedness signedness) { | 207 Node* ConvertToUI32(Node* node, Signedness signedness) { |
| 208 // Avoid introducing too many eager NumberToXXnt32() operations. | 208 // Avoid introducing too many eager NumberToXXnt32() operations. |
| 209 node = ConvertToNumber(node); | 209 node = ConvertToNumber(node); |
| 210 Type* type = NodeProperties::GetBounds(node).upper; | 210 Type* type = NodeProperties::GetBounds(node).upper; |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 } | 490 } |
| 491 | 491 |
| 492 | 492 |
| 493 Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) { | 493 Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) { |
| 494 if (input->opcode() == IrOpcode::kJSToBoolean) { | 494 if (input->opcode() == IrOpcode::kJSToBoolean) { |
| 495 // Recursively try to reduce the input first. | 495 // Recursively try to reduce the input first. |
| 496 Reduction result = ReduceJSToBoolean(input); | 496 Reduction result = ReduceJSToBoolean(input); |
| 497 if (result.Changed()) return result; | 497 if (result.Changed()) return result; |
| 498 return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x) | 498 return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x) |
| 499 } | 499 } |
| 500 // Check if we have a cached conversion. |
| 501 Node* conversion = FindConversion<IrOpcode::kJSToBoolean>(input); |
| 502 if (conversion) return Replace(conversion); |
| 500 Type* input_type = NodeProperties::GetBounds(input).upper; | 503 Type* input_type = NodeProperties::GetBounds(input).upper; |
| 501 if (input_type->Is(Type::Boolean())) { | 504 if (input_type->Is(Type::Boolean())) { |
| 502 return Changed(input); // JSToBoolean(x:boolean) => x | 505 return Changed(input); // JSToBoolean(x:boolean) => x |
| 503 } | 506 } |
| 504 if (input_type->Is(Type::Undefined())) { | 507 if (input_type->Is(Type::Undefined())) { |
| 505 // JSToBoolean(undefined) => #false | 508 // JSToBoolean(undefined) => #false |
| 506 return Replace(jsgraph()->FalseConstant()); | 509 return Replace(jsgraph()->FalseConstant()); |
| 507 } | 510 } |
| 508 if (input_type->Is(Type::Null())) { | 511 if (input_type->Is(Type::Null())) { |
| 509 // JSToBoolean(null) => #false | 512 // JSToBoolean(null) => #false |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 // JSToBoolean(phi(x1,...,xn,control),context) | 550 // JSToBoolean(phi(x1,...,xn,control),context) |
| 548 // => phi(JSToBoolean(x1,no-context),...,JSToBoolean(xn,no-context)) | 551 // => phi(JSToBoolean(x1,no-context),...,JSToBoolean(xn,no-context)) |
| 549 int const input_count = input->InputCount() - 1; | 552 int const input_count = input->InputCount() - 1; |
| 550 Node* const control = input->InputAt(input_count); | 553 Node* const control = input->InputAt(input_count); |
| 551 DCHECK_LE(0, input_count); | 554 DCHECK_LE(0, input_count); |
| 552 DCHECK(NodeProperties::IsControl(control)); | 555 DCHECK(NodeProperties::IsControl(control)); |
| 553 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); | 556 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); |
| 554 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); | 557 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); |
| 555 node->set_op(common()->Phi(kMachAnyTagged, input_count)); | 558 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
| 556 for (int i = 0; i < input_count; ++i) { | 559 for (int i = 0; i < input_count; ++i) { |
| 557 Node* value = input->InputAt(i); | 560 // We must be very careful not to introduce cycles when pushing |
| 558 // Recursively try to reduce the value first. | 561 // operations into phis. It is safe for {value}, since it appears |
| 559 Reduction reduction = ReduceJSToBooleanInput(value); | 562 // as input to the phi that we are replacing, but it's not safe |
| 560 if (reduction.Changed()) { | 563 // to simply reuse the context of the {node}. However, ToBoolean() |
| 561 value = reduction.replacement(); | 564 // does not require a context anyways, so it's safe to discard it |
| 562 } else { | 565 // here and pass the dummy context. |
| 563 // We must be very careful not to introduce cycles when pushing | 566 Node* const value = ConvertToBoolean(input->InputAt(i)); |
| 564 // operations into phis. It is safe for {value}, since it appears | |
| 565 // as input to the phi that we are replacing, but it's not safe | |
| 566 // to simply reuse the context of the {node}. However, ToBoolean() | |
| 567 // does not require a context anyways, so it's safe to discard it | |
| 568 // here and pass the dummy context. | |
| 569 value = graph()->NewNode(javascript()->ToBoolean(), value, | |
| 570 jsgraph()->NoContextConstant()); | |
| 571 } | |
| 572 if (i < node->InputCount()) { | 567 if (i < node->InputCount()) { |
| 573 node->ReplaceInput(i, value); | 568 node->ReplaceInput(i, value); |
| 574 } else { | 569 } else { |
| 575 node->AppendInput(graph()->zone(), value); | 570 node->AppendInput(graph()->zone(), value); |
| 576 } | 571 } |
| 577 } | 572 } |
| 578 if (input_count < node->InputCount()) { | 573 if (input_count < node->InputCount()) { |
| 579 node->ReplaceInput(input_count, control); | 574 node->ReplaceInput(input_count, control); |
| 580 } else { | 575 } else { |
| 581 node->AppendInput(graph()->zone(), control); | 576 node->AppendInput(graph()->zone(), control); |
| 582 } | 577 } |
| 583 node->TrimInputCount(input_count + 1); | 578 node->TrimInputCount(input_count + 1); |
| 584 return Changed(node); | 579 return Changed(node); |
| 585 } | 580 } |
| 586 if (input->opcode() == IrOpcode::kSelect) { | 581 if (input->opcode() == IrOpcode::kSelect) { |
| 587 // JSToBoolean(select(c,x1,x2),context) | 582 // JSToBoolean(select(c,x1,x2),context) |
| 588 // => select(c,JSToBoolean(x1,no-context),...,JSToBoolean(x2,no-context)) | 583 // => select(c,JSToBoolean(x1,no-context),...,JSToBoolean(x2,no-context)) |
| 589 int const input_count = input->InputCount(); | 584 int const input_count = input->InputCount(); |
| 590 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); | 585 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); |
| 591 DCHECK_EQ(3, input_count); | 586 DCHECK_EQ(3, input_count); |
| 592 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); | 587 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); |
| 593 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); | 588 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); |
| 594 node->set_op(common()->Select(kMachAnyTagged, input_hint)); | 589 node->set_op(common()->Select(kMachAnyTagged, input_hint)); |
| 595 node->InsertInput(graph()->zone(), 0, input->InputAt(0)); | 590 node->InsertInput(graph()->zone(), 0, input->InputAt(0)); |
| 596 for (int i = 1; i < input_count; ++i) { | 591 for (int i = 1; i < input_count; ++i) { |
| 597 Node* value = input->InputAt(i); | 592 // We must be very careful not to introduce cycles when pushing |
| 598 // Recursively try to reduce the value first. | 593 // operations into selects. It is safe for {value}, since it appears |
| 599 Reduction reduction = ReduceJSToBooleanInput(value); | 594 // as input to the select that we are replacing, but it's not safe |
| 600 if (reduction.Changed()) { | 595 // to simply reuse the context of the {node}. However, ToBoolean() |
| 601 value = reduction.replacement(); | 596 // does not require a context anyways, so it's safe to discard it |
| 602 } else { | 597 // here and pass the dummy context. |
| 603 // We must be very careful not to introduce cycles when pushing | 598 Node* const value = ConvertToBoolean(input->InputAt(i)); |
| 604 // operations into selects. It is safe for {value}, since it appears | |
| 605 // as input to the select that we are replacing, but it's not safe | |
| 606 // to simply reuse the context of the {node}. However, ToBoolean() | |
| 607 // does not require a context anyways, so it's safe to discard it | |
| 608 // here and pass the dummy context. | |
| 609 value = graph()->NewNode(javascript()->ToBoolean(), value, | |
| 610 jsgraph()->NoContextConstant()); | |
| 611 } | |
| 612 node->ReplaceInput(i, value); | 599 node->ReplaceInput(i, value); |
| 613 } | 600 } |
| 614 DCHECK_EQ(3, node->InputCount()); | 601 DCHECK_EQ(3, node->InputCount()); |
| 615 return Changed(node); | 602 return Changed(node); |
| 616 } | 603 } |
| 604 InsertConversion(node); |
| 605 if (node->InputAt(1) != jsgraph()->NoContextConstant()) { |
| 606 // JSToBoolean(x,context) => JSToBoolean(x,no-context) |
| 607 node->ReplaceInput(1, jsgraph()->NoContextConstant()); |
| 608 return Changed(node); |
| 609 } |
| 617 return NoChange(); | 610 return NoChange(); |
| 618 } | 611 } |
| 619 | 612 |
| 620 | 613 |
| 621 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { | 614 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { |
| 622 if (input->opcode() == IrOpcode::kJSToNumber) { | 615 if (input->opcode() == IrOpcode::kJSToNumber) { |
| 623 // Recursively try to reduce the input first. | 616 // Recursively try to reduce the input first. |
| 624 Reduction result = ReduceJSToNumber(input); | 617 Reduction result = ReduceJSToNumber(input); |
| 625 if (result.Changed()) return result; | 618 if (result.Changed()) return result; |
| 626 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x) | 619 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x) |
| 627 } | 620 } |
| 621 // Check if we have a cached conversion. |
| 622 Node* conversion = FindConversion<IrOpcode::kJSToNumber>(input); |
| 623 if (conversion) return Replace(conversion); |
| 628 Type* input_type = NodeProperties::GetBounds(input).upper; | 624 Type* input_type = NodeProperties::GetBounds(input).upper; |
| 629 if (input_type->Is(Type::Number())) { | 625 if (input_type->Is(Type::Number())) { |
| 630 // JSToNumber(x:number) => x | 626 // JSToNumber(x:number) => x |
| 631 return Changed(input); | 627 return Changed(input); |
| 632 } | 628 } |
| 633 if (input_type->Is(Type::Undefined())) { | 629 if (input_type->Is(Type::Undefined())) { |
| 634 // JSToNumber(undefined) => #NaN | 630 // JSToNumber(undefined) => #NaN |
| 635 return Replace(jsgraph()->NaNConstant()); | 631 return Replace(jsgraph()->NaNConstant()); |
| 636 } | 632 } |
| 637 if (input_type->Is(Type::Null())) { | 633 if (input_type->Is(Type::Null())) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 664 // JSToNumber(xn,no-context),control) | 660 // JSToNumber(xn,no-context),control) |
| 665 int const input_count = input->InputCount() - 1; | 661 int const input_count = input->InputCount() - 1; |
| 666 Node* const control = input->InputAt(input_count); | 662 Node* const control = input->InputAt(input_count); |
| 667 DCHECK_LE(0, input_count); | 663 DCHECK_LE(0, input_count); |
| 668 DCHECK(NodeProperties::IsControl(control)); | 664 DCHECK(NodeProperties::IsControl(control)); |
| 669 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); | 665 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
| 670 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); | 666 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
| 671 RelaxEffects(node); | 667 RelaxEffects(node); |
| 672 node->set_op(common()->Phi(kMachAnyTagged, input_count)); | 668 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
| 673 for (int i = 0; i < input_count; ++i) { | 669 for (int i = 0; i < input_count; ++i) { |
| 674 Node* value = input->InputAt(i); | 670 // We must be very careful not to introduce cycles when pushing |
| 675 // Recursively try to reduce the value first. | 671 // operations into phis. It is safe for {value}, since it appears |
| 676 Reduction reduction = ReduceJSToNumberInput(value); | 672 // as input to the phi that we are replacing, but it's not safe |
| 677 if (reduction.Changed()) { | 673 // to simply reuse the context of the {node}. However, ToNumber() |
| 678 value = reduction.replacement(); | 674 // does not require a context anyways, so it's safe to discard it |
| 679 } else { | 675 // here and pass the dummy context. |
| 680 // We must be very careful not to introduce cycles when pushing | 676 Node* const value = ConvertToNumber(input->InputAt(i)); |
| 681 // operations into phis. It is safe for {value}, since it appears | |
| 682 // as input to the phi that we are replacing, but it's not safe | |
| 683 // to simply reuse the context of the {node}. However, ToNumber() | |
| 684 // does not require a context anyways, so it's safe to discard it | |
| 685 // here and pass the dummy context. | |
| 686 value = graph()->NewNode(javascript()->ToNumber(), value, | |
| 687 jsgraph()->NoContextConstant(), | |
| 688 graph()->start(), graph()->start()); | |
| 689 } | |
| 690 if (i < node->InputCount()) { | 677 if (i < node->InputCount()) { |
| 691 node->ReplaceInput(i, value); | 678 node->ReplaceInput(i, value); |
| 692 } else { | 679 } else { |
| 693 node->AppendInput(graph()->zone(), value); | 680 node->AppendInput(graph()->zone(), value); |
| 694 } | 681 } |
| 695 } | 682 } |
| 696 if (input_count < node->InputCount()) { | 683 if (input_count < node->InputCount()) { |
| 697 node->ReplaceInput(input_count, control); | 684 node->ReplaceInput(input_count, control); |
| 698 } else { | 685 } else { |
| 699 node->AppendInput(graph()->zone(), control); | 686 node->AppendInput(graph()->zone(), control); |
| 700 } | 687 } |
| 701 node->TrimInputCount(input_count + 1); | 688 node->TrimInputCount(input_count + 1); |
| 702 return Changed(node); | 689 return Changed(node); |
| 703 } | 690 } |
| 704 if (input->opcode() == IrOpcode::kSelect) { | 691 if (input->opcode() == IrOpcode::kSelect) { |
| 705 // JSToNumber(select(c,x1,x2):plain-primitive,context) | 692 // JSToNumber(select(c,x1,x2):plain-primitive,context) |
| 706 // => select(c,JSToNumber(x1,no-context),JSToNumber(x2,no-context)) | 693 // => select(c,JSToNumber(x1,no-context),JSToNumber(x2,no-context)) |
| 707 int const input_count = input->InputCount(); | 694 int const input_count = input->InputCount(); |
| 708 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); | 695 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); |
| 709 DCHECK_EQ(3, input_count); | 696 DCHECK_EQ(3, input_count); |
| 710 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); | 697 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
| 711 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); | 698 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
| 712 RelaxEffects(node); | 699 RelaxEffects(node); |
| 713 node->set_op(common()->Select(kMachAnyTagged, input_hint)); | 700 node->set_op(common()->Select(kMachAnyTagged, input_hint)); |
| 714 node->ReplaceInput(0, input->InputAt(0)); | 701 node->ReplaceInput(0, input->InputAt(0)); |
| 715 for (int i = 1; i < input_count; ++i) { | 702 for (int i = 1; i < input_count; ++i) { |
| 716 Node* value = input->InputAt(i); | 703 // We must be very careful not to introduce cycles when pushing |
| 717 // Recursively try to reduce the value first. | 704 // operations into selects. It is safe for {value}, since it appears |
| 718 Reduction reduction = ReduceJSToNumberInput(value); | 705 // as input to the select that we are replacing, but it's not safe |
| 719 if (reduction.Changed()) { | 706 // to simply reuse the context of the {node}. However, ToNumber() |
| 720 value = reduction.replacement(); | 707 // does not require a context anyways, so it's safe to discard it |
| 721 } else { | 708 // here and pass the dummy context. |
| 722 // We must be very careful not to introduce cycles when pushing | 709 Node* const value = ConvertToNumber(input->InputAt(i)); |
| 723 // operations into selects. It is safe for {value}, since it appears | |
| 724 // as input to the select that we are replacing, but it's not safe | |
| 725 // to simply reuse the context of the {node}. However, ToNumber() | |
| 726 // does not require a context anyways, so it's safe to discard it | |
| 727 // here and pass the dummy context. | |
| 728 value = graph()->NewNode(javascript()->ToNumber(), value, | |
| 729 jsgraph()->NoContextConstant(), | |
| 730 graph()->start(), graph()->start()); | |
| 731 } | |
| 732 node->ReplaceInput(i, value); | 710 node->ReplaceInput(i, value); |
| 733 } | 711 } |
| 734 node->TrimInputCount(input_count); | 712 node->TrimInputCount(input_count); |
| 735 return Changed(node); | 713 return Changed(node); |
| 736 } | 714 } |
| 715 // Remember this conversion. |
| 716 InsertConversion(node); |
| 737 if (node->InputAt(1) != jsgraph()->NoContextConstant() || | 717 if (node->InputAt(1) != jsgraph()->NoContextConstant() || |
| 738 node->InputAt(2) != graph()->start()) { | 718 node->InputAt(2) != graph()->start() || |
| 739 // JSToNumber(x:plain-primitive,context) => JSToNumber(x,no-context) | 719 node->InputAt(3) != graph()->start()) { |
| 720 // JSToNumber(x:plain-primitive,context,effect,control) |
| 721 // => JSToNumber(x,no-context,start,start) |
| 722 RelaxEffects(node); |
| 740 node->ReplaceInput(1, jsgraph()->NoContextConstant()); | 723 node->ReplaceInput(1, jsgraph()->NoContextConstant()); |
| 741 RelaxEffects(node); | 724 node->ReplaceInput(2, graph()->start()); |
| 725 node->ReplaceInput(3, graph()->start()); |
| 742 return Changed(node); | 726 return Changed(node); |
| 743 } | 727 } |
| 744 } | 728 } |
| 745 return NoChange(); | 729 return NoChange(); |
| 746 } | 730 } |
| 747 | 731 |
| 748 | 732 |
| 749 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { | 733 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { |
| 750 if (input->opcode() == IrOpcode::kJSToString) { | 734 if (input->opcode() == IrOpcode::kJSToString) { |
| 751 // Recursively try to reduce the input first. | 735 // Recursively try to reduce the input first. |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1015 return ReduceJSLoadContext(node); | 999 return ReduceJSLoadContext(node); |
| 1016 case IrOpcode::kJSStoreContext: | 1000 case IrOpcode::kJSStoreContext: |
| 1017 return ReduceJSStoreContext(node); | 1001 return ReduceJSStoreContext(node); |
| 1018 default: | 1002 default: |
| 1019 break; | 1003 break; |
| 1020 } | 1004 } |
| 1021 return NoChange(); | 1005 return NoChange(); |
| 1022 } | 1006 } |
| 1023 | 1007 |
| 1024 | 1008 |
| 1009 Node* JSTypedLowering::ConvertToBoolean(Node* input) { |
| 1010 // Avoid inserting too many eager ToBoolean() operations. |
| 1011 Reduction const reduction = ReduceJSToBooleanInput(input); |
| 1012 if (reduction.Changed()) return reduction.replacement(); |
| 1013 Node* const conversion = graph()->NewNode(javascript()->ToBoolean(), input, |
| 1014 jsgraph()->NoContextConstant()); |
| 1015 InsertConversion(conversion); |
| 1016 return conversion; |
| 1017 } |
| 1018 |
| 1019 |
| 1020 Node* JSTypedLowering::ConvertToNumber(Node* input) { |
| 1021 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); |
| 1022 // Avoid inserting too many eager ToNumber() operations. |
| 1023 Reduction const reduction = ReduceJSToNumberInput(input); |
| 1024 if (reduction.Changed()) return reduction.replacement(); |
| 1025 Node* const conversion = graph()->NewNode(javascript()->ToNumber(), input, |
| 1026 jsgraph()->NoContextConstant(), |
| 1027 graph()->start(), graph()->start()); |
| 1028 InsertConversion(conversion); |
| 1029 return conversion; |
| 1030 } |
| 1031 |
| 1032 |
| 1033 template <IrOpcode::Value kOpcode> |
| 1034 Node* JSTypedLowering::FindConversion(Node* input) { |
| 1035 size_t const input_id = input->id(); |
| 1036 if (input_id < conversions_.size()) { |
| 1037 Node* const conversion = conversions_[input_id]; |
| 1038 if (conversion && conversion->opcode() == kOpcode) { |
| 1039 return conversion; |
| 1040 } |
| 1041 } |
| 1042 return nullptr; |
| 1043 } |
| 1044 |
| 1045 |
| 1046 void JSTypedLowering::InsertConversion(Node* conversion) { |
| 1047 DCHECK(conversion->opcode() == IrOpcode::kJSToBoolean || |
| 1048 conversion->opcode() == IrOpcode::kJSToNumber); |
| 1049 size_t const input_id = conversion->InputAt(0)->id(); |
| 1050 if (input_id >= conversions_.size()) { |
| 1051 conversions_.resize(2 * input_id + 1); |
| 1052 } |
| 1053 conversions_[input_id] = conversion; |
| 1054 } |
| 1055 |
| 1056 |
| 1025 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { | 1057 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { |
| 1026 if (rhs == 0) return lhs; | 1058 if (rhs == 0) return lhs; |
| 1027 return graph()->NewNode(machine()->Word32Shl(), lhs, | 1059 return graph()->NewNode(machine()->Word32Shl(), lhs, |
| 1028 jsgraph()->Int32Constant(rhs)); | 1060 jsgraph()->Int32Constant(rhs)); |
| 1029 } | 1061 } |
| 1030 | 1062 |
| 1031 | 1063 |
| 1032 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } | 1064 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } |
| 1033 | 1065 |
| 1034 | 1066 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1045 } | 1077 } |
| 1046 | 1078 |
| 1047 | 1079 |
| 1048 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1080 MachineOperatorBuilder* JSTypedLowering::machine() const { |
| 1049 return jsgraph()->machine(); | 1081 return jsgraph()->machine(); |
| 1050 } | 1082 } |
| 1051 | 1083 |
| 1052 } // namespace compiler | 1084 } // namespace compiler |
| 1053 } // namespace internal | 1085 } // namespace internal |
| 1054 } // namespace v8 | 1086 } // namespace v8 |
| OLD | NEW |