Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | List of all members
dart::BoundsCheckGeneralizer Class Reference

Public Member Functions

 BoundsCheckGeneralizer (RangeAnalysis *range_analysis, FlowGraph *flow_graph)
 
void TryGeneralize (CheckArrayBoundInstr *check)
 

Static Public Member Functions

static void RemoveGeneralizedCheck (CheckArrayBoundInstr *check)
 

Detailed Description

Definition at line 743 of file range_analysis.cc.

Constructor & Destructor Documentation

◆ BoundsCheckGeneralizer()

dart::BoundsCheckGeneralizer::BoundsCheckGeneralizer ( RangeAnalysis range_analysis,
FlowGraph flow_graph 
)
inline

Definition at line 745 of file range_analysis.cc.

746 : range_analysis_(range_analysis),
747 flow_graph_(flow_graph),
748 scheduler_(flow_graph) {}

Member Function Documentation

◆ RemoveGeneralizedCheck()

static void dart::BoundsCheckGeneralizer::RemoveGeneralizedCheck ( CheckArrayBoundInstr check)
inlinestatic

Definition at line 886 of file range_analysis.cc.

886 {
887 BinarySmiOpInstr* binary_op = check->index()->definition()->AsBinarySmiOp();
888 if (binary_op != nullptr) {
889 binary_op->set_can_overflow(false);
890 }
891 check->ReplaceUsesWith(check->index()->definition());
892 check->RemoveFromGraph();
893 }
#define check(reporter, ref, unref, make, kill)
Definition: RefCntTest.cpp:85

◆ TryGeneralize()

void dart::BoundsCheckGeneralizer::TryGeneralize ( CheckArrayBoundInstr check)
inline

Definition at line 750 of file range_analysis.cc.

750 {
751 Definition* upper_bound =
752 ConstructUpperBound(check->index()->definition(), check);
753 if (upper_bound == UnwrapConstraint(check->index()->definition())) {
754 // Unable to construct upper bound for the index.
755 if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
756 THR_Print("Failed to construct upper bound for %s index\n",
757 check->ToCString());
758 }
759 return;
760 }
761
762 // Re-associate subexpressions inside upper_bound to collect all constants
763 // together. This will expose more redundancies when we are going to emit
764 // upper bound through scheduler.
765 if (!Simplify(&upper_bound, nullptr)) {
766 if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
767 THR_Print("Failed to simplify upper bound for %s index\n",
768 check->ToCString());
769 }
770 return;
771 }
772 upper_bound = ApplyConstraints(upper_bound, check);
773 range_analysis_->AssignRangesRecursively(upper_bound);
774
775 // We are going to constrain any symbols participating in + and * operations
776 // to guarantee that they are positive. Find all symbols that need
777 // constraining. If there is a subtraction subexpression with non-positive
778 // range give up on generalization for simplicity.
779 GrowableArray<Definition*> non_positive_symbols;
780 if (!FindNonPositiveSymbols(&non_positive_symbols, upper_bound)) {
781#ifndef PRODUCT
782 if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
783 THR_Print(
784 "Failed to generalize %s index to %s"
785 " (can't ensure positivity)\n",
786 check->ToCString(), IndexBoundToCString(upper_bound));
787 }
788#endif // !PRODUCT
789 return;
790 }
791
792 // Check that we can statically prove that lower bound of the index is
793 // non-negative under the assumption that all potentially non-positive
794 // symbols are positive.
795 GrowableArray<ConstraintInstr*> positive_constraints(
796 non_positive_symbols.length());
797 Range* positive_range =
798 new Range(RangeBoundary::FromConstant(0),
800 for (intptr_t i = 0; i < non_positive_symbols.length(); i++) {
801 Definition* symbol = non_positive_symbols[i];
802 positive_constraints.Add(
803 new ConstraintInstr(new Value(symbol), positive_range));
804 }
805
806 Definition* lower_bound =
807 ConstructLowerBound(check->index()->definition(), check);
808 // No need to simplify lower bound before applying constraints as
809 // we are not going to emit it.
810 lower_bound = ApplyConstraints(lower_bound, check, &positive_constraints);
811 range_analysis_->AssignRangesRecursively(lower_bound);
812
813 if (!RangeUtils::IsPositive(lower_bound->range())) {
814// Can't prove that lower bound is positive even with additional checks
815// against potentially non-positive symbols. Give up.
816#ifndef PRODUCT
817 if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
818 THR_Print(
819 "Failed to generalize %s index to %s"
820 " (lower bound is not positive)\n",
821 check->ToCString(), IndexBoundToCString(upper_bound));
822 }
823#endif // !PRODUCT
824 return;
825 }
826
827#ifndef PRODUCT
828 if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
829 THR_Print("For %s computed index bounds [%s, %s]\n", check->ToCString(),
830 IndexBoundToCString(lower_bound),
831 IndexBoundToCString(upper_bound));
832 }
833#endif // !PRODUCT
834
835 // At this point we know that 0 <= index < UpperBound(index) under
836 // certain preconditions. Start by emitting this preconditions.
837 scheduler_.Start();
838
839 // AOT should only see non-deopting GenericCheckBound.
840 ASSERT(!CompilerState::Current().is_aot());
841
842 ConstantInstr* max_smi = flow_graph_->GetConstant(
844 for (intptr_t i = 0; i < non_positive_symbols.length(); i++) {
845 CheckArrayBoundInstr* precondition = new CheckArrayBoundInstr(
846 new Value(max_smi), new Value(non_positive_symbols[i]),
848 precondition->mark_generalized();
849 precondition = scheduler_.Emit(precondition, check);
850 if (precondition == nullptr) {
851 if (FLAG_trace_range_analysis) {
852 THR_Print(" => failed to insert positivity constraint\n");
853 }
854 scheduler_.Rollback();
855 return;
856 }
857 }
858
859 CheckArrayBoundInstr* new_check = new CheckArrayBoundInstr(
860 new Value(UnwrapConstraint(check->length()->definition())),
861 new Value(upper_bound), DeoptId::kNone);
862 new_check->mark_generalized();
863 if (new_check->IsRedundant()) {
864 if (FLAG_trace_range_analysis) {
865 THR_Print(" => generalized check is redundant\n");
866 }
868 return;
869 }
870
871 new_check = scheduler_.Emit(new_check, check);
872 if (new_check != nullptr) {
873 if (FLAG_trace_range_analysis) {
874 THR_Print(" => generalized check was hoisted into B%" Pd "\n",
875 new_check->GetBlock()->block_id());
876 }
878 } else {
879 if (FLAG_trace_range_analysis) {
880 THR_Print(" => generalized check can't be hoisted\n");
881 }
882 scheduler_.Rollback();
883 }
884 }
static void RemoveGeneralizedCheck(CheckArrayBoundInstr *check)
static CompilerState & Current()
static constexpr intptr_t kNone
Definition: deopt_id.h:27
ConstantInstr * GetConstant(const Object &object, Representation representation=kTagged)
Definition: flow_graph.cc:187
static Object & Handle()
Definition: object.h:407
void AssignRangesRecursively(Definition *defn)
static RangeBoundary MaxConstant(RangeSize size)
static RangeBoundary FromConstant(int64_t val)
static bool IsPositive(Range *range)
T * Emit(T *instruction, Instruction *post_dominator)
static SmiPtr New(intptr_t value)
Definition: object.h:10006
#define THR_Print(format,...)
Definition: log.h:20
#define ASSERT(E)
constexpr bool FLAG_support_il_printer
Definition: flag_list.h:48
constexpr word kSmiMax
Definition: runtime_api.h:305
static Definition * UnwrapConstraint(Definition *defn)
#define Pd
Definition: globals.h:408

The documentation for this class was generated from the following file: