14 #define INC_STAT(x) phase_->x++
20 #define TRACE(x) if (FLAG_trace_check_elimination) PrintF x
55 if (state1 == state2)
return state1;
87 case HValue::kCheckMaps: {
91 case HValue::kLoadNamedField: {
95 case HValue::kStoreNamedField: {
99 case HValue::kCompareMap: {
103 case HValue::kCompareObjectEqAndBranch: {
107 case HValue::kIsStringAndBranch: {
111 case HValue::kTransitionElementsKind: {
113 HTransitionElementsKind::cast(instr));
116 case HValue::kCheckHeapObject: {
120 case HValue::kCheckInstanceType: {
148 if (pred_state ==
NULL || pred_block->IsUnreachable()) {
151 if (succ_state ==
NULL) {
152 return pred_state->
Copy(succ_block, pred_block,
zone);
154 return succ_state->
Merge(succ_block, pred_state, pred_block,
zone);
163 block->MarkUnreachable();
164 }
else if (block->IsUnreachable()) {
167 if (FLAG_trace_check_elimination) {
168 PrintF(
"Processing B%d, checkmaps-table:\n", block->block_id());
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();
204 HPhi* phi = succ->phis()->at(phi_index);
208 if (pred_entry !=
NULL) {
217 bool learned =
false;
218 if (succ->predecessors()->length() == 1) {
221 if (end->IsCompareMap()) {
222 HCompareMap* cmp = HCompareMap::cast(end);
225 if (is_true_branch) {
231 copy->
Insert(
object, cmp, cmp->map(), state);
242 maps->Remove(cmp->map());
248 }
else if (is_true_branch && end->IsCompareObjectEqAndBranch()) {
260 }
else if (re ==
NULL) {
272 }
else if (end->IsIsStringAndBranch()) {
273 HIsStringAndBranch* cmp = HIsStringAndBranch::cast(end);
276 if (is_true_branch) {
298 if (FLAG_trace_check_elimination) {
299 PrintF(
"B%d checkmaps-table %s from B%d:\n",
301 learned ?
"learned" :
"copied",
302 from_block->block_id());
311 HBasicBlock* pred_block,
Zone*
zone) {
312 if (that->
size_ == 0) {
317 int pred_index = succ->PredecessorIndexOf(pred_block);
318 bool compact =
false;
324 HPhi* phi = HPhi::cast(this_entry->
object_);
326 that_entry = that->
Find(phi_operand);
332 if (that_entry ==
NULL ||
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());
366 HGraph* graph = instr->block()->graph();
367 if (entry->
maps_->IsSubset(instr->maps())) {
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_);
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();
382 }
else if (!instr->IsStabilityCheck()) {
383 TRACE((
"Marking redundant CheckMaps #%d at B%d as dead\n",
384 instr->id(), instr->block()->block_id()));
393 MapSet intersection = instr->maps()->Intersect(
394 entry->
maps_, graph->zone());
395 if (intersection->size() == 0) {
402 entry->
maps_ = intersection;
404 if (instr->maps_are_stable() ||
408 if (intersection->size() != instr->maps()->size()) {
412 entry->
check_->IsCheckMaps()) {
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()));
420 check->set_maps(intersection);
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_);
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;
432 if (FLAG_trace_check_elimination) {
443 HCheckMaps* check = instr->IsStabilityCheck() ?
NULL : instr;
444 Insert(
object, check, instr->maps(), state);
452 if (instr->check() == HCheckInstanceType::IS_STRING) {
459 for (
int i = 0;
i < entry->
maps_->size(); ++
i) {
466 type =
map.handle()->instance_type();
468 if (instr->is_interval_check()) {
470 instr->GetCheckInterval(&first_type, &last_type);
471 if (first_type <= type && type <= last_type) maps->Add(
map,
zone());
474 instr->GetCheckMaskAndTag(&mask, &tag);
475 if ((type & mask) == tag) maps->Add(
map,
zone());
478 if (maps->size() == entry->
maps_->size()) {
479 TRACE((
"Removing redundant CheckInstanceType #%d at B%d\n",
480 instr->id(), instr->block()->block_id()));
482 instr->DeleteAndReplaceWith(value);
484 }
else if (maps->size() != 0) {
494 if (!instr->access().IsMap()) {
496 MapSet maps = instr->maps();
506 if (entry ==
NULL || entry->
maps_->size() != 1)
return;
511 HConstant* constant = HConstant::CreateAndInsertBefore(
512 instr->block()->graph()->zone(),
map, map_is_stable, instr);
513 instr->DeleteAndReplaceWith(constant);
528 if (instr->has_transition()) {
531 HConstant* c_transition = HConstant::cast(instr->transition());
535 Insert(
object,
NULL, c_transition->MapValue(), state);
536 }
else if (instr->access().IsMap()) {
539 if (!instr->value()->IsConstant())
return;
540 HConstant* c_value = HConstant::cast(instr->value());
544 Insert(
object,
NULL, c_value->MapValue(), state);
547 CHECK(!instr->CheckChangesFlag(kMaps));
553 if (entry ==
NULL)
return;
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()));
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);
577 int unreachable_succ = 1 - succ;
578 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
587 if (re ==
NULL)
return;
594 if (intersection->size() > 0)
return;
596 TRACE((
"Marking redundant CompareObjectEqAndBranch #%d at B%d as false\n",
597 instr->
id(), instr->
block()->block_id()));
601 int unreachable_succ = 1 - succ;
602 instr->
block()->MarkSuccEdgeUnreachable(unreachable_succ);
608 if (entry ==
NULL)
return;
612 TRACE((
"Marking redundant IsStringAndBranch #%d at B%d as true\n",
613 instr->id(), instr->block()->block_id()));
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()));
622 instr->set_known_successor_index(succ);
623 int unreachable_succ = 1 - succ;
624 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
631 if (entry ==
NULL)
return;
633 if (entry->
maps_->Contains(instr->original_map())) {
636 maps->Remove(instr->original_map());
637 maps->Add(instr->transitioned_map(),
zone());
641 instr->DeleteAndReplaceWith(
object);
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();
666 bool compact =
false;
684 bool compact =
false;
700 for (
int i = 0;
i < max;
i++) {
735 for (
int i = 0;
i < table->
size_;
i++) {
738 PrintF(
" checkmaps-table @%d: %s #%d ",
i,
744 PrintF(
"%d %s maps { ", list->size(),
746 for (
int j = 0; j < list->size(); j++) {
755 for (
int i =
size_ - 1;
i >= 0;
i--) {
811 switch (instr->
opcode()) {
812 case HValue::kStoreNamedField: {
813 HStoreNamedField* store = HStoreNamedField::cast(instr);
814 if (store->access().IsMap() || store->has_transition()) {
815 objects_.Add(store->object(), zone);
819 case HValue::kTransitionElementsKind: {
820 objects_.Add(HTransitionElementsKind::cast(instr)->
object(), zone);
852 for (
int i = 0;
i < that->
objects_.length(); ++
i) {
874 for (
int i = 0;
i <
graph()->blocks()->length();
i++) {
880 if (FLAG_trace_check_elimination)
PrintStats();
887 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_)
889 #define PRINT_STAT(x)
bool Contains(E element) const
bool MustAlias(HValue *a, HValue *b)
bool MayAlias(HValue *a, HValue *b)
const UniqueSet< Map > * string_maps() const
HAliasAnalyzer * aliasing_
void Union(HCheckMapsEffects *that, Zone *zone)
HCheckMapsEffects(Zone *zone)
void Apply(HCheckTable *table)
ZoneList< HValue * > objects_
void Process(HInstruction *instr, Zone *zone)
void ReduceCheckInstanceType(HCheckInstanceType *instr)
void EnsureChecked(HCheckTableEntry *entry, HValue *value, HInstruction *instr)
void ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch *instr)
void Insert(HValue *object, HInstruction *check, MapSet maps, HCheckTableEntry::State state)
static void Print(HCheckTable *table)
static HCheckTable * Finish(HCheckTable *state, HBasicBlock *block, Zone *zone)
void Kill(HValue *object)
void ReduceIsStringAndBranch(HIsStringAndBranch *instr)
HCheckEliminationPhase * phase_
HCheckTableEntry entries_[kMaxTrackedObjects]
HCheckTable * Process(HInstruction *instr, Zone *zone)
void ReduceCheckHeapObject(HCheckHeapObject *instr)
HCheckTable * Merge(HBasicBlock *succ, HCheckTable *that, HBasicBlock *pred_block, Zone *zone)
void ReduceCompareMap(HCompareMap *instr)
HCheckTableEntry * Find(HValue *object)
MapSet string_maps() const
void KillUnstableEntries()
void ReduceStoreNamedField(HStoreNamedField *instr)
void ReduceTransitionElementsKind(HTransitionElementsKind *instr)
HCheckTable * Copy(HBasicBlock *succ, HBasicBlock *from_block, Zone *zone)
void ReduceCheckMaps(HCheckMaps *instr)
static const int kMaxTrackedObjects
static HCheckTable * Merge(HCheckTable *succ_state, HBasicBlock *succ_block, HCheckTable *pred_state, HBasicBlock *pred_block, Zone *zone)
STATIC_ASSERT(kMaxTrackedObjects<(1<< 15))
void Insert(HValue *object, HInstruction *check, Unique< Map > map, HCheckTableEntry::State state)
void ReduceLoadNamedField(HLoadNamedField *instr)
HCheckTable(HCheckEliminationPhase *phase)
void set_known_successor_index(int known_successor_index)
virtual HBasicBlock * SuccessorAt(int i) const =0
State * AnalyzeOneBlock(HBasicBlock *block, State *state)
void AnalyzeDominatedBlocks(HBasicBlock *root, State *initial)
static HValue * cast(HValue *value)
virtual Opcode opcode() const =0
HBasicBlock * block() const
GVNFlagSet ChangesFlags() const
bool CheckChangesFlag(GVNFlag f) const
virtual HValue * OperandAt(int index) const =0
void DeleteAndReplaceWith(HValue *other)
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
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_NOT_NULL(p)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
void MemMove(void *dest, const void *src, size_t size)
const UniqueSet< Map > * MapSet
void PrintF(const char *format,...)
Debugger support for the V8 JavaScript engine.
static const char * State2String(State state)
static State StateMerge(State state1, State state2)