V8 Project
v8::internal::HLoadEliminationTable Class Reference
+ Inheritance diagram for v8::internal::HLoadEliminationTable:
+ Collaboration diagram for v8::internal::HLoadEliminationTable:

Public Member Functions

 HLoadEliminationTable (Zone *zone, HAliasAnalyzer *aliasing)
 
HLoadEliminationTableProcess (HInstruction *instr, Zone *zone)
 
- Public Member Functions inherited from v8::internal::ZoneObject
 INLINE (void *operator new(size_t size, Zone *zone))
 
void operator delete (void *, size_t)
 
void operator delete (void *pointer, Zone *zone)
 

Static Public Member Functions

static HLoadEliminationTableMerge (HLoadEliminationTable *succ_state, HBasicBlock *succ_block, HLoadEliminationTable *pred_state, HBasicBlock *pred_block, Zone *zone)
 
static HLoadEliminationTableFinish (HLoadEliminationTable *state, HBasicBlock *block, Zone *zone)
 

Private Member Functions

HLoadEliminationTableCopy (HBasicBlock *succ, HBasicBlock *from_block, Zone *zone)
 
HLoadEliminationTableMerge (HBasicBlock *succ, HLoadEliminationTable *that, HBasicBlock *that_block, Zone *zone)
 
HValueload (HLoadNamedField *instr)
 
HValuestore (HStoreNamedField *instr)
 
void Kill ()
 
void KillOffset (int offset)
 
void KillStore (HStoreNamedField *s)
 
HValueKillIfMisaligned (HStoreNamedField *instr)
 
HFieldApproximationFind (HValue *object, int field)
 
HFieldApproximationFindOrCreate (HValue *object, int field)
 
void KillFieldInternal (HValue *object, int field, HValue *value)
 
bool Equal (HValue *a, HValue *b)
 
HFieldApproximationReuseLastApproximation (int field)
 
int FieldOf (HObjectAccess access)
 
int FieldOf (int offset)
 
void EnsureFields (int num_fields)
 
void Print ()
 

Private Attributes

Zonezone_
 
ZoneList< HFieldApproximation * > fields_
 
HAliasAnalyzeraliasing_
 

Friends

class HLoadEliminationEffects
 
class HLoadEliminationPhase
 

Detailed Description

Definition at line 40 of file hydrogen-load-elimination.cc.

Constructor & Destructor Documentation

◆ HLoadEliminationTable()

v8::internal::HLoadEliminationTable::HLoadEliminationTable ( Zone zone,
HAliasAnalyzer aliasing 
)
inline

Definition at line 42 of file hydrogen-load-elimination.cc.

Referenced by Copy().

+ Here is the caller graph for this function:

Member Function Documentation

◆ Copy()

HLoadEliminationTable* v8::internal::HLoadEliminationTable::Copy ( HBasicBlock *  succ,
HBasicBlock *  from_block,
Zone zone 
)
inlineprivate

Definition at line 144 of file hydrogen-load-elimination.cc.

145  {
146  HLoadEliminationTable* copy =
147  new(zone) HLoadEliminationTable(zone, aliasing_);
148  copy->EnsureFields(fields_.length());
149  for (int i = 0; i < fields_.length(); i++) {
150  copy->fields_[i] = fields_[i] == NULL ? NULL : fields_[i]->Copy(zone);
151  }
152  if (FLAG_trace_load_elimination) {
153  TRACE((" copy-to B%d\n", succ->block_id()));
154  copy->Print();
155  }
156  return copy;
157  }
HLoadEliminationTable(Zone *zone, HAliasAnalyzer *aliasing)
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 TRACE(x)

References aliasing_, EnsureFields(), fields_, HLoadEliminationTable(), NULL, Print(), and TRACE.

Referenced by Merge().

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

◆ EnsureFields()

void v8::internal::HLoadEliminationTable::EnsureFields ( int  num_fields)
inlineprivate

Definition at line 410 of file hydrogen-load-elimination.cc.

410  {
411  if (fields_.length() < num_fields) {
412  fields_.AddBlock(NULL, num_fields - fields_.length(), zone_);
413  }
414  }

References fields_, NULL, and zone_.

Referenced by Copy(), and FindOrCreate().

+ Here is the caller graph for this function:

◆ Equal()

bool v8::internal::HLoadEliminationTable::Equal ( HValue a,
HValue b 
)
inlineprivate

Definition at line 372 of file hydrogen-load-elimination.cc.

372  {
373  if (a == b) return true;
374  if (a != NULL && b != NULL && a->CheckFlag(HValue::kUseGVN)) {
375  return a->Equals(b);
376  }
377  return false;
378  }

References v8::internal::HValue::CheckFlag(), v8::internal::HValue::Equals(), v8::internal::HValue::kUseGVN, and NULL.

Referenced by KillFieldInternal(), Merge(), and store().

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

◆ FieldOf() [1/2]

int v8::internal::HLoadEliminationTable::FieldOf ( HObjectAccess  access)
inlineprivate

Definition at line 397 of file hydrogen-load-elimination.cc.

397  {
398  return access.IsInobject() ? FieldOf(access.offset()) : -1;
399  }

Referenced by KillOffset(), KillStore(), load(), Process(), and store().

+ Here is the caller graph for this function:

◆ FieldOf() [2/2]

int v8::internal::HLoadEliminationTable::FieldOf ( int  offset)
inlineprivate

Definition at line 402 of file hydrogen-load-elimination.cc.

402  {
403  if (offset >= kMaxTrackedFields * kPointerSize) return -1;
404  // TODO(titzer): track misaligned loads in a separate list?
405  if ((offset % kPointerSize) != 0) return -1; // Ignore misaligned accesses.
406  return offset / kPointerSize;
407  }
const int kPointerSize
Definition: globals.h:129

References v8::internal::kMaxTrackedFields, and v8::internal::kPointerSize.

◆ Find()

HFieldApproximation* v8::internal::HLoadEliminationTable::Find ( HValue object,
int  field 
)
inlineprivate

Definition at line 307 of file hydrogen-load-elimination.cc.

307  {
308  // Search for a field approximation for this object.
309  HFieldApproximation* approx = fields_[field];
310  while (approx != NULL) {
311  if (aliasing_->MustAlias(object, approx->object_)) return approx;
312  approx = approx->next_;
313  }
314  return NULL;
315  }
bool MustAlias(HValue *a, HValue *b)

References aliasing_, fields_, v8::internal::HAliasAnalyzer::MustAlias(), v8::internal::HFieldApproximation::next_, NULL, and v8::internal::HFieldApproximation::object_.

Referenced by Merge().

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

◆ FindOrCreate()

HFieldApproximation* v8::internal::HLoadEliminationTable::FindOrCreate ( HValue object,
int  field 
)
inlineprivate

Definition at line 318 of file hydrogen-load-elimination.cc.

318  {
319  EnsureFields(field + 1);
320 
321  // Search for a field approximation for this object.
322  HFieldApproximation* approx = fields_[field];
323  int count = 0;
324  while (approx != NULL) {
325  if (aliasing_->MustAlias(object, approx->object_)) return approx;
326  count++;
327  approx = approx->next_;
328  }
329 
330  if (count >= kMaxTrackedObjects) {
331  // Pull the last entry off the end and repurpose it for this object.
332  approx = ReuseLastApproximation(field);
333  } else {
334  // Allocate a new entry.
335  approx = new(zone_) HFieldApproximation();
336  }
337 
338  // Insert the entry at the head of the list.
339  approx->object_ = object;
340  approx->last_value_ = NULL;
341  approx->next_ = fields_[field];
342  fields_[field] = approx;
343 
344  return approx;
345  }
HFieldApproximation * ReuseLastApproximation(int field)
static const int kMaxTrackedObjects

References aliasing_, EnsureFields(), fields_, v8::internal::kMaxTrackedObjects, v8::internal::HFieldApproximation::last_value_, v8::internal::HAliasAnalyzer::MustAlias(), v8::internal::HFieldApproximation::next_, NULL, v8::internal::HFieldApproximation::object_, ReuseLastApproximation(), and zone_.

Referenced by load(), and store().

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

◆ Finish()

static HLoadEliminationTable* v8::internal::HLoadEliminationTable::Finish ( HLoadEliminationTable state,
HBasicBlock *  block,
Zone zone 
)
inlinestatic

Definition at line 135 of file hydrogen-load-elimination.cc.

137  {
138  DCHECK(state != NULL);
139  return state;
140  }
#define DCHECK(condition)
Definition: logging.h:205

References DCHECK, and NULL.

◆ Kill()

void v8::internal::HLoadEliminationTable::Kill ( )
inlineprivate

Definition at line 264 of file hydrogen-load-elimination.cc.

264  {
265  fields_.Rewind(0);
266  }

References fields_.

Referenced by v8::internal::HLoadEliminationEffects::Apply(), Process(), and v8::internal::HLoadEliminationPhase::Run().

+ Here is the caller graph for this function:

◆ KillFieldInternal()

void v8::internal::HLoadEliminationTable::KillFieldInternal ( HValue object,
int  field,
HValue value 
)
inlineprivate

Definition at line 349 of file hydrogen-load-elimination.cc.

349  {
350  if (field >= fields_.length()) return; // Nothing to do.
351 
352  HFieldApproximation* approx = fields_[field];
353  HFieldApproximation* prev = NULL;
354  while (approx != NULL) {
355  if (aliasing_->MayAlias(object, approx->object_)) {
356  if (!Equal(approx->last_value_, value)) {
357  // Kill an aliasing entry that doesn't agree on the value.
358  if (prev != NULL) {
359  prev->next_ = approx->next_;
360  } else {
361  fields_[field] = approx->next_;
362  }
363  approx = approx->next_;
364  continue;
365  }
366  }
367  prev = approx;
368  approx = approx->next_;
369  }
370  }
bool MayAlias(HValue *a, HValue *b)

References aliasing_, Equal(), fields_, v8::internal::HFieldApproximation::last_value_, v8::internal::HAliasAnalyzer::MayAlias(), v8::internal::HFieldApproximation::next_, NULL, and v8::internal::HFieldApproximation::object_.

Referenced by KillIfMisaligned(), KillStore(), Process(), and store().

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

◆ KillIfMisaligned()

HValue* v8::internal::HLoadEliminationTable::KillIfMisaligned ( HStoreNamedField *  instr)
inlineprivate

Definition at line 287 of file hydrogen-load-elimination.cc.

287  {
288  HObjectAccess access = instr->access();
289  if (access.IsInobject()) {
290  int offset = access.offset();
291  if ((offset % kPointerSize) != 0) {
292  // Kill the field containing the first word of the access.
293  HValue* object = instr->object()->ActualValue();
294  int field = offset / kPointerSize;
295  KillFieldInternal(object, field, NULL);
296 
297  // Kill the next field in case of overlap.
298  int size = access.representation().size();
299  int next_field = (offset + size - 1) / kPointerSize;
300  if (next_field != field) KillFieldInternal(object, next_field, NULL);
301  }
302  }
303  return instr;
304  }
void KillFieldInternal(HValue *object, int field, HValue *value)
enable harmony numeric enable harmony object literal extensions Optimize object size

References v8::internal::HValue::ActualValue(), KillFieldInternal(), v8::internal::kPointerSize, NULL, and size.

Referenced by KillStore(), and store().

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

◆ KillOffset()

void v8::internal::HLoadEliminationTable::KillOffset ( int  offset)
inlineprivate

Definition at line 269 of file hydrogen-load-elimination.cc.

269  {
270  int field = FieldOf(offset);
271  if (field >= 0 && field < fields_.length()) {
272  fields_[field] = NULL;
273  }
274  }

References FieldOf(), fields_, and NULL.

Referenced by v8::internal::HLoadEliminationEffects::Apply(), and Process().

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

◆ KillStore()

void v8::internal::HLoadEliminationTable::KillStore ( HStoreNamedField *  s)
inlineprivate

Definition at line 277 of file hydrogen-load-elimination.cc.

277  {
278  int field = FieldOf(s->access());
279  if (field >= 0) {
280  KillFieldInternal(s->object()->ActualValue(), field, s->value());
281  } else {
282  KillIfMisaligned(s);
283  }
284  }
HValue * KillIfMisaligned(HStoreNamedField *instr)

References FieldOf(), KillFieldInternal(), and KillIfMisaligned().

Referenced by v8::internal::HLoadEliminationEffects::Apply().

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

◆ load()

HValue* v8::internal::HLoadEliminationTable::load ( HLoadNamedField *  instr)
inlineprivate

Definition at line 201 of file hydrogen-load-elimination.cc.

201  {
202  // There must be no loads from non observable in-object properties.
203  DCHECK(!instr->access().IsInobject() ||
204  instr->access().existing_inobject_property());
205 
206  int field = FieldOf(instr->access());
207  if (field < 0) return instr;
208 
209  HValue* object = instr->object()->ActualValue();
210  HFieldApproximation* approx = FindOrCreate(object, field);
211 
212  if (approx->last_value_ == NULL) {
213  // Load is not redundant. Fill out a new entry.
214  approx->last_value_ = instr;
215  return instr;
216  } else if (approx->last_value_->block()->EqualToOrDominates(
217  instr->block())) {
218  // Eliminate the load. Reuse previously stored value or load instruction.
219  return approx->last_value_;
220  } else {
221  return instr;
222  }
223  }
HFieldApproximation * FindOrCreate(HValue *object, int field)

References v8::internal::HValue::ActualValue(), v8::internal::HValue::block(), DCHECK, FieldOf(), FindOrCreate(), v8::internal::HFieldApproximation::last_value_, and NULL.

Referenced by Process().

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

◆ Merge() [1/2]

HLoadEliminationTable* v8::internal::HLoadEliminationTable::Merge ( HBasicBlock *  succ,
HLoadEliminationTable that,
HBasicBlock *  that_block,
Zone zone 
)
inlineprivate

Definition at line 160 of file hydrogen-load-elimination.cc.

161  {
162  if (that->fields_.length() < fields_.length()) {
163  // Drop fields not in the other table.
164  fields_.Rewind(that->fields_.length());
165  }
166  for (int i = 0; i < fields_.length(); i++) {
167  // Merge the field approximations for like fields.
168  HFieldApproximation* approx = fields_[i];
169  HFieldApproximation* prev = NULL;
170  while (approx != NULL) {
171  // TODO(titzer): Merging is O(N * M); sort?
172  HFieldApproximation* other = that->Find(approx->object_, i);
173  if (other == NULL || !Equal(approx->last_value_, other->last_value_)) {
174  // Kill an entry that doesn't agree with the other value.
175  if (prev != NULL) {
176  prev->next_ = approx->next_;
177  } else {
178  fields_[i] = approx->next_;
179  }
180  approx = approx->next_;
181  continue;
182  }
183  prev = approx;
184  approx = approx->next_;
185  }
186  }
187  if (FLAG_trace_load_elimination) {
188  TRACE((" merge-to B%d\n", succ->block_id()));
189  Print();
190  }
191  return this;
192  }

References Equal(), fields_, Find(), v8::internal::HFieldApproximation::last_value_, v8::internal::HFieldApproximation::next_, NULL, v8::internal::HFieldApproximation::object_, Print(), and TRACE.

+ Here is the call graph for this function:

◆ Merge() [2/2]

static HLoadEliminationTable* v8::internal::HLoadEliminationTable::Merge ( HLoadEliminationTable succ_state,
HBasicBlock *  succ_block,
HLoadEliminationTable pred_state,
HBasicBlock *  pred_block,
Zone zone 
)
inlinestatic

Definition at line 120 of file hydrogen-load-elimination.cc.

124  {
125  DCHECK(pred_state != NULL);
126  if (succ_state == NULL) {
127  return pred_state->Copy(succ_block, pred_block, zone);
128  } else {
129  return succ_state->Merge(succ_block, pred_state, pred_block, zone);
130  }
131  }

References Copy(), DCHECK, Merge(), and NULL.

Referenced by Merge().

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

◆ Print()

void v8::internal::HLoadEliminationTable::Print ( )
inlineprivate

Definition at line 417 of file hydrogen-load-elimination.cc.

417  {
418  for (int i = 0; i < fields_.length(); i++) {
419  PrintF(" field %d: ", i);
420  for (HFieldApproximation* a = fields_[i]; a != NULL; a = a->next_) {
421  PrintF("[o%d =", a->object_->id());
422  if (a->last_value_ != NULL) PrintF(" v%d", a->last_value_->id());
423  PrintF("] ");
424  }
425  PrintF("\n");
426  }
427  }
void PrintF(const char *format,...)
Definition: utils.cc:80

References fields_, NULL, and v8::internal::PrintF().

Referenced by Copy(), and Merge().

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

◆ Process()

HLoadEliminationTable* v8::internal::HLoadEliminationTable::Process ( HInstruction instr,
Zone zone 
)
inline

Definition at line 46 of file hydrogen-load-elimination.cc.

46  {
47  switch (instr->opcode()) {
48  case HValue::kLoadNamedField: {
49  HLoadNamedField* l = HLoadNamedField::cast(instr);
50  TRACE((" process L%d field %d (o%d)\n",
51  instr->id(),
52  FieldOf(l->access()),
53  l->object()->ActualValue()->id()));
54  HValue* result = load(l);
55  if (result != instr && l->CanBeReplacedWith(result)) {
56  // The load can be replaced with a previous load or a value.
57  TRACE((" replace L%d -> v%d\n", instr->id(), result->id()));
58  instr->DeleteAndReplaceWith(result);
59  }
60  break;
61  }
62  case HValue::kStoreNamedField: {
63  HStoreNamedField* s = HStoreNamedField::cast(instr);
64  TRACE((" process S%d field %d (o%d) = v%d\n",
65  instr->id(),
66  FieldOf(s->access()),
67  s->object()->ActualValue()->id(),
68  s->value()->id()));
69  HValue* result = store(s);
70  if (result == NULL) {
71  // The store is redundant. Remove it.
72  TRACE((" remove S%d\n", instr->id()));
73  instr->DeleteAndReplaceWith(NULL);
74  }
75  break;
76  }
77  case HValue::kTransitionElementsKind: {
78  HTransitionElementsKind* t = HTransitionElementsKind::cast(instr);
79  HValue* object = t->object()->ActualValue();
82  break;
83  }
84  default: {
85  if (instr->CheckChangesFlag(kInobjectFields)) {
86  TRACE((" kill-all i%d\n", instr->id()));
87  Kill();
88  break;
89  }
90  if (instr->CheckChangesFlag(kMaps)) {
91  TRACE((" kill-maps i%d\n", instr->id()));
93  }
94  if (instr->CheckChangesFlag(kElementsKind)) {
95  TRACE((" kill-elements-kind i%d\n", instr->id()));
98  }
99  if (instr->CheckChangesFlag(kElementsPointer)) {
100  TRACE((" kill-elements i%d\n", instr->id()));
102  }
103  if (instr->CheckChangesFlag(kOsrEntries)) {
104  TRACE((" kill-osr i%d\n", instr->id()));
105  Kill();
106  }
107  }
108  // Improvements possible:
109  // - learn from HCheckMaps for field 0
110  // - remove unobservable stores (write-after-write)
111  // - track cells
112  // - track globals
113  // - track roots
114  }
115  return this;
116  }
HValue * store(HStoreNamedField *instr)
HValue * load(HLoadNamedField *instr)
static const int kMapOffset
Definition: objects.h:1427
static const int kElementsOffset
Definition: objects.h:2194

References v8::internal::HValue::ActualValue(), v8::internal::HValue::CheckChangesFlag(), v8::internal::HValue::DeleteAndReplaceWith(), FieldOf(), v8::internal::HValue::id(), v8::internal::JSObject::kElementsOffset, Kill(), KillFieldInternal(), KillOffset(), v8::internal::HeapObject::kMapOffset, load(), NULL, v8::internal::HValue::opcode(), store(), and TRACE.

+ Here is the call graph for this function:

◆ ReuseLastApproximation()

HFieldApproximation* v8::internal::HLoadEliminationTable::ReuseLastApproximation ( int  field)
inlineprivate

Definition at line 383 of file hydrogen-load-elimination.cc.

383  {
384  HFieldApproximation* approx = fields_[field];
385  DCHECK(approx != NULL);
386 
387  HFieldApproximation* prev = NULL;
388  while (approx->next_ != NULL) {
389  prev = approx;
390  approx = approx->next_;
391  }
392  if (prev != NULL) prev->next_ = NULL;
393  return approx;
394  }

References DCHECK, fields_, v8::internal::HFieldApproximation::next_, and NULL.

Referenced by FindOrCreate().

+ Here is the caller graph for this function:

◆ store()

HValue* v8::internal::HLoadEliminationTable::store ( HStoreNamedField *  instr)
inlineprivate

Definition at line 229 of file hydrogen-load-elimination.cc.

229  {
230  if (instr->access().IsInobject() &&
231  !instr->access().existing_inobject_property()) {
232  TRACE((" skipping non existing property initialization store\n"));
233  return instr;
234  }
235 
236  int field = FieldOf(instr->access());
237  if (field < 0) return KillIfMisaligned(instr);
238 
239  HValue* object = instr->object()->ActualValue();
240  HValue* value = instr->value();
241 
242  if (instr->has_transition()) {
243  // A transition introduces a new field and alters the map of the object.
244  // Since the field in the object is new, it cannot alias existing entries.
245  // TODO(titzer): introduce a constant for the new map and remember it.
247  } else {
248  // Kill non-equivalent may-alias entries.
249  KillFieldInternal(object, field, value);
250  }
251  HFieldApproximation* approx = FindOrCreate(object, field);
252 
253  if (Equal(approx->last_value_, value)) {
254  // The store is redundant because the field already has this value.
255  return NULL;
256  } else {
257  // The store is not redundant. Update the entry.
258  approx->last_value_ = value;
259  return instr;
260  }
261  }

References v8::internal::HValue::ActualValue(), Equal(), FieldOf(), FindOrCreate(), KillFieldInternal(), KillIfMisaligned(), v8::internal::HeapObject::kMapOffset, v8::internal::HFieldApproximation::last_value_, NULL, and TRACE.

Referenced by Process().

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

Friends And Related Function Documentation

◆ HLoadEliminationEffects

friend class HLoadEliminationEffects
friend

Definition at line 194 of file hydrogen-load-elimination.cc.

◆ HLoadEliminationPhase

friend class HLoadEliminationPhase
friend

Definition at line 195 of file hydrogen-load-elimination.cc.

Member Data Documentation

◆ aliasing_

HAliasAnalyzer* v8::internal::HLoadEliminationTable::aliasing_
private

Definition at line 431 of file hydrogen-load-elimination.cc.

Referenced by Copy(), Find(), FindOrCreate(), and KillFieldInternal().

◆ fields_

ZoneList<HFieldApproximation*> v8::internal::HLoadEliminationTable::fields_
private

◆ zone_

Zone* v8::internal::HLoadEliminationTable::zone_
private

Definition at line 429 of file hydrogen-load-elimination.cc.

Referenced by EnsureFields(), and FindOrCreate().


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