V8 Project
hydrogen-removable-simulates.cc
Go to the documentation of this file.
1 // Copyright 2013 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 
8 
9 namespace v8 {
10 namespace internal {
11 
12 class State : public ZoneObject {
13  public:
14  explicit State(Zone* zone)
15  : zone_(zone), mergelist_(2, zone), first_(true), mode_(NORMAL) { }
16 
17  State* Process(HInstruction* instr, Zone* zone) {
18  if (FLAG_trace_removable_simulates) {
19  PrintF("[%s with state %p in B%d: #%d %s]\n",
20  mode_ == NORMAL ? "processing" : "collecting",
21  reinterpret_cast<void*>(this), instr->block()->block_id(),
22  instr->id(), instr->Mnemonic());
23  }
24  // Forward-merge "trains" of simulates after an instruction with observable
25  // side effects to keep live ranges short.
27  if (instr->IsSimulate()) {
28  HSimulate* current_simulate = HSimulate::cast(instr);
29  if (current_simulate->is_candidate_for_removal() &&
30  !current_simulate->ast_id().IsNone()) {
31  Remember(current_simulate);
32  return this;
33  }
34  }
36  mode_ = NORMAL;
37  }
38  // Ensure there's a non-foldable HSimulate before an HEnterInlined to avoid
39  // folding across HEnterInlined.
40  DCHECK(!(instr->IsEnterInlined() &&
41  HSimulate::cast(instr->previous())->is_candidate_for_removal()));
42  if (instr->IsLeaveInlined() || instr->IsReturn()) {
43  // Never fold simulates from inlined environments into simulates in the
44  // outer environment. Simply remove all accumulated simulates without
45  // merging. This is safe because simulates after instructions with side
46  // effects are never added to the merge list. The same reasoning holds for
47  // return instructions.
49  return this;
50  }
51  if (instr->IsControlInstruction()) {
52  // Merge the accumulated simulates at the end of the block.
54  return this;
55  }
56  if (instr->IsCapturedObject()) {
57  // Do not merge simulates across captured objects - captured objects
58  // change environments during environment replay, and such changes
59  // would not be reflected in the simulate.
61  return this;
62  }
63  // Skip the non-simulates and the first simulate.
64  if (!instr->IsSimulate()) return this;
65  if (first_) {
66  first_ = false;
67  return this;
68  }
69  HSimulate* current_simulate = HSimulate::cast(instr);
70  if (!current_simulate->is_candidate_for_removal()) {
71  Remember(current_simulate);
73  } else if (current_simulate->ast_id().IsNone()) {
74  DCHECK(current_simulate->next()->IsEnterInlined());
76  } else if (current_simulate->previous()->HasObservableSideEffects()) {
77  Remember(current_simulate);
79  } else {
80  Remember(current_simulate);
81  }
82 
83  return this;
84  }
85 
86  static State* Merge(State* succ_state,
87  HBasicBlock* succ_block,
88  State* pred_state,
89  HBasicBlock* pred_block,
90  Zone* zone) {
91  return (succ_state == NULL)
92  ? pred_state->Copy(succ_block, pred_block, zone)
93  : succ_state->Merge(succ_block, pred_state, pred_block, zone);
94  }
95 
96  static State* Finish(State* state, HBasicBlock* block, Zone* zone) {
97  if (FLAG_trace_removable_simulates) {
98  PrintF("[preparing state %p for B%d]\n", reinterpret_cast<void*>(state),
99  block->block_id());
100  }
101  // For our current local analysis, we should not remember simulates across
102  // block boundaries.
103  DCHECK(!state->HasRememberedSimulates());
104  // Nasty heuristic: Never remove the first simulate in a block. This
105  // just so happens to have a beneficial effect on register allocation.
106  state->first_ = true;
107  return state;
108  }
109 
110  private:
111  explicit State(const State& other)
112  : zone_(other.zone_),
113  mergelist_(other.mergelist_, other.zone_),
114  first_(other.first_),
115  mode_(other.mode_) { }
116 
118 
119  bool HasRememberedSimulates() const { return !mergelist_.is_empty(); }
120 
121  void Remember(HSimulate* sim) {
122  mergelist_.Add(sim, zone_);
123  }
124 
125  void FlushSimulates() {
126  if (HasRememberedSimulates()) {
127  mergelist_.RemoveLast()->MergeWith(&mergelist_);
128  }
129  }
130 
132  while (HasRememberedSimulates()) {
133  mergelist_.RemoveLast()->DeleteAndReplaceWith(NULL);
134  }
135  }
136 
137  State* Copy(HBasicBlock* succ_block, HBasicBlock* pred_block, Zone* zone) {
138  State* copy = new(zone) State(*this);
139  if (FLAG_trace_removable_simulates) {
140  PrintF("[copy state %p from B%d to new state %p for B%d]\n",
141  reinterpret_cast<void*>(this), pred_block->block_id(),
142  reinterpret_cast<void*>(copy), succ_block->block_id());
143  }
144  return copy;
145  }
146 
147  State* Merge(HBasicBlock* succ_block,
148  State* pred_state,
149  HBasicBlock* pred_block,
150  Zone* zone) {
151  // For our current local analysis, we should not remember simulates across
152  // block boundaries.
153  DCHECK(!pred_state->HasRememberedSimulates());
155  if (FLAG_trace_removable_simulates) {
156  PrintF("[merge state %p from B%d into %p for B%d]\n",
157  reinterpret_cast<void*>(pred_state), pred_block->block_id(),
158  reinterpret_cast<void*>(this), succ_block->block_id());
159  }
160  return this;
161  }
162 
165  bool first_;
167 };
168 
169 
170 // We don't use effects here.
171 class Effects : public ZoneObject {
172  public:
173  explicit Effects(Zone* zone) { }
174  bool Disabled() { return true; }
175  void Process(HInstruction* instr, Zone* zone) { }
176  void Apply(State* state) { }
177  void Union(Effects* that, Zone* zone) { }
178 };
179 
180 
182  HFlowEngine<State, Effects> engine(graph(), zone());
183  State* state = new(zone()) State(zone());
184  engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), state);
185 }
186 
187 } } // namespace v8::internal
void Union(Effects *that, Zone *zone)
void Process(HInstruction *instr, Zone *zone)
void AnalyzeDominatedBlocks(HBasicBlock *root, State *initial)
HInstruction * previous() const
HGraph * graph() const
Definition: hydrogen.h:2802
HBasicBlock * block() const
const char * Mnemonic() const
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:17
State * Copy(HBasicBlock *succ_block, HBasicBlock *pred_block, Zone *zone)
static State * Finish(State *state, HBasicBlock *block, Zone *zone)
State * Merge(HBasicBlock *succ_block, State *pred_state, HBasicBlock *pred_block, Zone *zone)
State * Process(HInstruction *instr, Zone *zone)
static State * Merge(State *succ_state, HBasicBlock *succ_block, State *pred_state, HBasicBlock *pred_block, Zone *zone)
ZoneList< HSimulate * > mergelist_
enable harmony numeric enable harmony object literal extensions true
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
#define DCHECK(condition)
Definition: logging.h:205
void PrintF(const char *format,...)
Definition: utils.cc:80
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20