V8 Project
v8::internal::HRangeAnalysisPhase Class Reference

#include <hydrogen-range-analysis.h>

+ Inheritance diagram for v8::internal::HRangeAnalysisPhase:
+ Collaboration diagram for v8::internal::HRangeAnalysisPhase:

Public Member Functions

 HRangeAnalysisPhase (HGraph *graph)
 
void Run ()
 
- Public Member Functions inherited from v8::internal::HPhase
 HPhase (const char *name, HGraph *graph)
 
 ~HPhase ()
 

Private Member Functions

void TraceRange (const char *msg,...)
 
void InferControlFlowRange (HCompareNumericAndBranch *test, HBasicBlock *dest)
 
void UpdateControlFlowRange (Token::Value op, HValue *value, HValue *other)
 
void InferRange (HValue *value)
 
void RollBackTo (int index)
 
void AddRange (HValue *value, Range *range)
 
void AddToWorklist (HValue *value)
 
void PropagateMinusZeroChecks (HValue *value)
 
void PoisonRanges ()
 
 DISALLOW_COPY_AND_ASSIGN (HRangeAnalysisPhase)
 

Private Attributes

ZoneList< HValue * > changed_ranges_
 
BitVector in_worklist_
 
ZoneList< HValue * > worklist_
 

Additional Inherited Members

- Protected Member Functions inherited from v8::internal::HPhase
HGraph * graph () const
 

Detailed Description

Definition at line 14 of file hydrogen-range-analysis.h.

Constructor & Destructor Documentation

◆ HRangeAnalysisPhase()

v8::internal::HRangeAnalysisPhase::HRangeAnalysisPhase ( HGraph *  graph)
inlineexplicit

Definition at line 16 of file hydrogen-range-analysis.h.

17  : HPhase("H_Range analysis", graph), changed_ranges_(16, zone()),
18  in_worklist_(graph->GetMaximumValueID(), zone()),
19  worklist_(32, zone()) {}
HGraph * graph() const
Definition: hydrogen.h:2802
HPhase(const char *name, HGraph *graph)
Definition: hydrogen.h:2796

Member Function Documentation

◆ AddRange()

void v8::internal::HRangeAnalysisPhase::AddRange ( HValue value,
Range *  range 
)
private

Definition at line 195 of file hydrogen-range-analysis.cc.

195  {
196  Range* original_range = value->range();
197  value->AddNewRange(range, graph()->zone());
198  changed_ranges_.Add(value, zone());
199  Range* new_range = value->range();
200  TraceRange("Updated range of %d set to [%d,%d]\n",
201  value->id(),
202  new_range->lower(),
203  new_range->upper());
204  if (original_range != NULL) {
205  TraceRange("Original range was [%d,%d]\n",
206  original_range->lower(),
207  original_range->upper());
208  }
209  TraceRange("New information was [%d,%d]\n",
210  range->lower(),
211  range->upper());
212 }
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL

References v8::internal::HValue::AddNewRange(), changed_ranges_, v8::internal::HPhase::graph(), v8::internal::HValue::id(), NULL, v8::internal::HValue::range(), and TraceRange().

Referenced by UpdateControlFlowRange().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ AddToWorklist()

void v8::internal::HRangeAnalysisPhase::AddToWorklist ( HValue value)
inlineprivate

Definition at line 31 of file hydrogen-range-analysis.h.

31  {
32  if (in_worklist_.Contains(value->id())) return;
33  in_worklist_.Add(value->id());
34  worklist_.Add(value, zone());
35  }
bool Contains(int i) const
Definition: data-flow.h:99

References v8::internal::BitVector::Add(), v8::internal::BitVector::Contains(), v8::internal::HValue::id(), in_worklist_, and worklist_.

Referenced by PropagateMinusZeroChecks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DISALLOW_COPY_AND_ASSIGN()

v8::internal::HRangeAnalysisPhase::DISALLOW_COPY_AND_ASSIGN ( HRangeAnalysisPhase  )
private

◆ InferControlFlowRange()

void v8::internal::HRangeAnalysisPhase::InferControlFlowRange ( HCompareNumericAndBranch test,
HBasicBlock *  dest 
)
private

Definition at line 122 of file hydrogen-range-analysis.cc.

123  {
124  DCHECK((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
125  if (test->representation().IsSmiOrInteger32()) {
126  Token::Value op = test->token();
127  if (test->SecondSuccessor() == dest) {
128  op = Token::NegateCompareOp(op);
129  }
130  Token::Value inverted_op = Token::ReverseCompareOp(op);
131  UpdateControlFlowRange(op, test->left(), test->right());
132  UpdateControlFlowRange(inverted_op, test->right(), test->left());
133  }
134 }
void UpdateControlFlowRange(Token::Value op, HValue *value, HValue *other)
static Value NegateCompareOp(Value op)
Definition: token.h:223
static Value ReverseCompareOp(Value op)
Definition: token.h:240
#define DCHECK(condition)
Definition: logging.h:205

References DCHECK, v8::internal::HControlInstruction::FirstSuccessor(), v8::internal::Representation::IsSmiOrInteger32(), v8::internal::HCompareNumericAndBranch::left(), v8::internal::Token::NegateCompareOp(), v8::internal::HValue::representation(), v8::internal::Token::ReverseCompareOp(), v8::internal::HCompareNumericAndBranch::right(), v8::internal::HControlInstruction::SecondSuccessor(), v8::internal::HCompareNumericAndBranch::token(), and UpdateControlFlowRange().

Referenced by Run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ InferRange()

void v8::internal::HRangeAnalysisPhase::InferRange ( HValue value)
private

Definition at line 172 of file hydrogen-range-analysis.cc.

172  {
173  DCHECK(!value->HasRange());
174  if (!value->representation().IsNone()) {
175  value->ComputeInitialRange(graph()->zone());
176  Range* range = value->range();
177  TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
178  value->id(),
179  value->Mnemonic(),
180  range->lower(),
181  range->upper());
182  }
183 }

References v8::internal::HValue::ComputeInitialRange(), DCHECK, v8::internal::HPhase::graph(), v8::internal::HValue::HasRange(), v8::internal::HValue::id(), v8::internal::Representation::IsNone(), v8::internal::HValue::Mnemonic(), v8::internal::HValue::range(), v8::internal::HValue::representation(), and TraceRange().

Referenced by Run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PoisonRanges()

void v8::internal::HRangeAnalysisPhase::PoisonRanges ( )
private

Definition at line 109 of file hydrogen-range-analysis.cc.

109  {
110 #ifdef DEBUG
111  for (int i = 0; i < graph()->blocks()->length(); ++i) {
112  HBasicBlock* block = graph()->blocks()->at(i);
113  for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
114  HInstruction* instr = it.Current();
115  if (instr->HasRange()) instr->PoisonRange();
116  }
117  }
118 #endif
119 }

References v8::internal::HPhase::graph(), and v8::internal::HValue::HasRange().

Referenced by Run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PropagateMinusZeroChecks()

void v8::internal::HRangeAnalysisPhase::PropagateMinusZeroChecks ( HValue value)
private

Definition at line 215 of file hydrogen-range-analysis.cc.

215  {
216  DCHECK(worklist_.is_empty());
218 
219  AddToWorklist(value);
220  while (!worklist_.is_empty()) {
221  value = worklist_.RemoveLast();
222 
223  if (value->IsPhi()) {
224  // For phis, we must propagate the check to all of its inputs.
225  HPhi* phi = HPhi::cast(value);
226  for (int i = 0; i < phi->OperandCount(); ++i) {
227  AddToWorklist(phi->OperandAt(i));
228  }
229  } else if (value->IsUnaryMathOperation()) {
230  HUnaryMathOperation* instr = HUnaryMathOperation::cast(value);
231  if (instr->representation().IsSmiOrInteger32() &&
232  !instr->value()->representation().Equals(instr->representation())) {
233  if (instr->value()->range() == NULL ||
234  instr->value()->range()->CanBeMinusZero()) {
235  instr->SetFlag(HValue::kBailoutOnMinusZero);
236  }
237  }
238  if (instr->RequiredInputRepresentation(0).IsSmiOrInteger32() &&
239  instr->representation().Equals(
240  instr->RequiredInputRepresentation(0))) {
241  AddToWorklist(instr->value());
242  }
243  } else if (value->IsChange()) {
244  HChange* instr = HChange::cast(value);
245  if (!instr->from().IsSmiOrInteger32() &&
246  !instr->CanTruncateToInt32() &&
247  (instr->value()->range() == NULL ||
248  instr->value()->range()->CanBeMinusZero())) {
249  instr->SetFlag(HValue::kBailoutOnMinusZero);
250  }
251  } else if (value->IsForceRepresentation()) {
252  HForceRepresentation* instr = HForceRepresentation::cast(value);
253  AddToWorklist(instr->value());
254  } else if (value->IsMod()) {
255  HMod* instr = HMod::cast(value);
256  if (instr->range() == NULL || instr->range()->CanBeMinusZero()) {
257  instr->SetFlag(HValue::kBailoutOnMinusZero);
258  AddToWorklist(instr->left());
259  }
260  } else if (value->IsDiv() || value->IsMul()) {
261  HBinaryOperation* instr = HBinaryOperation::cast(value);
262  if (instr->range() == NULL || instr->range()->CanBeMinusZero()) {
263  instr->SetFlag(HValue::kBailoutOnMinusZero);
264  }
265  AddToWorklist(instr->right());
266  AddToWorklist(instr->left());
267  } else if (value->IsMathFloorOfDiv()) {
268  HMathFloorOfDiv* instr = HMathFloorOfDiv::cast(value);
269  instr->SetFlag(HValue::kBailoutOnMinusZero);
270  } else if (value->IsAdd() || value->IsSub()) {
271  HBinaryOperation* instr = HBinaryOperation::cast(value);
272  if (instr->range() == NULL || instr->range()->CanBeMinusZero()) {
273  // Propagate to the left argument. If the left argument cannot be -0,
274  // then the result of the add/sub operation cannot be either.
275  AddToWorklist(instr->left());
276  }
277  } else if (value->IsMathMinMax()) {
278  HMathMinMax* instr = HMathMinMax::cast(value);
279  AddToWorklist(instr->right());
280  AddToWorklist(instr->left());
281  }
282  }
283 
286  DCHECK(worklist_.is_empty());
287 }
bool IsEmpty() const
Definition: data-flow.h:164
static HValue * cast(HValue *value)

References AddToWorklist(), v8::internal::HValue::cast(), v8::internal::BitVector::Clear(), DCHECK, in_worklist_, v8::internal::BitVector::IsEmpty(), v8::internal::HValue::IsPhi(), v8::internal::HValue::kBailoutOnMinusZero, v8::internal::HBinaryOperation::left(), NULL, v8::internal::HValue::range(), v8::internal::HBinaryOperation::right(), v8::internal::HValue::SetFlag(), and worklist_.

Referenced by Run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ RollBackTo()

void v8::internal::HRangeAnalysisPhase::RollBackTo ( int  index)
private

Definition at line 186 of file hydrogen-range-analysis.cc.

186  {
187  DCHECK(index <= changed_ranges_.length());
188  for (int i = index; i < changed_ranges_.length(); ++i) {
189  changed_ranges_[i]->RemoveLastAddedRange();
190  }
191  changed_ranges_.Rewind(index);
192 }

References changed_ranges_, and DCHECK.

Referenced by Run().

+ Here is the caller graph for this function:

◆ Run()

void v8::internal::HRangeAnalysisPhase::Run ( )

Definition at line 35 of file hydrogen-range-analysis.cc.

35  {
36  HBasicBlock* block(graph()->entry_block());
37  ZoneList<Pending> stack(graph()->blocks()->length(), zone());
38  while (block != NULL) {
39  TraceRange("Analyzing block B%d\n", block->block_id());
40 
41  // Infer range based on control flow.
42  if (block->predecessors()->length() == 1) {
43  HBasicBlock* pred = block->predecessors()->first();
44  if (pred->end()->IsCompareNumericAndBranch()) {
46  block);
47  }
48  }
49 
50  // Process phi instructions.
51  for (int i = 0; i < block->phis()->length(); ++i) {
52  HPhi* phi = block->phis()->at(i);
53  InferRange(phi);
54  }
55 
56  // Go through all instructions of the current block.
57  for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
58  HValue* value = it.Current();
59  InferRange(value);
60 
61  // Compute the bailout-on-minus-zero flag.
62  if (value->IsChange()) {
63  HChange* instr = HChange::cast(value);
64  // Propagate flags for negative zero checks upwards from conversions
65  // int32-to-tagged and int32-to-double.
66  Representation from = instr->value()->representation();
67  DCHECK(from.Equals(instr->from()));
68  if (from.IsSmiOrInteger32()) {
69  DCHECK(instr->to().IsTagged() ||
70  instr->to().IsDouble() ||
71  instr->to().IsSmiOrInteger32());
72  PropagateMinusZeroChecks(instr->value());
73  }
74  } else if (value->IsCompareMinusZeroAndBranch()) {
75  HCompareMinusZeroAndBranch* instr =
76  HCompareMinusZeroAndBranch::cast(value);
77  if (instr->value()->representation().IsSmiOrInteger32()) {
78  PropagateMinusZeroChecks(instr->value());
79  }
80  }
81  }
82 
83  // Continue analysis in all dominated blocks.
84  const ZoneList<HBasicBlock*>* dominated_blocks(block->dominated_blocks());
85  if (!dominated_blocks->is_empty()) {
86  // Continue with first dominated block, and push the
87  // remaining blocks on the stack (in reverse order).
88  int last_changed_range = changed_ranges_.length();
89  for (int i = dominated_blocks->length() - 1; i > 0; --i) {
90  stack.Add(Pending(dominated_blocks->at(i), last_changed_range), zone());
91  }
92  block = dominated_blocks->at(0);
93  } else if (!stack.is_empty()) {
94  // Pop next pending block from stack.
95  Pending pending = stack.RemoveLast();
96  RollBackTo(pending.last_changed_range());
97  block = pending.block();
98  } else {
99  // All blocks done.
100  block = NULL;
101  }
102  }
103 
104  // The ranges are not valid anymore due to SSI vs. SSA!
105  PoisonRanges();
106 }
void InferControlFlowRange(HCompareNumericAndBranch *test, HBasicBlock *dest)

References v8::internal::List< T, AllocationPolicy >::Add(), v8::internal::List< T, AllocationPolicy >::at(), v8::internal::Pending::block(), v8::internal::HValue::cast(), changed_ranges_, DCHECK, v8::internal::Representation::Equals(), v8::internal::HPhase::graph(), InferControlFlowRange(), InferRange(), v8::internal::Representation::IsSmiOrInteger32(), v8::internal::Pending::last_changed_range(), NULL, PoisonRanges(), PropagateMinusZeroChecks(), RollBackTo(), and TraceRange().

+ Here is the call graph for this function:

◆ TraceRange()

void v8::internal::HRangeAnalysisPhase::TraceRange ( const char *  msg,
  ... 
)
private

Definition at line 25 of file hydrogen-range-analysis.cc.

25  {
26  if (FLAG_trace_range) {
27  va_list arguments;
28  va_start(arguments, msg);
29  base::OS::VPrint(msg, arguments);
30  va_end(arguments);
31  }
32 }
static void VPrint(const char *format, va_list args)

References v8::base::OS::VPrint().

Referenced by AddRange(), InferRange(), Run(), and UpdateControlFlowRange().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ UpdateControlFlowRange()

void v8::internal::HRangeAnalysisPhase::UpdateControlFlowRange ( Token::Value  op,
HValue value,
HValue other 
)
private

Definition at line 139 of file hydrogen-range-analysis.cc.

141  {
142  Range temp_range;
143  Range* range = other->range() != NULL ? other->range() : &temp_range;
144  Range* new_range = NULL;
145 
146  TraceRange("Control flow range infer %d %s %d\n",
147  value->id(),
148  Token::Name(op),
149  other->id());
150 
151  if (op == Token::EQ || op == Token::EQ_STRICT) {
152  // The same range has to apply for value.
153  new_range = range->Copy(graph()->zone());
154  } else if (op == Token::LT || op == Token::LTE) {
155  new_range = range->CopyClearLower(graph()->zone());
156  if (op == Token::LT) {
157  new_range->AddConstant(-1);
158  }
159  } else if (op == Token::GT || op == Token::GTE) {
160  new_range = range->CopyClearUpper(graph()->zone());
161  if (op == Token::GT) {
162  new_range->AddConstant(1);
163  }
164  }
165 
166  if (new_range != NULL && !new_range->IsMostGeneric()) {
167  AddRange(value, new_range);
168  }
169 }
void AddRange(HValue *value, Range *range)
static const char * Name(Value tok)
Definition: token.h:180

References AddRange(), v8::internal::EQ, v8::internal::HPhase::graph(), v8::internal::HValue::id(), v8::internal::Token::Name(), NULL, v8::internal::HValue::range(), and TraceRange().

Referenced by InferControlFlowRange().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ changed_ranges_

ZoneList<HValue*> v8::internal::HRangeAnalysisPhase::changed_ranges_
private

Definition at line 39 of file hydrogen-range-analysis.h.

Referenced by AddRange(), RollBackTo(), and Run().

◆ in_worklist_

BitVector v8::internal::HRangeAnalysisPhase::in_worklist_
private

Definition at line 41 of file hydrogen-range-analysis.h.

Referenced by AddToWorklist(), and PropagateMinusZeroChecks().

◆ worklist_

ZoneList<HValue*> v8::internal::HRangeAnalysisPhase::worklist_
private

Definition at line 42 of file hydrogen-range-analysis.h.

Referenced by AddToWorklist(), and PropagateMinusZeroChecks().


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