37 : block_(block), last_changed_range_(last_changed_range) {}
39 HBasicBlock*
block()
const {
return block_; }
44 int last_changed_range_;
48 void HRangeAnalysisPhase::TraceRange(
const char* msg, ...) {
49 if (FLAG_trace_range) {
51 va_start(arguments, msg);
59 HBasicBlock* block(
graph()->entry_block());
61 while (block !=
NULL) {
62 TraceRange(
"Analyzing block B%d\n", block->block_id());
65 if (block->predecessors()->length() == 1) {
66 HBasicBlock* pred = block->predecessors()->first();
67 if (pred->end()->IsCompareNumericAndBranch()) {
74 for (
int i = 0; i < block->phis()->length(); ++i) {
75 HPhi* phi = block->phis()->at(i);
80 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
81 HValue* value = it.Current();
85 if (value->IsChange()) {
86 HChange* instr = HChange::cast(value);
92 ASSERT(instr->to().IsTagged() ||
93 instr->to().IsDouble() ||
94 instr->to().IsSmiOrInteger32());
95 PropagateMinusZeroChecks(instr->value());
97 }
else if (value->IsCompareMinusZeroAndBranch()) {
98 HCompareMinusZeroAndBranch* instr =
99 HCompareMinusZeroAndBranch::cast(value);
100 if (instr->value()->representation().IsSmiOrInteger32()) {
101 PropagateMinusZeroChecks(instr->value());
108 if (!dominated_blocks->is_empty()) {
111 int last_changed_range = changed_ranges_.length();
112 for (
int i = dominated_blocks->length() - 1; i > 0; --i) {
113 stack.
Add(
Pending(dominated_blocks->at(i), last_changed_range), zone());
115 block = dominated_blocks->at(0);
116 }
else if (!stack.is_empty()) {
118 Pending pending = stack.RemoveLast();
120 block = pending.
block();
138 UpdateControlFlowRange(op, test->
left(), test->
right());
139 UpdateControlFlowRange(inverted_op, test->
right(), test->
left());
146 void HRangeAnalysisPhase::UpdateControlFlowRange(
Token::Value op,
150 Range* range = other->range() !=
NULL ? other->range() : &temp_range;
151 Range* new_range =
NULL;
153 TraceRange(
"Control flow range infer %d %s %d\n",
158 if (op ==
Token::EQ || op == Token::EQ_STRICT) {
160 new_range = range->Copy(
graph()->zone());
161 }
else if (op == Token::LT || op == Token::LTE) {
162 new_range = range->CopyClearLower(
graph()->zone());
163 if (op == Token::LT) {
164 new_range->AddConstant(-1);
166 }
else if (op == Token::GT || op == Token::GTE) {
167 new_range = range->CopyClearUpper(
graph()->zone());
168 if (op == Token::GT) {
169 new_range->AddConstant(1);
173 if (new_range !=
NULL && !new_range->IsMostGeneric()) {
174 AddRange(value, new_range);
179 void HRangeAnalysisPhase::InferRange(HValue* value) {
180 ASSERT(!value->HasRange());
181 if (!value->representation().IsNone()) {
182 value->ComputeInitialRange(
graph()->zone());
183 Range* range = value->range();
184 TraceRange(
"Initial inferred range of %d (%s) set to [%d,%d]\n",
193 void HRangeAnalysisPhase::RollBackTo(
int index) {
194 ASSERT(index <= changed_ranges_.length());
195 for (
int i = index; i < changed_ranges_.length(); ++i) {
196 changed_ranges_[i]->RemoveLastAddedRange();
198 changed_ranges_.Rewind(index);
202 void HRangeAnalysisPhase::AddRange(HValue* value, Range* range) {
203 Range* original_range = value->range();
204 value->AddNewRange(range,
graph()->zone());
205 changed_ranges_.Add(value, zone());
206 Range* new_range = value->range();
207 TraceRange(
"Updated range of %d set to [%d,%d]\n",
211 if (original_range !=
NULL) {
212 TraceRange(
"Original range was [%d,%d]\n",
213 original_range->lower(),
214 original_range->upper());
216 TraceRange(
"New information was [%d,%d]\n",
222 void HRangeAnalysisPhase::PropagateMinusZeroChecks(HValue* value) {
223 ASSERT(worklist_.is_empty());
226 AddToWorklist(value);
227 while (!worklist_.is_empty()) {
228 value = worklist_.RemoveLast();
230 if (value->IsPhi()) {
232 HPhi* phi = HPhi::cast(value);
233 for (
int i = 0; i < phi->OperandCount(); ++i) {
234 AddToWorklist(phi->OperandAt(i));
236 }
else if (value->IsUnaryMathOperation()) {
237 HUnaryMathOperation* instr = HUnaryMathOperation::cast(value);
238 if (instr->representation().IsSmiOrInteger32() &&
239 !instr->value()->representation().Equals(instr->representation())) {
240 if (instr->value()->range() ==
NULL ||
241 instr->value()->range()->CanBeMinusZero()) {
245 if (instr->RequiredInputRepresentation(0).IsSmiOrInteger32() &&
246 instr->representation().Equals(
247 instr->RequiredInputRepresentation(0))) {
248 AddToWorklist(instr->value());
250 }
else if (value->IsChange()) {
251 HChange* instr = HChange::cast(value);
252 if (!instr->from().IsSmiOrInteger32() &&
253 !instr->CanTruncateToInt32() &&
254 (instr->value()->range() ==
NULL ||
255 instr->value()->range()->CanBeMinusZero())) {
258 }
else if (value->IsForceRepresentation()) {
259 HForceRepresentation* instr = HForceRepresentation::cast(value);
260 AddToWorklist(instr->value());
261 }
else if (value->IsMod()) {
262 HMod* instr = HMod::cast(value);
263 if (instr->range() ==
NULL || instr->range()->CanBeMinusZero()) {
265 AddToWorklist(instr->left());
267 }
else if (value->IsDiv() || value->IsMul()) {
269 if (instr->range() ==
NULL || instr->range()->CanBeMinusZero()) {
272 AddToWorklist(instr->right());
273 AddToWorklist(instr->left());
274 }
else if (value->IsMathFloorOfDiv()) {
275 HMathFloorOfDiv* instr = HMathFloorOfDiv::cast(value);
277 }
else if (value->IsAdd() || value->IsSub()) {
279 if (instr->range() ==
NULL || instr->range()->CanBeMinusZero()) {
282 AddToWorklist(instr->left());
284 }
else if (value->IsMathMinMax()) {
285 HMathMinMax* instr = HMathMinMax::cast(value);
286 AddToWorklist(instr->right());
287 AddToWorklist(instr->left());
291 in_worklist_.
Clear();
293 ASSERT(worklist_.is_empty());
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
static const char * Name(Value tok)
Token::Value token() const
HBasicBlock * FirstSuccessor()
#define ASSERT(condition)
Representation representation() const
static Value ReverseCompareOp(Value op)
bool Equals(const Representation &other) const
bool IsSmiOrInteger32() const
static Value NegateCompareOp(Value op)
static void VPrint(const char *format, va_list args)
int last_changed_range() const
HBasicBlock * block() const
HBasicBlock * SecondSuccessor()
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Pending(HBasicBlock *block, int last_changed_range)
static HValue * cast(HValue *value)