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

Public Member Functions

 HCheckTable (HCheckEliminationPhase *phase)
 
HCheckTableProcess (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 HCheckTableMerge (HCheckTable *succ_state, HBasicBlock *succ_block, HCheckTable *pred_state, HBasicBlock *pred_block, Zone *zone)
 
static HCheckTableFinish (HCheckTable *state, HBasicBlock *block, Zone *zone)
 

Static Public Attributes

static const int kMaxTrackedObjects = 16
 

Private Member Functions

HCheckTableCopy (HBasicBlock *succ, HBasicBlock *from_block, Zone *zone)
 
HCheckTableMerge (HBasicBlock *succ, HCheckTable *that, HBasicBlock *pred_block, Zone *zone)
 
void ReduceCheckMaps (HCheckMaps *instr)
 
void ReduceCheckInstanceType (HCheckInstanceType *instr)
 
void ReduceLoadNamedField (HLoadNamedField *instr)
 
void ReduceCheckHeapObject (HCheckHeapObject *instr)
 
void ReduceStoreNamedField (HStoreNamedField *instr)
 
void ReduceCompareMap (HCompareMap *instr)
 
void ReduceCompareObjectEqAndBranch (HCompareObjectEqAndBranch *instr)
 
void ReduceIsStringAndBranch (HIsStringAndBranch *instr)
 
void ReduceTransitionElementsKind (HTransitionElementsKind *instr)
 
void EnsureChecked (HCheckTableEntry *entry, HValue *value, HInstruction *instr)
 
void Kill ()
 
void KillUnstableEntries ()
 
void Kill (HValue *object)
 
void Compact ()
 
HCheckTableEntryFind (HValue *object)
 
void Insert (HValue *object, HInstruction *check, Unique< Map > map, HCheckTableEntry::State state)
 
void Insert (HValue *object, HInstruction *check, MapSet maps, HCheckTableEntry::State state)
 
Zonezone () const
 
MapSet string_maps () const
 
 STATIC_ASSERT (kMaxTrackedObjects<(1<< 15))
 

Static Private Member Functions

static void Print (HCheckTable *table)
 

Private Attributes

HCheckEliminationPhasephase_
 
HCheckTableEntry entries_ [kMaxTrackedObjects]
 
int16_t cursor_
 
int16_t size_
 

Friends

class HCheckMapsEffects
 
class HCheckEliminationPhase
 

Detailed Description

Definition at line 74 of file hydrogen-check-elimination.cc.

Constructor & Destructor Documentation

◆ HCheckTable()

v8::internal::HCheckTable::HCheckTable ( HCheckEliminationPhase phase)
inlineexplicit

Definition at line 78 of file hydrogen-check-elimination.cc.

Referenced by Copy().

+ Here is the caller graph for this function:

Member Function Documentation

◆ Compact()

void v8::internal::HCheckTable::Compact ( )
inlineprivate

Definition at line 697 of file hydrogen-check-elimination.cc.

697  {
698  // First, compact the array in place.
699  int max = size_, dest = 0, old_cursor = cursor_;
700  for (int i = 0; i < max; i++) {
701  if (entries_[i].object_ != NULL) {
702  if (dest != i) entries_[dest] = entries_[i];
703  dest++;
704  } else {
705  if (i < old_cursor) cursor_--;
706  size_--;
707  }
708  }
709  DCHECK(size_ == dest);
710  DCHECK(cursor_ <= size_);
711 
712  // Preserve the age of the entries by moving the older entries to the end.
713  if (cursor_ == size_) return; // Cursor already points at end.
714  if (cursor_ != 0) {
715  // | L = oldest | R = newest | |
716  // ^ cursor ^ size ^ MAX
717  HCheckTableEntry tmp_entries[kMaxTrackedObjects];
718  int L = cursor_;
719  int R = size_ - cursor_;
720 
721  MemMove(&tmp_entries[0], &entries_[0], L * sizeof(HCheckTableEntry));
722  MemMove(&entries_[0], &entries_[L], R * sizeof(HCheckTableEntry));
723  MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry));
724  }
725 
726  cursor_ = size_; // Move cursor to end.
727  }
HCheckTableEntry entries_[kMaxTrackedObjects]
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 MemMove(void *dest, const void *src, size_t size)
Definition: utils.h:353

References cursor_, DCHECK, entries_, kMaxTrackedObjects, v8::internal::L, v8::internal::MemMove(), NULL, and size_.

Referenced by Kill(), KillUnstableEntries(), Merge(), and ReduceCheckMaps().

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

◆ Copy()

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

Definition at line 176 of file hydrogen-check-elimination.cc.

176  {
177  HCheckTable* copy = new(zone) HCheckTable(phase_);
178  for (int i = 0; i < size_; i++) {
179  HCheckTableEntry* old_entry = &entries_[i];
180  DCHECK(old_entry->maps_->size() > 0);
181  HCheckTableEntry* new_entry = &copy->entries_[i];
182  new_entry->object_ = old_entry->object_;
183  new_entry->maps_ = old_entry->maps_;
184  new_entry->state_ = old_entry->state_;
185  // Keep the check if the existing check's block dominates the successor.
186  if (old_entry->check_ != NULL &&
187  old_entry->check_->block()->Dominates(succ)) {
188  new_entry->check_ = old_entry->check_;
189  } else {
190  // Leave it NULL till we meet a new check instruction for this object
191  // in the control flow.
192  new_entry->check_ = NULL;
193  }
194  }
195  copy->cursor_ = cursor_;
196  copy->size_ = size_;
197 
198  // Create entries for succ block's phis.
199  if (!succ->IsLoopHeader() && succ->phis()->length() > 0) {
200  int pred_index = succ->PredecessorIndexOf(from_block);
201  for (int phi_index = 0;
202  phi_index < succ->phis()->length();
203  ++phi_index) {
204  HPhi* phi = succ->phis()->at(phi_index);
205  HValue* phi_operand = phi->OperandAt(pred_index);
206 
207  HCheckTableEntry* pred_entry = copy->Find(phi_operand);
208  if (pred_entry != NULL) {
209  // Create an entry for a phi in the table.
210  copy->Insert(phi, NULL, pred_entry->maps_, pred_entry->state_);
211  }
212  }
213  }
214 
215  // Branch-sensitive analysis for certain comparisons may add more facts
216  // to the state for the successor on the true branch.
217  bool learned = false;
218  if (succ->predecessors()->length() == 1) {
219  HControlInstruction* end = succ->predecessors()->at(0)->end();
220  bool is_true_branch = end->SuccessorAt(0) == succ;
221  if (end->IsCompareMap()) {
222  HCompareMap* cmp = HCompareMap::cast(end);
223  HValue* object = cmp->value()->ActualValue();
224  HCheckTableEntry* entry = copy->Find(object);
225  if (is_true_branch) {
226  HCheckTableEntry::State state = cmp->map_is_stable()
229  // Learn on the true branch of if(CompareMap(x)).
230  if (entry == NULL) {
231  copy->Insert(object, cmp, cmp->map(), state);
232  } else {
233  entry->maps_ = new(zone) UniqueSet<Map>(cmp->map(), zone);
234  entry->check_ = cmp;
235  entry->state_ = state;
236  }
237  } else {
238  // Learn on the false branch of if(CompareMap(x)).
239  if (entry != NULL) {
240  EnsureChecked(entry, object, cmp);
241  UniqueSet<Map>* maps = entry->maps_->Copy(zone);
242  maps->Remove(cmp->map());
243  entry->maps_ = maps;
245  }
246  }
247  learned = true;
248  } else if (is_true_branch && end->IsCompareObjectEqAndBranch()) {
249  // Learn on the true branch of if(CmpObjectEq(x, y)).
250  HCompareObjectEqAndBranch* cmp =
252  HValue* left = cmp->left()->ActualValue();
253  HValue* right = cmp->right()->ActualValue();
254  HCheckTableEntry* le = copy->Find(left);
255  HCheckTableEntry* re = copy->Find(right);
256  if (le == NULL) {
257  if (re != NULL) {
258  copy->Insert(left, NULL, re->maps_, re->state_);
259  }
260  } else if (re == NULL) {
261  copy->Insert(right, NULL, le->maps_, le->state_);
262  } else {
263  EnsureChecked(le, cmp->left(), cmp);
264  EnsureChecked(re, cmp->right(), cmp);
265  le->maps_ = re->maps_ = le->maps_->Intersect(re->maps_, zone);
266  le->state_ = re->state_ = HCheckTableEntry::StateMerge(
267  le->state_, re->state_);
270  }
271  learned = true;
272  } else if (end->IsIsStringAndBranch()) {
273  HIsStringAndBranch* cmp = HIsStringAndBranch::cast(end);
274  HValue* object = cmp->value()->ActualValue();
275  HCheckTableEntry* entry = copy->Find(object);
276  if (is_true_branch) {
277  // Learn on the true branch of if(IsString(x)).
278  if (entry == NULL) {
279  copy->Insert(object, NULL, string_maps(),
281  } else {
282  EnsureChecked(entry, object, cmp);
283  entry->maps_ = entry->maps_->Intersect(string_maps(), zone);
285  }
286  } else {
287  // Learn on the false branch of if(IsString(x)).
288  if (entry != NULL) {
289  EnsureChecked(entry, object, cmp);
290  entry->maps_ = entry->maps_->Subtract(string_maps(), zone);
292  }
293  }
294  }
295  // Learning on false branches requires storing negative facts.
296  }
297 
298  if (FLAG_trace_check_elimination) {
299  PrintF("B%d checkmaps-table %s from B%d:\n",
300  succ->block_id(),
301  learned ? "learned" : "copied",
302  from_block->block_id());
303  Print(copy);
304  }
305 
306  return copy;
307  }
void EnsureChecked(HCheckTableEntry *entry, HValue *value, HInstruction *instr)
static void Print(HCheckTable *table)
HCheckTable(HCheckEliminationPhase *phase)
static HValue * cast(HValue *value)
#define DCHECK_NE(v1, v2)
Definition: logging.h:207
void PrintF(const char *format,...)
Definition: utils.cc:80
static State StateMerge(State state1, State state2)

References v8::internal::HValue::ActualValue(), v8::internal::HValue::block(), v8::internal::HValue::cast(), v8::internal::HCheckTableEntry::check_, v8::internal::HCheckTableEntry::CHECKED, v8::internal::HCheckTableEntry::CHECKED_STABLE, cursor_, DCHECK, DCHECK_NE, EnsureChecked(), entries_, Find(), HCheckTable(), Insert(), v8::internal::le, v8::internal::HCompareObjectEqAndBranch::left(), v8::internal::HCheckTableEntry::maps_, NULL, v8::internal::HCheckTableEntry::object_, v8::internal::HValue::OperandAt(), phase_, Print(), v8::internal::PrintF(), v8::internal::HCompareObjectEqAndBranch::right(), size_, v8::internal::HCheckTableEntry::state_, v8::internal::HCheckTableEntry::StateMerge(), string_maps(), v8::internal::HControlInstruction::SuccessorAt(), v8::internal::HCheckTableEntry::UNCHECKED_STABLE, and zone().

Referenced by Merge().

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

◆ EnsureChecked()

void v8::internal::HCheckTable::EnsureChecked ( HCheckTableEntry entry,
HValue value,
HInstruction instr 
)
inlineprivate

Definition at line 646 of file hydrogen-check-elimination.cc.

648  {
649  if (entry->state_ != HCheckTableEntry::UNCHECKED_STABLE) return;
650  HGraph* graph = instr->block()->graph();
651  HCheckMaps* check = HCheckMaps::CreateAndInsertBefore(
652  graph->zone(), value, entry->maps_->Copy(graph->zone()), true, instr);
653  check->MarkAsStabilityCheck();
654  entry->state_ = HCheckTableEntry::CHECKED_STABLE;
655  entry->check_ = NULL;
656  }

References v8::internal::HValue::block(), v8::internal::HCheckTableEntry::check_, v8::internal::HCheckTableEntry::CHECKED_STABLE, v8::internal::HCheckTableEntry::maps_, NULL, v8::internal::HCheckTableEntry::state_, and v8::internal::HCheckTableEntry::UNCHECKED_STABLE.

Referenced by Copy(), ReduceCheckInstanceType(), ReduceCompareMap(), ReduceCompareObjectEqAndBranch(), ReduceIsStringAndBranch(), ReduceLoadNamedField(), and ReduceTransitionElementsKind().

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

◆ Find()

HCheckTableEntry* v8::internal::HCheckTable::Find ( HValue object)
inlineprivate

Definition at line 754 of file hydrogen-check-elimination.cc.

754  {
755  for (int i = size_ - 1; i >= 0; i--) {
756  // Search from most-recently-inserted to least-recently-inserted.
757  HCheckTableEntry* entry = &entries_[i];
758  DCHECK(entry->object_ != NULL);
759  if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry;
760  }
761  return NULL;
762  }
bool MustAlias(HValue *a, HValue *b)

References v8::internal::HCheckEliminationPhase::aliasing_, DCHECK, entries_, v8::internal::HAliasAnalyzer::MustAlias(), NULL, v8::internal::HCheckTableEntry::object_, phase_, and size_.

Referenced by Copy(), Kill(), Merge(), ReduceCheckHeapObject(), ReduceCheckInstanceType(), ReduceCheckMaps(), ReduceCompareMap(), ReduceCompareObjectEqAndBranch(), ReduceIsStringAndBranch(), ReduceLoadNamedField(), and ReduceTransitionElementsKind().

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

◆ Finish()

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

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

161  {
162  if (state == NULL) {
163  block->MarkUnreachable();
164  } else if (block->IsUnreachable()) {
165  state = NULL;
166  }
167  if (FLAG_trace_check_elimination) {
168  PrintF("Processing B%d, checkmaps-table:\n", block->block_id());
169  Print(state);
170  }
171  return state;
172  }

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

+ Here is the call graph for this function:

◆ Insert() [1/2]

void v8::internal::HCheckTable::Insert ( HValue object,
HInstruction check,
MapSet  maps,
HCheckTableEntry::State  state 
)
inlineprivate

Definition at line 771 of file hydrogen-check-elimination.cc.

774  {
775  DCHECK(state != HCheckTableEntry::UNCHECKED_STABLE || check == NULL);
776  HCheckTableEntry* entry = &entries_[cursor_++];
777  entry->object_ = object;
778  entry->check_ = check;
779  entry->maps_ = maps;
780  entry->state_ = state;
781  // If the table becomes full, wrap around and overwrite older entries.
782  if (cursor_ == kMaxTrackedObjects) cursor_ = 0;
783  if (size_ < kMaxTrackedObjects) size_++;
784  }

References v8::internal::HCheckTableEntry::check_, cursor_, DCHECK, entries_, kMaxTrackedObjects, v8::internal::HCheckTableEntry::maps_, NULL, v8::internal::HCheckTableEntry::object_, size_, v8::internal::HCheckTableEntry::state_, and v8::internal::HCheckTableEntry::UNCHECKED_STABLE.

◆ Insert() [2/2]

void v8::internal::HCheckTable::Insert ( HValue object,
HInstruction check,
Unique< Map map,
HCheckTableEntry::State  state 
)
inlineprivate

Definition at line 764 of file hydrogen-check-elimination.cc.

767  {
768  Insert(object, check, new(zone()) UniqueSet<Map>(map, zone()), state);
769  }
void Insert(HValue *object, HInstruction *check, Unique< Map > map, HCheckTableEntry::State state)
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 map

References map, and zone().

Referenced by Copy(), ReduceCheckInstanceType(), ReduceCheckMaps(), ReduceLoadNamedField(), and ReduceStoreNamedField().

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

◆ Kill() [1/2]

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

Definition at line 659 of file hydrogen-check-elimination.cc.

659  {
660  size_ = 0;
661  cursor_ = 0;
662  }

References cursor_, and size_.

Referenced by v8::internal::HCheckMapsEffects::Apply(), Process(), ReduceStoreNamedField(), and v8::internal::HCheckEliminationPhase::Run().

+ Here is the caller graph for this function:

◆ Kill() [2/2]

void v8::internal::HCheckTable::Kill ( HValue object)
inlineprivate

Definition at line 683 of file hydrogen-check-elimination.cc.

683  {
684  bool compact = false;
685  for (int i = 0; i < size_; i++) {
686  HCheckTableEntry* entry = &entries_[i];
687  DCHECK(entry->object_ != NULL);
688  if (phase_->aliasing_->MayAlias(entry->object_, object)) {
689  entry->object_ = NULL;
690  compact = true;
691  }
692  }
693  if (compact) Compact();
694  DCHECK(Find(object) == NULL);
695  }
bool MayAlias(HValue *a, HValue *b)
HCheckTableEntry * Find(HValue *object)

References v8::internal::HCheckEliminationPhase::aliasing_, Compact(), DCHECK, entries_, Find(), v8::internal::HAliasAnalyzer::MayAlias(), NULL, v8::internal::HCheckTableEntry::object_, phase_, and size_.

+ Here is the call graph for this function:

◆ KillUnstableEntries()

void v8::internal::HCheckTable::KillUnstableEntries ( )
inlineprivate

Definition at line 665 of file hydrogen-check-elimination.cc.

665  {
666  bool compact = false;
667  for (int i = 0; i < size_; ++i) {
668  HCheckTableEntry* entry = &entries_[i];
669  DCHECK_NOT_NULL(entry->object_);
670  if (entry->state_ == HCheckTableEntry::CHECKED) {
671  entry->object_ = NULL;
672  compact = true;
673  } else {
674  // All checked stable entries become unchecked stable.
675  entry->state_ = HCheckTableEntry::UNCHECKED_STABLE;
676  entry->check_ = NULL;
677  }
678  }
679  if (compact) Compact();
680  }
#define DCHECK_NOT_NULL(p)
Definition: logging.h:213

References v8::internal::HCheckTableEntry::check_, v8::internal::HCheckTableEntry::CHECKED, Compact(), DCHECK_NOT_NULL, entries_, NULL, v8::internal::HCheckTableEntry::object_, size_, v8::internal::HCheckTableEntry::state_, and v8::internal::HCheckTableEntry::UNCHECKED_STABLE.

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

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

◆ Merge() [1/2]

HCheckTable* v8::internal::HCheckTable::Merge ( HBasicBlock *  succ,
HCheckTable that,
HBasicBlock *  pred_block,
Zone zone 
)
inlineprivate

Definition at line 310 of file hydrogen-check-elimination.cc.

311  {
312  if (that->size_ == 0) {
313  // If the other state is empty, simply reset.
314  size_ = 0;
315  cursor_ = 0;
316  } else {
317  int pred_index = succ->PredecessorIndexOf(pred_block);
318  bool compact = false;
319  for (int i = 0; i < size_; i++) {
320  HCheckTableEntry* this_entry = &entries_[i];
321  HCheckTableEntry* that_entry;
322  if (this_entry->object_->IsPhi() &&
323  this_entry->object_->block() == succ) {
324  HPhi* phi = HPhi::cast(this_entry->object_);
325  HValue* phi_operand = phi->OperandAt(pred_index);
326  that_entry = that->Find(phi_operand);
327 
328  } else {
329  that_entry = that->Find(this_entry->object_);
330  }
331 
332  if (that_entry == NULL ||
333  (that_entry->state_ == HCheckTableEntry::CHECKED &&
334  this_entry->state_ == HCheckTableEntry::UNCHECKED_STABLE) ||
335  (this_entry->state_ == HCheckTableEntry::CHECKED &&
336  that_entry->state_ == HCheckTableEntry::UNCHECKED_STABLE)) {
337  this_entry->object_ = NULL;
338  compact = true;
339  } else {
340  this_entry->maps_ =
341  this_entry->maps_->Union(that_entry->maps_, zone);
342  this_entry->state_ = HCheckTableEntry::StateMerge(
343  this_entry->state_, that_entry->state_);
344  if (this_entry->check_ != that_entry->check_) {
345  this_entry->check_ = NULL;
346  }
347  DCHECK(this_entry->maps_->size() > 0);
348  }
349  }
350  if (compact) Compact();
351  }
352 
353  if (FLAG_trace_check_elimination) {
354  PrintF("B%d checkmaps-table merged with B%d table:\n",
355  succ->block_id(), pred_block->block_id());
356  Print(this);
357  }
358  return this;
359  }

References v8::internal::HValue::block(), v8::internal::HCheckTableEntry::check_, v8::internal::HCheckTableEntry::CHECKED, Compact(), cursor_, DCHECK, entries_, Find(), v8::internal::HValue::IsPhi(), v8::internal::HCheckTableEntry::maps_, NULL, v8::internal::HCheckTableEntry::object_, v8::internal::HValue::OperandAt(), Print(), v8::internal::PrintF(), size_, v8::internal::HCheckTableEntry::state_, v8::internal::HCheckTableEntry::StateMerge(), v8::internal::HCheckTableEntry::UNCHECKED_STABLE, and zone().

+ Here is the call graph for this function:

◆ Merge() [2/2]

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

Definition at line 145 of file hydrogen-check-elimination.cc.

147  {
148  if (pred_state == NULL || pred_block->IsUnreachable()) {
149  return succ_state;
150  }
151  if (succ_state == NULL) {
152  return pred_state->Copy(succ_block, pred_block, zone);
153  } else {
154  return succ_state->Merge(succ_block, pred_state, pred_block, zone);
155  }
156  }

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

Referenced by Merge().

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

◆ Print()

static void v8::internal::HCheckTable::Print ( HCheckTable table)
inlinestaticprivate

Definition at line 729 of file hydrogen-check-elimination.cc.

729  {
730  if (table == NULL) {
731  PrintF(" unreachable\n");
732  return;
733  }
734 
735  for (int i = 0; i < table->size_; i++) {
736  HCheckTableEntry* entry = &table->entries_[i];
737  DCHECK(entry->object_ != NULL);
738  PrintF(" checkmaps-table @%d: %s #%d ", i,
739  entry->object_->IsPhi() ? "phi" : "object", entry->object_->id());
740  if (entry->check_ != NULL) {
741  PrintF("check #%d ", entry->check_->id());
742  }
743  MapSet list = entry->maps_;
744  PrintF("%d %s maps { ", list->size(),
745  HCheckTableEntry::State2String(entry->state_));
746  for (int j = 0; j < list->size(); j++) {
747  if (j > 0) PrintF(", ");
748  PrintF("%" V8PRIxPTR, list->at(j).Hashcode());
749  }
750  PrintF(" }\n");
751  }
752  }
#define V8PRIxPTR
Definition: macros.h:363
const UniqueSet< Map > * MapSet
static const char * State2String(State state)

References v8::internal::HCheckTableEntry::check_, DCHECK, entries_, v8::internal::HValue::id(), v8::internal::HValue::IsPhi(), v8::internal::HCheckTableEntry::maps_, NULL, v8::internal::HCheckTableEntry::object_, v8::internal::PrintF(), size_, v8::internal::HCheckTableEntry::State2String(), v8::internal::HCheckTableEntry::state_, and V8PRIxPTR.

Referenced by Copy(), Finish(), Merge(), and ReduceCheckMaps().

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

◆ Process()

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

Definition at line 85 of file hydrogen-check-elimination.cc.

85  {
86  switch (instr->opcode()) {
87  case HValue::kCheckMaps: {
88  ReduceCheckMaps(HCheckMaps::cast(instr));
89  break;
90  }
91  case HValue::kLoadNamedField: {
92  ReduceLoadNamedField(HLoadNamedField::cast(instr));
93  break;
94  }
95  case HValue::kStoreNamedField: {
96  ReduceStoreNamedField(HStoreNamedField::cast(instr));
97  break;
98  }
99  case HValue::kCompareMap: {
100  ReduceCompareMap(HCompareMap::cast(instr));
101  break;
102  }
103  case HValue::kCompareObjectEqAndBranch: {
105  break;
106  }
107  case HValue::kIsStringAndBranch: {
108  ReduceIsStringAndBranch(HIsStringAndBranch::cast(instr));
109  break;
110  }
111  case HValue::kTransitionElementsKind: {
113  HTransitionElementsKind::cast(instr));
114  break;
115  }
116  case HValue::kCheckHeapObject: {
117  ReduceCheckHeapObject(HCheckHeapObject::cast(instr));
118  break;
119  }
120  case HValue::kCheckInstanceType: {
121  ReduceCheckInstanceType(HCheckInstanceType::cast(instr));
122  break;
123  }
124  default: {
125  // If the instruction changes maps uncontrollably, drop everything.
126  if (instr->CheckChangesFlag(kOsrEntries)) {
127  Kill();
128  break;
129  }
130  if (instr->CheckChangesFlag(kElementsKind) ||
131  instr->CheckChangesFlag(kMaps)) {
133  }
134  }
135  // Improvements possible:
136  // - eliminate redundant HCheckSmi instructions
137  // - track which values have been HCheckHeapObject'd
138  }
139 
140  return this;
141  }
void ReduceCheckInstanceType(HCheckInstanceType *instr)
void ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch *instr)
void ReduceIsStringAndBranch(HIsStringAndBranch *instr)
void ReduceCheckHeapObject(HCheckHeapObject *instr)
void ReduceCompareMap(HCompareMap *instr)
void ReduceStoreNamedField(HStoreNamedField *instr)
void ReduceTransitionElementsKind(HTransitionElementsKind *instr)
void ReduceCheckMaps(HCheckMaps *instr)
void ReduceLoadNamedField(HLoadNamedField *instr)

References v8::internal::HValue::cast(), v8::internal::HValue::CheckChangesFlag(), Kill(), KillUnstableEntries(), v8::internal::HValue::opcode(), ReduceCheckHeapObject(), ReduceCheckInstanceType(), ReduceCheckMaps(), ReduceCompareMap(), ReduceCompareObjectEqAndBranch(), ReduceIsStringAndBranch(), ReduceLoadNamedField(), ReduceStoreNamedField(), and ReduceTransitionElementsKind().

+ Here is the call graph for this function:

◆ ReduceCheckHeapObject()

void v8::internal::HCheckTable::ReduceCheckHeapObject ( HCheckHeapObject *  instr)
inlineprivate

Definition at line 517 of file hydrogen-check-elimination.cc.

517  {
518  HValue* value = instr->value()->ActualValue();
519  if (Find(value) != NULL) {
520  // If the object has known maps, it's definitely a heap object.
521  instr->DeleteAndReplaceWith(value);
522  INC_STAT(removed_cho_);
523  }
524  }
#define INC_STAT(x)

References v8::internal::HValue::ActualValue(), v8::internal::HValue::DeleteAndReplaceWith(), Find(), INC_STAT, and NULL.

Referenced by Process().

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

◆ ReduceCheckInstanceType()

void v8::internal::HCheckTable::ReduceCheckInstanceType ( HCheckInstanceType *  instr)
inlineprivate

Definition at line 448 of file hydrogen-check-elimination.cc.

448  {
449  HValue* value = instr->value()->ActualValue();
450  HCheckTableEntry* entry = Find(value);
451  if (entry == NULL) {
452  if (instr->check() == HCheckInstanceType::IS_STRING) {
454  }
455  return;
456  }
457  UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(
458  entry->maps_->size(), zone());
459  for (int i = 0; i < entry->maps_->size(); ++i) {
460  InstanceType type;
461  Unique<Map> map = entry->maps_->at(i);
462  {
463  // This is safe, because maps don't move and their instance type does
464  // not change.
465  AllowHandleDereference allow_deref;
466  type = map.handle()->instance_type();
467  }
468  if (instr->is_interval_check()) {
469  InstanceType first_type, last_type;
470  instr->GetCheckInterval(&first_type, &last_type);
471  if (first_type <= type && type <= last_type) maps->Add(map, zone());
472  } else {
473  uint8_t mask, tag;
474  instr->GetCheckMaskAndTag(&mask, &tag);
475  if ((type & mask) == tag) maps->Add(map, zone());
476  }
477  }
478  if (maps->size() == entry->maps_->size()) {
479  TRACE(("Removing redundant CheckInstanceType #%d at B%d\n",
480  instr->id(), instr->block()->block_id()));
481  EnsureChecked(entry, value, instr);
482  instr->DeleteAndReplaceWith(value);
483  INC_STAT(removed_cit_);
484  } else if (maps->size() != 0) {
485  entry->maps_ = maps;
486  if (entry->state_ == HCheckTableEntry::UNCHECKED_STABLE) {
487  entry->state_ = HCheckTableEntry::CHECKED_STABLE;
488  }
489  }
490  }
#define TRACE(x)
PerThreadAssertScopeDebugOnly< HANDLE_DEREFERENCE_ASSERT, true > AllowHandleDereference
Definition: assert-scope.h:122

References v8::internal::HValue::ActualValue(), v8::internal::HCheckTableEntry::CHECKED, v8::internal::HCheckTableEntry::CHECKED_STABLE, EnsureChecked(), Find(), INC_STAT, Insert(), map, v8::internal::HCheckTableEntry::maps_, NULL, v8::internal::HCheckTableEntry::state_, string_maps(), TRACE, v8::internal::HCheckTableEntry::UNCHECKED_STABLE, and zone().

Referenced by Process().

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

◆ ReduceCheckMaps()

void v8::internal::HCheckTable::ReduceCheckMaps ( HCheckMaps *  instr)
inlineprivate

Definition at line 361 of file hydrogen-check-elimination.cc.

361  {
362  HValue* object = instr->value()->ActualValue();
363  HCheckTableEntry* entry = Find(object);
364  if (entry != NULL) {
365  // entry found;
366  HGraph* graph = instr->block()->graph();
367  if (entry->maps_->IsSubset(instr->maps())) {
368  // The first check is more strict; the second is redundant.
369  if (entry->check_ != NULL) {
371  TRACE(("Replacing redundant CheckMaps #%d at B%d with #%d\n",
372  instr->id(), instr->block()->block_id(), entry->check_->id()));
373  instr->DeleteAndReplaceWith(entry->check_);
374  INC_STAT(redundant_);
375  } else if (entry->state_ == HCheckTableEntry::UNCHECKED_STABLE) {
376  DCHECK_EQ(NULL, entry->check_);
377  TRACE(("Marking redundant CheckMaps #%d at B%d as stability check\n",
378  instr->id(), instr->block()->block_id()));
379  instr->set_maps(entry->maps_->Copy(graph->zone()));
380  instr->MarkAsStabilityCheck();
381  entry->state_ = HCheckTableEntry::CHECKED_STABLE;
382  } else if (!instr->IsStabilityCheck()) {
383  TRACE(("Marking redundant CheckMaps #%d at B%d as dead\n",
384  instr->id(), instr->block()->block_id()));
385  // Mark check as dead but leave it in the graph as a checkpoint for
386  // subsequent checks.
387  instr->SetFlag(HValue::kIsDead);
388  entry->check_ = instr;
389  INC_STAT(removed_);
390  }
391  return;
392  }
393  MapSet intersection = instr->maps()->Intersect(
394  entry->maps_, graph->zone());
395  if (intersection->size() == 0) {
396  // Intersection is empty; probably megamorphic.
397  INC_STAT(empty_);
398  entry->object_ = NULL;
399  Compact();
400  } else {
401  // Update set of maps in the entry.
402  entry->maps_ = intersection;
403  // Update state of the entry.
404  if (instr->maps_are_stable() ||
405  entry->state_ == HCheckTableEntry::UNCHECKED_STABLE) {
406  entry->state_ = HCheckTableEntry::CHECKED_STABLE;
407  }
408  if (intersection->size() != instr->maps()->size()) {
409  // Narrow set of maps in the second check maps instruction.
410  if (entry->check_ != NULL &&
411  entry->check_->block() == instr->block() &&
412  entry->check_->IsCheckMaps()) {
413  // There is a check in the same block so replace it with a more
414  // strict check and eliminate the second check entirely.
415  HCheckMaps* check = HCheckMaps::cast(entry->check_);
416  DCHECK(!check->IsStabilityCheck());
417  TRACE(("CheckMaps #%d at B%d narrowed\n", check->id(),
418  check->block()->block_id()));
419  // Update map set and ensure that the check is alive.
420  check->set_maps(intersection);
421  check->ClearFlag(HValue::kIsDead);
422  TRACE(("Replacing redundant CheckMaps #%d at B%d with #%d\n",
423  instr->id(), instr->block()->block_id(), entry->check_->id()));
424  instr->DeleteAndReplaceWith(entry->check_);
425  } else {
426  TRACE(("CheckMaps #%d at B%d narrowed\n", instr->id(),
427  instr->block()->block_id()));
428  instr->set_maps(intersection);
429  entry->check_ = instr->IsStabilityCheck() ? NULL : instr;
430  }
431 
432  if (FLAG_trace_check_elimination) {
433  Print(this);
434  }
435  INC_STAT(narrowed_);
436  }
437  }
438  } else {
439  // No entry; insert a new one.
440  HCheckTableEntry::State state = instr->maps_are_stable()
443  HCheckMaps* check = instr->IsStabilityCheck() ? NULL : instr;
444  Insert(object, check, instr->maps(), state);
445  }
446  }
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206

References v8::internal::HValue::ActualValue(), v8::internal::HValue::block(), v8::internal::HCheckTableEntry::check_, v8::internal::HCheckTableEntry::CHECKED, v8::internal::HCheckTableEntry::CHECKED_STABLE, Compact(), DCHECK, DCHECK_EQ, DCHECK_NE, Find(), v8::internal::HValue::id(), INC_STAT, Insert(), v8::internal::HValue::kIsDead, v8::internal::HCheckTableEntry::maps_, NULL, v8::internal::HCheckTableEntry::object_, Print(), v8::internal::HCheckTableEntry::state_, TRACE, and v8::internal::HCheckTableEntry::UNCHECKED_STABLE.

Referenced by Process().

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

◆ ReduceCompareMap()

void v8::internal::HCheckTable::ReduceCompareMap ( HCompareMap *  instr)
inlineprivate

Definition at line 551 of file hydrogen-check-elimination.cc.

551  {
552  HCheckTableEntry* entry = Find(instr->value()->ActualValue());
553  if (entry == NULL) return;
554 
555  EnsureChecked(entry, instr->value(), instr);
556 
557  int succ;
558  if (entry->maps_->Contains(instr->map())) {
559  if (entry->maps_->size() != 1) {
560  TRACE(("CompareMap #%d for #%d at B%d can't be eliminated: "
561  "ambiguous set of maps\n", instr->id(), instr->value()->id(),
562  instr->block()->block_id()));
563  return;
564  }
565  succ = 0;
566  INC_STAT(compares_true_);
567  } else {
568  succ = 1;
569  INC_STAT(compares_false_);
570  }
571 
572  TRACE(("Marking redundant CompareMap #%d for #%d at B%d as %s\n",
573  instr->id(), instr->value()->id(), instr->block()->block_id(),
574  succ == 0 ? "true" : "false"));
575  instr->set_known_successor_index(succ);
576 
577  int unreachable_succ = 1 - succ;
578  instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
579  }

References EnsureChecked(), Find(), INC_STAT, v8::internal::HCheckTableEntry::maps_, NULL, and TRACE.

Referenced by Process().

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

◆ ReduceCompareObjectEqAndBranch()

void v8::internal::HCheckTable::ReduceCompareObjectEqAndBranch ( HCompareObjectEqAndBranch instr)
inlineprivate

Definition at line 581 of file hydrogen-check-elimination.cc.

581  {
582  HValue* left = instr->left()->ActualValue();
583  HCheckTableEntry* le = Find(left);
584  if (le == NULL) return;
585  HValue* right = instr->right()->ActualValue();
586  HCheckTableEntry* re = Find(right);
587  if (re == NULL) return;
588 
589  EnsureChecked(le, left, instr);
590  EnsureChecked(re, right, instr);
591 
592  // TODO(bmeurer): Add a predicate here instead of computing the intersection
593  MapSet intersection = le->maps_->Intersect(re->maps_, zone());
594  if (intersection->size() > 0) return;
595 
596  TRACE(("Marking redundant CompareObjectEqAndBranch #%d at B%d as false\n",
597  instr->id(), instr->block()->block_id()));
598  int succ = 1;
599  instr->set_known_successor_index(succ);
600 
601  int unreachable_succ = 1 - succ;
602  instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
603  }

References v8::internal::HValue::ActualValue(), v8::internal::HValue::block(), EnsureChecked(), Find(), v8::internal::HValue::id(), v8::internal::le, v8::internal::HCompareObjectEqAndBranch::left(), v8::internal::HCheckTableEntry::maps_, NULL, v8::internal::HCompareObjectEqAndBranch::right(), v8::internal::HCompareObjectEqAndBranch::set_known_successor_index(), TRACE, and zone().

Referenced by Process().

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

◆ ReduceIsStringAndBranch()

void v8::internal::HCheckTable::ReduceIsStringAndBranch ( HIsStringAndBranch *  instr)
inlineprivate

Definition at line 605 of file hydrogen-check-elimination.cc.

605  {
606  HValue* value = instr->value()->ActualValue();
607  HCheckTableEntry* entry = Find(value);
608  if (entry == NULL) return;
609  EnsureChecked(entry, value, instr);
610  int succ;
611  if (entry->maps_->IsSubset(string_maps())) {
612  TRACE(("Marking redundant IsStringAndBranch #%d at B%d as true\n",
613  instr->id(), instr->block()->block_id()));
614  succ = 0;
615  } else {
616  MapSet intersection = entry->maps_->Intersect(string_maps(), zone());
617  if (intersection->size() > 0) return;
618  TRACE(("Marking redundant IsStringAndBranch #%d at B%d as false\n",
619  instr->id(), instr->block()->block_id()));
620  succ = 1;
621  }
622  instr->set_known_successor_index(succ);
623  int unreachable_succ = 1 - succ;
624  instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
625  }

References v8::internal::HValue::ActualValue(), EnsureChecked(), Find(), v8::internal::HCheckTableEntry::maps_, NULL, string_maps(), TRACE, and zone().

Referenced by Process().

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

◆ ReduceLoadNamedField()

void v8::internal::HCheckTable::ReduceLoadNamedField ( HLoadNamedField *  instr)
inlineprivate

Definition at line 492 of file hydrogen-check-elimination.cc.

492  {
493  // Reduce a load of the map field when it is known to be a constant.
494  if (!instr->access().IsMap()) {
495  // Check if we introduce field maps here.
496  MapSet maps = instr->maps();
497  if (maps != NULL) {
498  DCHECK_NE(0, maps->size());
500  }
501  return;
502  }
503 
504  HValue* object = instr->object()->ActualValue();
505  HCheckTableEntry* entry = Find(object);
506  if (entry == NULL || entry->maps_->size() != 1) return; // Not a constant.
507 
508  EnsureChecked(entry, object, instr);
509  Unique<Map> map = entry->maps_->at(0);
510  bool map_is_stable = (entry->state_ != HCheckTableEntry::CHECKED);
511  HConstant* constant = HConstant::CreateAndInsertBefore(
512  instr->block()->graph()->zone(), map, map_is_stable, instr);
513  instr->DeleteAndReplaceWith(constant);
514  INC_STAT(loads_);
515  }

References v8::internal::HValue::ActualValue(), v8::internal::HCheckTableEntry::CHECKED, DCHECK_NE, EnsureChecked(), Find(), INC_STAT, Insert(), map, v8::internal::HCheckTableEntry::maps_, NULL, v8::internal::HCheckTableEntry::state_, and v8::internal::HCheckTableEntry::UNCHECKED_STABLE.

Referenced by Process().

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

◆ ReduceStoreNamedField()

void v8::internal::HCheckTable::ReduceStoreNamedField ( HStoreNamedField *  instr)
inlineprivate

Definition at line 526 of file hydrogen-check-elimination.cc.

526  {
527  HValue* object = instr->object()->ActualValue();
528  if (instr->has_transition()) {
529  // This store transitions the object to a new map.
530  Kill(object);
531  HConstant* c_transition = HConstant::cast(instr->transition());
532  HCheckTableEntry::State state = c_transition->HasStableMapValue()
535  Insert(object, NULL, c_transition->MapValue(), state);
536  } else if (instr->access().IsMap()) {
537  // This is a store directly to the map field of the object.
538  Kill(object);
539  if (!instr->value()->IsConstant()) return;
540  HConstant* c_value = HConstant::cast(instr->value());
541  HCheckTableEntry::State state = c_value->HasStableMapValue()
544  Insert(object, NULL, c_value->MapValue(), state);
545  } else {
546  // If the instruction changes maps, it should be handled above.
547  CHECK(!instr->CheckChangesFlag(kMaps));
548  }
549  }
#define CHECK(condition)
Definition: logging.h:36

References v8::internal::HValue::ActualValue(), CHECK, v8::internal::HCheckTableEntry::CHECKED, v8::internal::HCheckTableEntry::CHECKED_STABLE, Insert(), Kill(), and NULL.

Referenced by Process().

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

◆ ReduceTransitionElementsKind()

void v8::internal::HCheckTable::ReduceTransitionElementsKind ( HTransitionElementsKind *  instr)
inlineprivate

Definition at line 627 of file hydrogen-check-elimination.cc.

627  {
628  HValue* object = instr->object()->ActualValue();
629  HCheckTableEntry* entry = Find(object);
630  // Can only learn more about an object that already has a known set of maps.
631  if (entry == NULL) return;
632  EnsureChecked(entry, object, instr);
633  if (entry->maps_->Contains(instr->original_map())) {
634  // If the object has the original map, it will be transitioned.
635  UniqueSet<Map>* maps = entry->maps_->Copy(zone());
636  maps->Remove(instr->original_map());
637  maps->Add(instr->transitioned_map(), zone());
638  entry->maps_ = maps;
639  } else {
640  // Object does not have the given map, thus the transition is redundant.
641  instr->DeleteAndReplaceWith(object);
642  INC_STAT(transitions_);
643  }
644  }

References v8::internal::HValue::ActualValue(), EnsureChecked(), Find(), INC_STAT, v8::internal::HCheckTableEntry::maps_, NULL, and zone().

Referenced by Process().

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

◆ STATIC_ASSERT()

v8::internal::HCheckTable::STATIC_ASSERT ( )
private

◆ string_maps()

MapSet v8::internal::HCheckTable::string_maps ( ) const
inlineprivate

Definition at line 787 of file hydrogen-check-elimination.cc.

787 { return phase_->string_maps(); }
const UniqueSet< Map > * string_maps() const

References phase_, and v8::internal::HCheckEliminationPhase::string_maps().

Referenced by Copy(), ReduceCheckInstanceType(), and ReduceIsStringAndBranch().

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

◆ zone()

Zone* v8::internal::HCheckTable::zone ( ) const
inlineprivate

Definition at line 786 of file hydrogen-check-elimination.cc.

786 { return phase_->zone(); }

References phase_.

Referenced by Copy(), Insert(), Merge(), ReduceCheckInstanceType(), ReduceCompareObjectEqAndBranch(), ReduceIsStringAndBranch(), and ReduceTransitionElementsKind().

+ Here is the caller graph for this function:

Friends And Related Function Documentation

◆ HCheckEliminationPhase

friend class HCheckEliminationPhase
friend

Definition at line 790 of file hydrogen-check-elimination.cc.

◆ HCheckMapsEffects

friend class HCheckMapsEffects
friend

Definition at line 789 of file hydrogen-check-elimination.cc.

Member Data Documentation

◆ cursor_

int16_t v8::internal::HCheckTable::cursor_
private

Definition at line 794 of file hydrogen-check-elimination.cc.

Referenced by Compact(), Copy(), Insert(), Kill(), and Merge().

◆ entries_

HCheckTableEntry v8::internal::HCheckTable::entries_[kMaxTrackedObjects]
private

◆ kMaxTrackedObjects

const int v8::internal::HCheckTable::kMaxTrackedObjects = 16
static

Definition at line 76 of file hydrogen-check-elimination.cc.

Referenced by Compact(), and Insert().

◆ phase_

HCheckEliminationPhase* v8::internal::HCheckTable::phase_
private

Definition at line 792 of file hydrogen-check-elimination.cc.

Referenced by Copy(), Find(), Kill(), string_maps(), and zone().

◆ size_

int16_t v8::internal::HCheckTable::size_
private

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