Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Friends | List of all members
dart::FlowGraph Class Reference

#include <flow_graph.h>

Inheritance diagram for dart::FlowGraph:
dart::ZoneAllocated

Classes

struct  LogicalAnd
 

Public Types

enum class  CompilationMode { kUnoptimized , kOptimized , kIntrinsic }
 
enum class  ToCheck { kNoCheck , kCheckNull , kCheckCid }
 
enum  UseKind { kEffect , kValue }
 

Public Member Functions

 FlowGraph (const ParsedFunction &parsed_function, GraphEntryInstr *graph_entry, intptr_t max_block_id, PrologueInfo prologue_info, CompilationMode compilation_mode)
 
const ParsedFunctionparsed_function () const
 
const Functionfunction () const
 
void Print (const char *phase="unknown")
 
intptr_t num_direct_parameters () const
 
intptr_t variable_count () const
 
intptr_t osr_variable_count () const
 
intptr_t num_stack_locals () const
 
bool IsIrregexpFunction () const
 
LocalVariableSuspendStateVar () const
 
intptr_t SuspendStateEnvIndex () const
 
LocalVariableCurrentContextVar () const
 
intptr_t CurrentContextEnvIndex () const
 
intptr_t RawTypeArgumentEnvIndex () const
 
intptr_t ArgumentDescriptorEnvIndex () const
 
intptr_t EnvIndex (const LocalVariable *variable) const
 
bool IsImmortalVariable (intptr_t env_index) const
 
const GrowableArray< BlockEntryInstr * > & preorder () const
 
const GrowableArray< BlockEntryInstr * > & postorder () const
 
const GrowableArray< BlockEntryInstr * > & reverse_postorder () const
 
const GrowableArray< BlockEntryInstr * > & optimized_block_order () const
 
GrowableArray< BlockEntryInstr * > * CodegenBlockOrder ()
 
const GrowableArray< BlockEntryInstr * > * CodegenBlockOrder () const
 
BlockIterator reverse_postorder_iterator () const
 
BlockIterator postorder_iterator () const
 
void EnsureSSATempIndex (Definition *defn, Definition *replacement)
 
void ReplaceCurrentInstruction (ForwardInstructionIterator *iterator, Instruction *current, Instruction *replacement)
 
InstructionCreateCheckClass (Definition *to_check, const Cids &cids, intptr_t deopt_id, const InstructionSource &source)
 
DefinitionCreateCheckBound (Definition *length, Definition *index, intptr_t deopt_id)
 
void AddExactnessGuard (InstanceCallInstr *call, intptr_t receiver_cid)
 
intptr_t current_ssa_temp_index () const
 
void set_current_ssa_temp_index (intptr_t index)
 
intptr_t max_vreg () const
 
ToCheck CheckForInstanceCall (InstanceCallInstr *call, UntaggedFunction::Kind kind) const
 
Threadthread () const
 
Zonezone () const
 
IsolateGroupisolate_group () const
 
intptr_t max_block_id () const
 
void set_max_block_id (intptr_t id)
 
intptr_t allocate_block_id ()
 
GraphEntryInstrgraph_entry () const
 
ConstantInstrconstant_null () const
 
ConstantInstrconstant_dead () const
 
void AllocateSSAIndex (Definition *def)
 
intptr_t InstructionCount () const
 
ConstantInstrGetExistingConstant (const Object &object, Representation representation=kTagged) const
 
ConstantInstrGetConstant (const Object &object, Representation representation=kTagged)
 
void AddToGraphInitialDefinitions (Definition *defn)
 
void AddToInitialDefinitions (BlockEntryWithInitialDefs *entry, Definition *defn)
 
DefinitionTryCreateConstantReplacementFor (Definition *op, const Object &value)
 
void InsertBefore (Instruction *next, Instruction *instr, Environment *env, UseKind use_kind)
 
void InsertSpeculativeBefore (Instruction *next, Instruction *instr, Environment *env, UseKind use_kind)
 
void InsertAfter (Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
 
void InsertSpeculativeAfter (Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
 
InstructionAppendTo (Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
 
InstructionAppendSpeculativeTo (Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
 
void ComputeSSA (ZoneGrowableArray< Definition * > *inlining_parameters)
 
bool VerifyRedefinitions ()
 
void DiscoverBlocks ()
 
void MergeBlocks ()
 
RedefinitionInstrEnsureRedefinition (Instruction *prev, Definition *original, CompileType compile_type)
 
void RemoveRedefinitions (bool keep_checks=false)
 
void InsertMoveArguments ()
 
void CopyDeoptTarget (Instruction *to, Instruction *from)
 
bool is_licm_allowed () const
 
void disallow_licm ()
 
bool unmatched_representations_allowed () const
 
void disallow_unmatched_representations ()
 
bool is_huge_method () const
 
void mark_huge_method ()
 
PrologueInfo prologue_info () const
 
const LoopHierarchyGetLoopHierarchy ()
 
const LoopHierarchyloop_hierarchy () const
 
void ResetLoopHierarchy ()
 
ZoneGrowableArray< BitVector * > * loop_invariant_loads () const
 
void set_loop_invariant_loads (ZoneGrowableArray< BitVector * > *loop_invariant_loads)
 
bool IsCompiledForOsr () const
 
BitVectorcaptured_parameters () const
 
intptr_t inlining_id () const
 
void set_inlining_id (intptr_t value)
 
bool Canonicalize ()
 
void PopulateWithICData (const Function &function)
 
void SelectRepresentations ()
 
void WidenSmiToInt32 ()
 
void EliminateEnvironments ()
 
void ExtractNonInternalTypedDataPayloads ()
 
bool IsReceiver (Definition *def) const
 
void TryOptimizePatterns ()
 
void RenameUsesDominatedByRedefinitions ()
 
bool should_print () const
 
const uint8_t * compiler_pass_filters () const
 
bool should_reorder_blocks () const
 
bool should_remove_all_bounds_checks () const
 
JoinEntryInstrNewDiamond (Instruction *instruction, Instruction *inherit, ComparisonInstr *compare, TargetEntryInstr **block_true, TargetEntryInstr **block_false)
 
JoinEntryInstrNewDiamond (Instruction *instruction, Instruction *inherit, const LogicalAnd &condition, TargetEntryInstr **block_true, TargetEntryInstr **block_false)
 
PhiInstrAddPhi (JoinEntryInstr *join, Definition *d1, Definition *d2)
 
void ComputeDominators (GrowableArray< BitVector * > *dominance_frontier)
 
void CreateCommonConstants ()
 
const Arraycoverage_array () const
 
void set_coverage_array (const Array &array)
 
void CompactSSA (ZoneGrowableArray< Definition * > *detached_defs=nullptr)
 
intptr_t max_argument_slot_count () const
 
void set_max_argument_slot_count (intptr_t count)
 
const std::pair< Location, Representation > & GetDirectParameterInfoAt (intptr_t i)
 
bool ExtractExternalUntaggedPayload (Instruction *instr, Value *array, classid_t cid)
 
- Public Member Functions inherited from dart::ZoneAllocated
 ZoneAllocated ()
 
void * operator new (size_t size)
 
void * operator new (size_t size, Zone *zone)
 
void operator delete (void *pointer)
 

Static Public Member Functions

static Representation ParameterRepresentationAt (const Function &function, intptr_t index)
 
static Representation ReturnRepresentationOf (const Function &function)
 
static bool IsConstantRepresentable (const Object &value, Representation target_rep, bool tagged_value_must_be_smi)
 
static void RenameDominatedUses (Definition *def, Instruction *dom, Definition *other)
 
static intptr_t ComputeLocationsOfFixedParameters (Zone *zone, const Function &function, bool should_assign_stack_locations=false, compiler::ParameterInfoArray *parameter_info=nullptr)
 
static intptr_t ComputeArgumentsSizeInWords (const Function &function, intptr_t arguments_count)
 
static constexpr CompilationMode CompilationModeFrom (bool is_optimizing)
 

Friends

class FlowGraphCompiler
 
class FlowGraphChecker
 
class IfConverter
 
class BranchSimplifier
 
class ConstantPropagator
 
class DeadCodeElimination
 
class compiler::GraphIntrinsifier
 

Detailed Description

Definition at line 114 of file flow_graph.h.

Member Enumeration Documentation

◆ CompilationMode

Enumerator
kUnoptimized 
kOptimized 
kIntrinsic 

Definition at line 116 of file flow_graph.h.

◆ ToCheck

enum class dart::FlowGraph::ToCheck
strong
Enumerator
kNoCheck 
kCheckNull 
kCheckCid 

Definition at line 252 of file flow_graph.h.

◆ UseKind

Enumerator
kEffect 
kValue 

Definition at line 310 of file flow_graph.h.

Constructor & Destructor Documentation

◆ FlowGraph()

dart::FlowGraph::FlowGraph ( const ParsedFunction parsed_function,
GraphEntryInstr graph_entry,
intptr_t  max_block_id,
PrologueInfo  prologue_info,
CompilationMode  compilation_mode 
)

Definition at line 51 of file flow_graph.cc.

56 : thread_(Thread::Current()),
57 parent_(),
58 current_ssa_temp_index_(0),
59 max_block_id_(max_block_id),
60 parsed_function_(parsed_function),
61 num_direct_parameters_(parsed_function.function().MakesCopyOfParameters()
62 ? 0
63 : parsed_function.function().NumParameters()),
64 direct_parameter_locations_(
65 parsed_function.function().num_fixed_parameters()),
66 graph_entry_(graph_entry),
67 preorder_(),
68 postorder_(),
69 reverse_postorder_(),
70 optimized_block_order_(),
71 constant_null_(nullptr),
72 constant_dead_(nullptr),
73 licm_allowed_(true),
74 should_reorder_blocks_(
75 ShouldReorderBlocks(parsed_function.function(), compilation_mode)),
76 prologue_info_(prologue_info),
77 loop_hierarchy_(nullptr),
78 loop_invariant_loads_(nullptr),
79 captured_parameters_(new(zone()) BitVector(zone(), variable_count())),
80 inlining_id_(-1),
81 should_print_(false),
82 should_remove_all_bounds_checks_(
83 CompilerState::Current().is_aot() &&
86 &compiler_pass_filters_);
88 zone(), function(),
89 /*should_assign_stack_locations=*/
91 &direct_parameter_locations_);
93}
static bool ShouldPrint(const Function &function, uint8_t **compiler_pass_filter=nullptr)
GraphEntryInstr * graph_entry() const
Definition flow_graph.h:268
PrologueInfo prologue_info() const
Definition flow_graph.h:427
Zone * zone() const
Definition flow_graph.h:261
intptr_t max_block_id() const
Definition flow_graph.h:264
void DiscoverBlocks()
static intptr_t ComputeLocationsOfFixedParameters(Zone *zone, const Function &function, bool should_assign_stack_locations=false, compiler::ParameterInfoArray *parameter_info=nullptr)
const Function & function() const
Definition flow_graph.h:130
const ParsedFunction & parsed_function() const
Definition flow_graph.h:129
intptr_t variable_count() const
Definition flow_graph.h:143
bool MakesCopyOfParameters() const
Definition object.h:3494
const Function & function() const
Definition parser.h:73
static Thread * Current()
Definition thread.h:361
static bool ShouldReorderBlocks(const Function &function, FlowGraph::CompilationMode mode)
Definition flow_graph.cc:37
static bool IsMarkedWithNoBoundsChecks(const Function &function)
Definition flow_graph.cc:43

Member Function Documentation

◆ AddExactnessGuard()

void dart::FlowGraph::AddExactnessGuard ( InstanceCallInstr call,
intptr_t  receiver_cid 
)

Definition at line 630 of file flow_graph.cc.

631 {
632 const Class& cls =
633 Class::Handle(zone(), isolate_group()->class_table()->At(receiver_cid));
634
635 Definition* load_type_args = new (zone()) LoadFieldInstr(
636 call->Receiver()->CopyWithType(),
637 Slot::GetTypeArgumentsSlotFor(thread(), cls), call->source());
638 InsertBefore(call, load_type_args, call->env(), FlowGraph::kValue);
639
640 const AbstractType& type =
641 AbstractType::Handle(zone(), call->ic_data()->receivers_static_type());
642 ASSERT(!type.IsNull());
643 const TypeArguments& args = TypeArguments::Handle(
644 zone(), Type::Cast(type).GetInstanceTypeArguments(thread()));
645 Instruction* guard = new (zone()) CheckConditionInstr(
646 new StrictCompareInstr(call->source(), Token::kEQ_STRICT,
647 new (zone()) Value(load_type_args),
648 new (zone()) Value(GetConstant(args)),
649 /*needs_number_check=*/false, call->deopt_id()),
650 call->deopt_id());
651 InsertBefore(call, guard, call->env(), FlowGraph::kEffect);
652}
ConstantInstr * GetConstant(const Object &object, Representation representation=kTagged)
IsolateGroup * isolate_group() const
Definition flow_graph.h:262
Thread * thread() const
Definition flow_graph.h:260
void InsertBefore(Instruction *next, Instruction *instr, Environment *env, UseKind use_kind)
Definition flow_graph.h:312
static Object & Handle()
Definition object.h:407
static const Slot & GetTypeArgumentsSlotFor(Thread *thread, const Class &cls)
Definition slot.cc:276
#define ASSERT(E)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
call(args)
Definition dom.py:159

◆ AddPhi()

PhiInstr * dart::FlowGraph::AddPhi ( JoinEntryInstr join,
Definition d1,
Definition d2 
)

Definition at line 3159 of file flow_graph.cc.

3161 {
3162 PhiInstr* phi = new (zone()) PhiInstr(join, 2);
3163 Value* v1 = new (zone()) Value(d1);
3164 Value* v2 = new (zone()) Value(d2);
3165
3166 AllocateSSAIndex(phi);
3167
3168 phi->mark_alive();
3169 phi->SetInputAt(0, v1);
3170 phi->SetInputAt(1, v2);
3171 d1->AddInputUse(v1);
3172 d2->AddInputUse(v2);
3173 join->InsertPhi(phi);
3174
3175 return phi;
3176}
Vec2Value v2
void AllocateSSAIndex(Definition *def)
Definition flow_graph.h:274
SINT Vec< 2 *N, T > join(const Vec< N, T > &lo, const Vec< N, T > &hi)
Definition SkVx.h:242

◆ AddToGraphInitialDefinitions()

void dart::FlowGraph::AddToGraphInitialDefinitions ( Definition defn)

Definition at line 263 of file flow_graph.cc.

263 {
264 defn->set_previous(graph_entry_);
265 graph_entry_->initial_definitions()->Add(defn);
266}
GrowableArray< Definition * > * initial_definitions()
Definition il.h:1911

◆ AddToInitialDefinitions()

void dart::FlowGraph::AddToInitialDefinitions ( BlockEntryWithInitialDefs entry,
Definition defn 
)

Definition at line 268 of file flow_graph.cc.

269 {
270 ASSERT(defn->previous() == nullptr);
271 defn->set_previous(entry);
272 if (auto par = defn->AsParameter()) {
273 par->set_block(entry); // set cached block
274 }
275 entry->initial_definitions()->Add(defn);
276}

◆ allocate_block_id()

intptr_t dart::FlowGraph::allocate_block_id ( )
inline

Definition at line 266 of file flow_graph.h.

266{ return ++max_block_id_; }

◆ AllocateSSAIndex()

void dart::FlowGraph::AllocateSSAIndex ( Definition def)
inline

Definition at line 274 of file flow_graph.h.

274 {
275 def->set_ssa_temp_index(current_ssa_temp_index_);
276 current_ssa_temp_index_++;
277 }

◆ AppendSpeculativeTo()

Instruction * dart::FlowGraph::AppendSpeculativeTo ( Instruction prev,
Instruction instr,
Environment env,
UseKind  use_kind 
)

Definition at line 317 of file flow_graph.cc.

320 {
321 auto result = AppendTo(prev, instr, env, use_kind);
322 if (instr->env() != nullptr) {
323 instr->env()->MarkAsLazyDeoptToBeforeDeoptId();
324 }
325 return result;
326}
static float prev(float f)
Instruction * AppendTo(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
GAsyncResult * result
Definition __init__.py:1

◆ AppendTo()

Instruction * dart::FlowGraph::AppendTo ( Instruction prev,
Instruction instr,
Environment env,
UseKind  use_kind 
)

Definition at line 303 of file flow_graph.cc.

306 {
307 if (use_kind == kValue) {
308 ASSERT(instr->IsDefinition());
309 AllocateSSAIndex(instr->AsDefinition());
310 }
311 ASSERT(instr->env() == nullptr);
312 if (env != nullptr) {
313 env->DeepCopyTo(zone(), instr);
314 }
315 return prev->AppendInstruction(instr);
316}

◆ ArgumentDescriptorEnvIndex()

intptr_t dart::FlowGraph::ArgumentDescriptorEnvIndex ( ) const
inline

Definition at line 185 of file flow_graph.h.

185 {
186 return EnvIndex(parsed_function().arg_desc_var());
187 }
intptr_t EnvIndex(const LocalVariable *variable) const
Definition flow_graph.h:189

◆ Canonicalize()

bool dart::FlowGraph::Canonicalize ( )

Definition at line 2698 of file flow_graph.cc.

2698 {
2699 bool changed = false;
2700
2701 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2702 block_it.Advance()) {
2703 BlockEntryInstr* const block = block_it.Current();
2704 if (auto join = block->AsJoinEntry()) {
2705 for (PhiIterator it(join); !it.Done(); it.Advance()) {
2706 PhiInstr* current = it.Current();
2707 if (current->HasUnmatchedInputRepresentations() &&
2708 (current->SpeculativeModeOfInputs() == Instruction::kGuardInputs)) {
2709 // Can't canonicalize this instruction until all conversions for its
2710 // speculative inputs are inserted.
2711 continue;
2712 }
2713
2714 Definition* replacement = current->Canonicalize(this);
2715 ASSERT(replacement != nullptr);
2717 !replacement->HasUnmatchedInputRepresentations());
2718 if (replacement != current) {
2719 current->ReplaceUsesWith(replacement);
2720 it.RemoveCurrentFromGraph();
2721 changed = true;
2722 }
2723 }
2724 }
2725 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2726 Instruction* current = it.Current();
2727 if (current->HasUnmatchedInputRepresentations() &&
2728 (current->SpeculativeModeOfInputs() == Instruction::kGuardInputs)) {
2729 // Can't canonicalize this instruction until all conversions for its
2730 // speculative inputs are inserted.
2731 continue;
2732 }
2733
2734 Instruction* replacement = current->Canonicalize(this);
2735
2736 if (replacement != current) {
2737 // For non-definitions Canonicalize should return either nullptr or
2738 // this.
2739 if (replacement != nullptr) {
2740 ASSERT(current->IsDefinition());
2742 RELEASE_ASSERT(!replacement->HasUnmatchedInputRepresentations());
2743 if ((replacement->representation() != current->representation()) &&
2744 current->AsDefinition()->HasUses()) {
2745 // Can't canonicalize this instruction as unmatched
2746 // representations are not allowed at this point, but
2747 // replacement has a different representation.
2748 continue;
2749 }
2750 }
2751 }
2752 ReplaceCurrentInstruction(&it, current, replacement);
2753 changed = true;
2754 }
2755 }
2756 }
2757 return changed;
2758}
#define RELEASE_ASSERT(cond)
Definition assert.h:327
bool Done() const
Definition flow_graph.h:46
void ReplaceCurrentInstruction(ForwardInstructionIterator *iterator, Instruction *current, Instruction *replacement)
bool unmatched_representations_allowed() const
Definition flow_graph.h:411
BlockIterator reverse_postorder_iterator() const
Definition flow_graph.h:219

◆ captured_parameters()

BitVector * dart::FlowGraph::captured_parameters ( ) const
inline

Definition at line 462 of file flow_graph.h.

462{ return captured_parameters_; }

◆ CheckForInstanceCall()

FlowGraph::ToCheck dart::FlowGraph::CheckForInstanceCall ( InstanceCallInstr call,
UntaggedFunction::Kind  kind 
) const

Definition at line 498 of file flow_graph.cc.

500 {
501 if (!FLAG_use_cha_deopt && !isolate_group()->all_classes_finalized()) {
502 // Even if class or function are private, lazy class finalization
503 // may later add overriding methods.
504 return ToCheck::kCheckCid;
505 }
506
507 // Best effort to get the receiver class.
508 Value* receiver = call->Receiver();
509 Class& receiver_class = Class::Handle(zone());
510 bool receiver_maybe_null = false;
511 if (function().IsDynamicFunction() && IsReceiver(receiver->definition())) {
512 // Call receiver is callee receiver: calling "this.g()" in f().
513 receiver_class = function().Owner();
514 } else {
515 // Get the receiver's compile type. Note that
516 // we allow nullable types, which may result in just generating
517 // a null check rather than the more elaborate class check
518 CompileType* type = receiver->Type();
519 const intptr_t receiver_cid = type->ToNullableCid();
520 if (receiver_cid != kDynamicCid) {
521 receiver_class = isolate_group()->class_table()->At(receiver_cid);
522 receiver_maybe_null = type->is_nullable();
523 } else {
524 const AbstractType* atype = type->ToAbstractType();
525 if (atype->IsInstantiated() && atype->HasTypeClass() &&
526 !atype->IsDynamicType()) {
527 if (type->is_nullable()) {
528 receiver_maybe_null = true;
529 }
530 receiver_class = atype->type_class();
531 if (receiver_class.is_implemented()) {
532 receiver_class = Class::null();
533 }
534 }
535 }
536 }
537
538 // Useful receiver class information?
539 if (receiver_class.IsNull()) {
540 return ToCheck::kCheckCid;
541 } else if (call->HasICData()) {
542 // If the static class type does not match information found in ICData
543 // (which may be "guessed"), then bail, since subsequent code generation
544 // (AOT and JIT) for inlining uses the latter.
545 // TODO(ajcbik): improve this by using the static class.
546 const intptr_t cid = receiver_class.id();
547 const ICData* data = call->ic_data();
548 bool match = false;
549 Class& cls = Class::Handle(zone());
550 Function& fun = Function::Handle(zone());
551 for (intptr_t i = 0, len = data->NumberOfChecks(); i < len; i++) {
552 if (!data->IsUsedAt(i)) {
553 continue; // do not consider
554 }
555 fun = data->GetTargetAt(i);
556 cls = fun.Owner();
557 if (data->GetReceiverClassIdAt(i) == cid || cls.id() == cid) {
558 match = true;
559 break;
560 }
561 }
562 if (!match) {
563 return ToCheck::kCheckCid;
564 }
565 }
566
567 const String& method_name =
568 (kind == UntaggedFunction::kMethodExtractor)
569 ? String::Handle(zone(), Field::NameFromGetter(call->function_name()))
570 : call->function_name();
571
572 // If the receiver can have the null value, exclude any method
573 // that is actually valid on a null receiver.
574 if (receiver_maybe_null) {
575 const Class& null_class =
576 Class::Handle(zone(), isolate_group()->object_store()->null_class());
577 Function& target = Function::Handle(zone());
578 if (null_class.EnsureIsFinalized(thread()) == Error::null()) {
579 target = Resolver::ResolveDynamicAnyArgs(zone(), null_class, method_name);
580 }
581 if (!target.IsNull()) {
582 return ToCheck::kCheckCid;
583 }
584 }
585
586 // Use CHA to determine if the method is not overridden by any subclass
587 // of the receiver class. Any methods that are valid when the receiver
588 // has a null value are excluded above (to avoid throwing an exception
589 // on something valid, like null.hashCode).
590 intptr_t subclass_count = 0;
591 CHA& cha = thread()->compiler_state().cha();
592 if (!cha.HasOverride(receiver_class, method_name, &subclass_count)) {
593 if (FLAG_trace_cha) {
594 THR_Print(
595 " **(CHA) Instance call needs no class check since there "
596 "are no overrides of method '%s' on '%s'\n",
597 method_name.ToCString(), receiver_class.ToCString());
598 }
599 if (FLAG_use_cha_deopt) {
600 cha.AddToGuardedClassesForSubclassCount(receiver_class, subclass_count);
601 }
602 return receiver_maybe_null ? ToCheck::kCheckNull : ToCheck::kNoCheck;
603 }
604 return ToCheck::kCheckCid;
605}
static bool match(const char *needle, const char *haystack)
Definition DM.cpp:1132
ClassPtr At(intptr_t cid) const
static StringPtr NameFromGetter(const String &getter_name)
Definition object.cc:11867
bool IsReceiver(Definition *def) const
ClassPtr Owner() const
Definition object.cc:10899
ClassTable * class_table() const
Definition isolate.h:491
static ObjectPtr null()
Definition object.h:433
static FunctionPtr ResolveDynamicAnyArgs(Zone *zone, const Class &receiver_class, const String &function_name, bool allow_add=true)
Definition resolver.cc:198
CompilerState & compiler_state()
Definition thread.h:583
#define THR_Print(format,...)
Definition log.h:20
uint32_t * target
@ kDynamicCid
Definition class_id.h:253
const intptr_t cid
const char *const function_name
static int8_t data[kExtLength]

◆ CodegenBlockOrder() [1/2]

GrowableArray< BlockEntryInstr * > * dart::FlowGraph::CodegenBlockOrder ( )

Definition at line 175 of file flow_graph.cc.

175 {
176 return should_reorder_blocks() ? &optimized_block_order_
177 : &reverse_postorder_;
178}
bool should_reorder_blocks() const
Definition flow_graph.h:510

◆ CodegenBlockOrder() [2/2]

const GrowableArray< BlockEntryInstr * > * dart::FlowGraph::CodegenBlockOrder ( ) const

Definition at line 180 of file flow_graph.cc.

180 {
181 return should_reorder_blocks() ? &optimized_block_order_
182 : &reverse_postorder_;
183}

◆ CompactSSA()

void dart::FlowGraph::CompactSSA ( ZoneGrowableArray< Definition * > *  detached_defs = nullptr)

Definition at line 3355 of file flow_graph.cc.

3355 {
3356 if (detached_defs == nullptr) {
3357 detached_defs = new (Z) ZoneGrowableArray<Definition*>(Z, 0);
3358 }
3359 SSACompactor compactor(max_block_id() + 1, current_ssa_temp_index(),
3360 detached_defs);
3361 compactor.RenumberGraph(this);
3362}
#define Z
intptr_t current_ssa_temp_index() const
Definition flow_graph.h:243

◆ CompilationModeFrom()

static constexpr CompilationMode dart::FlowGraph::CompilationModeFrom ( bool  is_optimizing)
inlinestaticconstexpr

Definition at line 587 of file flow_graph.h.

587 {
588 return is_optimizing ? CompilationMode::kOptimized
590 }

◆ compiler_pass_filters()

const uint8_t * dart::FlowGraph::compiler_pass_filters ( ) const
inline

Definition at line 506 of file flow_graph.h.

506 {
507 return compiler_pass_filters_;
508 }

◆ ComputeArgumentsSizeInWords()

intptr_t dart::FlowGraph::ComputeArgumentsSizeInWords ( const Function function,
intptr_t  arguments_count 
)
static

Definition at line 101 of file flow_graph.cc.

102 {
105
106 const intptr_t fixed_parameters_size_in_bytes =
108
109 // Currently we box all optional parameters.
110 return fixed_parameters_size_in_bytes +
112}
intptr_t num_fixed_parameters() const
Definition object.cc:8914
intptr_t NumParameters() const
Definition object.cc:8935
int argument_count
Definition fuchsia.cc:52

◆ ComputeDominators()

void dart::FlowGraph::ComputeDominators ( GrowableArray< BitVector * > *  dominance_frontier)

Definition at line 978 of file flow_graph.cc.

979 {
980 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass
981 // version of the Lengauer-Tarjan algorithm (LT is normally three passes)
982 // that eliminates a pass by using nearest-common ancestor (NCA) to
983 // compute immediate dominators from semidominators. It also removes a
984 // level of indirection in the link-eval forest data structure.
985 //
986 // The algorithm is described in Georgiadis, Tarjan, and Werneck's
987 // "Finding Dominators in Practice".
988 // https://renatowerneck.files.wordpress.com/2016/06/gtw06-dominators.pdf
989
990 // All arrays are maps between preorder basic-block numbers.
991 intptr_t size = parent_.length();
992 GrowableArray<intptr_t> idom(size); // Immediate dominator.
993 GrowableArray<intptr_t> semi(size); // Semidominator.
994 GrowableArray<intptr_t> label(size); // Label for link-eval forest.
995
996 // 1. First pass: compute semidominators as in Lengauer-Tarjan.
997 // Semidominators are computed from a depth-first spanning tree and are an
998 // approximation of immediate dominators.
999
1000 // Use a link-eval data structure with path compression. Implement path
1001 // compression in place by mutating the parent array. Each block has a
1002 // label, which is the minimum block number on the compressed path.
1003
1004 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the
1005 // dominance frontier output array.
1006 for (intptr_t i = 0; i < size; ++i) {
1007 idom.Add(parent_[i]);
1008 semi.Add(i);
1009 label.Add(i);
1010 dominance_frontier->Add(new (zone()) BitVector(zone(), size));
1011 }
1012
1013 // Loop over the blocks in reverse preorder (not including the graph
1014 // entry). Clear the dominated blocks in the graph entry in case
1015 // ComputeDominators is used to recompute them.
1016 preorder_[0]->ClearDominatedBlocks();
1017 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
1018 // Loop over the predecessors.
1019 BlockEntryInstr* block = preorder_[block_index];
1020 // Clear the immediately dominated blocks in case ComputeDominators is
1021 // used to recompute them.
1022 block->ClearDominatedBlocks();
1023 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) {
1024 BlockEntryInstr* pred = block->PredecessorAt(i);
1025 ASSERT(pred != nullptr);
1026
1027 // Look for the semidominator by ascending the semidominator path
1028 // starting from pred.
1029 intptr_t pred_index = pred->preorder_number();
1030 intptr_t best = pred_index;
1031 if (pred_index > block_index) {
1032 CompressPath(block_index, pred_index, &parent_, &label);
1033 best = label[pred_index];
1034 }
1035
1036 // Update the semidominator if we've found a better one.
1037 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]);
1038 }
1039
1040 // Now use label for the semidominator.
1041 label[block_index] = semi[block_index];
1042 }
1043
1044 // 2. Compute the immediate dominators as the nearest common ancestor of
1045 // spanning tree parent and semidominator, for all blocks except the entry.
1046 for (intptr_t block_index = 1; block_index < size; ++block_index) {
1047 intptr_t dom_index = idom[block_index];
1048 while (dom_index > semi[block_index]) {
1049 dom_index = idom[dom_index];
1050 }
1051 idom[block_index] = dom_index;
1052 preorder_[dom_index]->AddDominatedBlock(preorder_[block_index]);
1053 }
1054
1055 // 3. Now compute the dominance frontier for all blocks. This is
1056 // algorithm in "A Simple, Fast Dominance Algorithm" (Figure 5), which is
1057 // attributed to a paper by Ferrante et al. There is no bookkeeping
1058 // required to avoid adding a block twice to the same block's dominance
1059 // frontier because we use a set to represent the dominance frontier.
1060 for (intptr_t block_index = 0; block_index < size; ++block_index) {
1061 BlockEntryInstr* block = preorder_[block_index];
1062 intptr_t count = block->PredecessorCount();
1063 if (count <= 1) continue;
1064 for (intptr_t i = 0; i < count; ++i) {
1065 BlockEntryInstr* runner = block->PredecessorAt(i);
1066 while (runner != block->dominator()) {
1067 (*dominance_frontier)[runner->preorder_number()]->Add(block_index);
1068 runner = runner->dominator();
1069 }
1070 }
1071 }
1072}
int count
intptr_t length() const
static T Minimum(T x, T y)
Definition utils.h:21
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259

◆ ComputeLocationsOfFixedParameters()

intptr_t dart::FlowGraph::ComputeLocationsOfFixedParameters ( Zone zone,
const Function function,
bool  should_assign_stack_locations = false,
compiler::ParameterInfoArray parameter_info = nullptr 
)
static

Definition at line 1207 of file flow_graph.cc.

1211 {
1214 [&](intptr_t i) {
1215 const intptr_t index = (function.IsFactory() ? (i - 1) : i);
1216 return index >= 0 ? ParameterRepresentationAt(function, index)
1217 : kTagged;
1218 },
1219 should_assign_stack_locations, parameter_info);
1220}
intptr_t ComputeCallingConvention(Zone *zone, const Function &target, intptr_t argc, std::function< Representation(intptr_t)> argument_rep, bool should_assign_stack_locations, ParameterInfoArray *parameter_info)

◆ ComputeSSA()

void dart::FlowGraph::ComputeSSA ( ZoneGrowableArray< Definition * > *  inlining_parameters)

Definition at line 929 of file flow_graph.cc.

930 {
931 GrowableArray<BitVector*> dominance_frontier;
932 GrowableArray<intptr_t> idom;
933
934#ifdef DEBUG
935 if (inlining_parameters != nullptr) {
936 for (intptr_t i = 0, n = inlining_parameters->length(); i < n; ++i) {
937 Definition* defn = (*inlining_parameters)[i];
938 if (defn->IsConstant()) {
939 ASSERT(defn->previous() == graph_entry_);
940 ASSERT(defn->HasSSATemp());
941 ASSERT(defn->ssa_temp_index() < current_ssa_temp_index());
942 } else {
943 ASSERT(defn->previous() == nullptr);
944 ASSERT(!defn->HasSSATemp());
945 }
946 }
947 } else {
949 }
950#endif
951
952 ComputeDominators(&dominance_frontier);
953
954 VariableLivenessAnalysis variable_liveness(this);
955 variable_liveness.Analyze();
956
957 GrowableArray<PhiInstr*> live_phis;
958
959 InsertPhis(preorder_, variable_liveness.ComputeAssignedVars(),
960 dominance_frontier, &live_phis);
961
962 // Rename uses to reference inserted phis where appropriate.
963 // Collect phis that reach a non-environment use.
964 Rename(&live_phis, &variable_liveness, inlining_parameters);
965
966 // Propagate alive mark transitively from alive phis and then remove
967 // non-live ones.
968 RemoveDeadPhis(&live_phis);
969}
void ComputeDominators(GrowableArray< BitVector * > *dominance_frontier)

◆ constant_dead()

ConstantInstr * dart::FlowGraph::constant_dead ( ) const
inline

Definition at line 272 of file flow_graph.h.

272{ return constant_dead_; }

◆ constant_null()

ConstantInstr * dart::FlowGraph::constant_null ( ) const
inline

Definition at line 270 of file flow_graph.h.

270{ return constant_null_; }

◆ CopyDeoptTarget()

void dart::FlowGraph::CopyDeoptTarget ( Instruction to,
Instruction from 
)
inline

Definition at line 395 of file flow_graph.h.

395 {
396 if (is_licm_allowed()) {
397 to->InheritDeoptTarget(zone(), from);
398 }
399 }
bool is_licm_allowed() const
Definition flow_graph.h:404

◆ coverage_array()

const Array & dart::FlowGraph::coverage_array ( ) const
inline

Definition at line 552 of file flow_graph.h.

552{ return *coverage_array_; }

◆ CreateCheckBound()

Definition * dart::FlowGraph::CreateCheckBound ( Definition length,
Definition index,
intptr_t  deopt_id 
)

Definition at line 619 of file flow_graph.cc.

621 {
622 Value* val1 = new (zone()) Value(length);
623 Value* val2 = new (zone()) Value(index);
625 return new (zone()) GenericCheckBoundInstr(val1, val2, deopt_id);
626 }
627 return new (zone()) CheckArrayBoundInstr(val1, val2, deopt_id);
628}
static CompilerState & Current()
size_t length

◆ CreateCheckClass()

Instruction * dart::FlowGraph::CreateCheckClass ( Definition to_check,
const Cids cids,
intptr_t  deopt_id,
const InstructionSource source 
)

Definition at line 607 of file flow_graph.cc.

610 {
611 if (cids.IsMonomorphic() && cids.MonomorphicReceiverCid() == kSmiCid) {
612 return new (zone())
613 CheckSmiInstr(new (zone()) Value(to_check), deopt_id, source);
614 }
615 return new (zone())
616 CheckClassInstr(new (zone()) Value(to_check), deopt_id, cids, source);
617}
SkBitmap source
Definition examples.cpp:28

◆ CreateCommonConstants()

void dart::FlowGraph::CreateCommonConstants ( )

Definition at line 1146 of file flow_graph.cc.

1146 {
1147 constant_null_ = GetConstant(Object::ZoneHandle());
1148 constant_dead_ = GetConstant(Object::optimized_out());
1149}
static Object & ZoneHandle()
Definition object.h:419

◆ current_ssa_temp_index()

intptr_t dart::FlowGraph::current_ssa_temp_index ( ) const
inline

Definition at line 243 of file flow_graph.h.

243{ return current_ssa_temp_index_; }

◆ CurrentContextEnvIndex()

intptr_t dart::FlowGraph::CurrentContextEnvIndex ( ) const
inline

Definition at line 177 of file flow_graph.h.

177 {
178 return EnvIndex(parsed_function().current_context_var());
179 }

◆ CurrentContextVar()

LocalVariable * dart::FlowGraph::CurrentContextVar ( ) const
inline

Definition at line 173 of file flow_graph.h.

173 {
175 }
LocalVariable * current_context_var() const
Definition parser.h:128

◆ disallow_licm()

void dart::FlowGraph::disallow_licm ( )
inline

Definition at line 408 of file flow_graph.h.

408{ licm_allowed_ = false; }

◆ disallow_unmatched_representations()

void dart::FlowGraph::disallow_unmatched_representations ( )
inline

Definition at line 417 of file flow_graph.h.

417 {
418 unmatched_representations_allowed_ = false;
419 }

◆ DiscoverBlocks()

void dart::FlowGraph::DiscoverBlocks ( )

Definition at line 351 of file flow_graph.cc.

351 {
353
354 StackZone zone(thread());
355
356 // Initialize state.
357 preorder_.Clear();
358 postorder_.Clear();
359 reverse_postorder_.Clear();
360 parent_.Clear();
361
362 GrowableArray<BlockTraversalState> block_stack;
363 graph_entry_->DiscoverBlock(nullptr, &preorder_, &parent_);
364 block_stack.Add(BlockTraversalState(graph_entry_));
365 while (!block_stack.is_empty()) {
366 BlockTraversalState& state = block_stack.Last();
367 BlockEntryInstr* block = state.block();
368 if (state.HasNextSuccessor()) {
369 // Process successors one-by-one.
370 BlockEntryInstr* succ = state.NextSuccessor();
371 if (succ->DiscoverBlock(block, &preorder_, &parent_)) {
372 block_stack.Add(BlockTraversalState(succ));
373 }
374 } else {
375 // All successors have been processed, pop the current block entry node
376 // and add it to the postorder list.
377 block_stack.RemoveLast();
378 block->set_postorder_number(postorder_.length());
379 postorder_.Add(block);
380 }
381 }
382
383 ASSERT(postorder_.length() == preorder_.length());
384
385 // Create an array of blocks in reverse postorder.
386 intptr_t block_count = postorder_.length();
387 for (intptr_t i = 0; i < block_count; ++i) {
388 reverse_postorder_.Add(postorder_[block_count - i - 1]);
389 }
390
392}
static int block_count(const SkSBlockAllocator< N > &pool)
bool DiscoverBlock(BlockEntryInstr *predecessor, GrowableArray< BlockEntryInstr * > *preorder, GrowableArray< intptr_t > *parent)
Definition il.cc:1690
void ResetLoopHierarchy()
Definition flow_graph.h:444
#define COMPILER_TIMINGS_TIMER_SCOPE(thread, timer_id)
AtkStateType state

◆ EliminateEnvironments()

void dart::FlowGraph::EliminateEnvironments ( )

Definition at line 2583 of file flow_graph.cc.

2583 {
2584 // After this pass we can no longer perform LICM and hoist instructions
2585 // that can deoptimize.
2586
2587 disallow_licm();
2588 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2589 block_it.Advance()) {
2590 BlockEntryInstr* block = block_it.Current();
2591 if (!block->IsCatchBlockEntry()) {
2592 block->RemoveEnvironment();
2593 }
2594 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2595 Instruction* current = it.Current();
2596 // This check is inconsistent with the flow graph checker. The flow graph
2597 // checker does not allow for not having an env if the block is not
2598 // inside a try-catch.
2599 // See FlowGraphChecker::VisitInstruction.
2600 if (!current->ComputeCanDeoptimize() &&
2601 !current->ComputeCanDeoptimizeAfterCall() &&
2602 (!current->MayThrow() || !current->GetBlock()->InsideTryBlock())) {
2603 // Instructions that can throw need an environment for optimized
2604 // try-catch.
2605 // TODO(srdjan): --source-lines needs deopt environments to get at
2606 // the code for this instruction, however, leaving the environment
2607 // changes code.
2608 current->RemoveEnvironment();
2609 }
2610 }
2611 }
2612}
void disallow_licm()
Definition flow_graph.h:408

◆ EnsureRedefinition()

RedefinitionInstr * dart::FlowGraph::EnsureRedefinition ( Instruction prev,
Definition original,
CompileType  compile_type 
)

Definition at line 1779 of file flow_graph.cc.

1781 {
1782 RedefinitionInstr* first = prev->next()->AsRedefinition();
1783 if (first != nullptr && (first->constrained_type() != nullptr)) {
1784 if ((first->value()->definition() == original) &&
1785 first->constrained_type()->IsEqualTo(&compile_type)) {
1786 // Already redefined. Do nothing.
1787 return nullptr;
1788 }
1789 }
1790 RedefinitionInstr* redef = new RedefinitionInstr(new Value(original));
1791
1792 // Don't set the constrained type when the type is None(), which denotes an
1793 // unreachable value (e.g. using value null after some form of null check).
1794 if (!compile_type.IsNone()) {
1795 redef->set_constrained_type(new CompileType(compile_type));
1796 }
1797
1798 InsertAfter(prev, redef, nullptr, FlowGraph::kValue);
1799 RenameDominatedUses(original, redef, redef);
1800
1801 if (redef->input_use_list() == nullptr) {
1802 // There are no dominated uses, so the newly added Redefinition is useless.
1803 // Remove Redefinition to avoid interfering with
1804 // BranchSimplifier::Simplify which needs empty blocks.
1805 redef->RemoveFromGraph();
1806 return nullptr;
1807 }
1808
1809 return redef;
1810}
static void RenameDominatedUses(Definition *def, Instruction *dom, Definition *other)
void InsertAfter(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)

◆ EnsureSSATempIndex()

void dart::FlowGraph::EnsureSSATempIndex ( Definition defn,
Definition replacement 
)

Definition at line 95 of file flow_graph.cc.

95 {
96 if ((replacement->ssa_temp_index() == -1) && (defn->ssa_temp_index() != -1)) {
97 AllocateSSAIndex(replacement);
98 }
99}

◆ EnvIndex()

intptr_t dart::FlowGraph::EnvIndex ( const LocalVariable variable) const
inline

Definition at line 189 of file flow_graph.h.

189 {
190 ASSERT(!variable->is_captured());
191 return num_direct_parameters_ - variable->index().value();
192 }

◆ ExtractExternalUntaggedPayload()

bool dart::FlowGraph::ExtractExternalUntaggedPayload ( Instruction instr,
Value array,
classid_t  cid 
)

Definition at line 2625 of file flow_graph.cc.

2627 {
2628 ASSERT(array->instruction() == instr);
2629 // Nothing to do if already untagged.
2630 if (array->definition()->representation() != kTagged) return false;
2631 // If we've determined at compile time that this is an object that has an
2632 // external payload, use the cid of the compile type instead.
2633 if (IsExternalPayloadClassId(array->Type()->ToCid())) {
2634 cid = array->Type()->ToCid();
2635 } else if (!IsExternalPayloadClassId(cid)) {
2636 // Can't extract the payload address if it points to GC-managed memory.
2637 return false;
2638 }
2639
2640 const Slot* slot = nullptr;
2641 if (cid == kPointerCid || IsExternalTypedDataClassId(cid)) {
2642 slot = &Slot::PointerBase_data();
2643 } else {
2644 UNREACHABLE();
2645 }
2646
2647 ExtractUntaggedPayload(instr, array, *slot,
2649 return true;
2650}
#define UNREACHABLE()
Definition assert.h:248
bool IsExternalPayloadClassId(classid_t cid)
Definition class_id.h:472
bool IsExternalTypedDataClassId(intptr_t index)
Definition class_id.h:447

◆ ExtractNonInternalTypedDataPayloads()

void dart::FlowGraph::ExtractNonInternalTypedDataPayloads ( )

Definition at line 2676 of file flow_graph.cc.

2676 {
2677 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2678 block_it.Advance()) {
2679 BlockEntryInstr* block = block_it.Current();
2680 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2681 Instruction* current = it.Current();
2682 if (auto* const load_indexed = current->AsLoadIndexed()) {
2683 ExtractNonInternalTypedDataPayload(load_indexed, load_indexed->array(),
2684 load_indexed->class_id());
2685 } else if (auto* const store_indexed = current->AsStoreIndexed()) {
2686 ExtractNonInternalTypedDataPayload(
2687 store_indexed, store_indexed->array(), store_indexed->class_id());
2688 } else if (auto* const memory_copy = current->AsMemoryCopy()) {
2689 ExtractNonInternalTypedDataPayload(memory_copy, memory_copy->src(),
2690 memory_copy->src_cid());
2691 ExtractNonInternalTypedDataPayload(memory_copy, memory_copy->dest(),
2692 memory_copy->dest_cid());
2693 }
2694 }
2695 }
2696}

◆ function()

const Function & dart::FlowGraph::function ( ) const
inline

Definition at line 130 of file flow_graph.h.

130{ return parsed_function_.function(); }

◆ GetConstant()

ConstantInstr * dart::FlowGraph::GetConstant ( const Object object,
Representation  representation = kTagged 
)

Definition at line 192 of file flow_graph.cc.

193 {
194 ConstantInstr* constant = GetExistingConstant(object, representation);
195 if (constant == nullptr) {
196 // Otherwise, allocate and add it to the pool.
197 const Object& zone_object = Object::ZoneHandle(zone(), object.ptr());
198 if (representation == kTagged) {
199 constant = new (zone()) ConstantInstr(zone_object);
200 } else {
201 constant = new (zone()) UnboxedConstantInstr(zone_object, representation);
202 }
203 AllocateSSAIndex(constant);
205 constant_instr_pool_.Insert(constant);
206 }
207 return constant;
208}
ConstantInstr * GetExistingConstant(const Object &object, Representation representation=kTagged) const
void AddToGraphInitialDefinitions(Definition *defn)

◆ GetDirectParameterInfoAt()

const std::pair< Location, Representation > & dart::FlowGraph::GetDirectParameterInfoAt ( intptr_t  i)
inline

Definition at line 573 of file flow_graph.h.

574 {
575 return direct_parameter_locations_[i];
576 }

◆ GetExistingConstant()

ConstantInstr * dart::FlowGraph::GetExistingConstant ( const Object object,
Representation  representation = kTagged 
) const

Definition at line 185 of file flow_graph.cc.

187 {
188 return constant_instr_pool_.LookupValue(
189 ConstantAndRepresentation{object, representation});
190}

◆ GetLoopHierarchy()

const LoopHierarchy & dart::FlowGraph::GetLoopHierarchy ( )
inline

Definition at line 430 of file flow_graph.h.

430 {
431 if (loop_hierarchy_ == nullptr) {
432 loop_hierarchy_ = ComputeLoops();
433 }
434 return loop_hierarchy();
435 }
const LoopHierarchy & loop_hierarchy() const
Definition flow_graph.h:437

◆ graph_entry()

GraphEntryInstr * dart::FlowGraph::graph_entry ( ) const
inline

Definition at line 268 of file flow_graph.h.

268{ return graph_entry_; }

◆ inlining_id()

intptr_t dart::FlowGraph::inlining_id ( ) const
inline

Definition at line 464 of file flow_graph.h.

464{ return inlining_id_; }

◆ InsertAfter()

void dart::FlowGraph::InsertAfter ( Instruction prev,
Instruction instr,
Environment env,
UseKind  use_kind 
)

Definition at line 278 of file flow_graph.cc.

281 {
282 if (use_kind == kValue) {
283 ASSERT(instr->IsDefinition());
284 AllocateSSAIndex(instr->AsDefinition());
285 }
286 instr->InsertAfter(prev);
287 ASSERT(instr->env() == nullptr);
288 if (env != nullptr) {
289 env->DeepCopyTo(zone(), instr);
290 }
291}

◆ InsertBefore()

void dart::FlowGraph::InsertBefore ( Instruction next,
Instruction instr,
Environment env,
UseKind  use_kind 
)
inline

Definition at line 312 of file flow_graph.h.

315 {
316 InsertAfter(next->previous(), instr, env, use_kind);
317 }
static float next(float f)

◆ InsertMoveArguments()

void dart::FlowGraph::InsertMoveArguments ( )

Definition at line 3178 of file flow_graph.cc.

3178 {
3179 compiler::ParameterInfoArray argument_locations;
3180
3181 intptr_t max_argument_slot_count = 0;
3182 auto& target = Function::Handle();
3183
3184 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
3185 block_it.Advance()) {
3187 for (ForwardInstructionIterator instr_it(block_it.Current());
3188 !instr_it.Done(); instr_it.Advance()) {
3189 Instruction* instruction = instr_it.Current();
3190 const intptr_t arg_count = instruction->ArgumentCount();
3191 if (arg_count == 0) {
3192 continue;
3193 }
3194
3196 if (auto static_call = instruction->AsStaticCall()) {
3197 target = static_call->function().ptr();
3198 } else if (auto instance_call = instruction->AsInstanceCallBase()) {
3199 target = instance_call->interface_target().ptr();
3200 } else if (auto dispatch_call = instruction->AsDispatchTableCall()) {
3201 target = dispatch_call->interface_target().ptr();
3202 } else if (auto cachable_call = instruction->AsCachableIdempotentCall()) {
3203 target = cachable_call->function().ptr();
3204 }
3205
3206 MoveArgumentsArray* arguments =
3207 new (Z) MoveArgumentsArray(zone(), arg_count);
3208 arguments->EnsureLength(arg_count, nullptr);
3209
3210 const intptr_t stack_arguments_size_in_words =
3212 zone(), target, arg_count,
3213 [&](intptr_t i) {
3214 return instruction->RequiredInputRepresentation(i);
3215 },
3216 /*should_assign_stack_locations=*/true, &argument_locations);
3217
3218 for (intptr_t i = 0; i < arg_count; ++i) {
3219 const auto& [location, rep] = argument_locations[i];
3220 Value* arg = instruction->ArgumentValueAt(i);
3221 (*arguments)[i] = new (Z) MoveArgumentInstr(
3222 arg->CopyWithType(Z), rep, location.ToCallerSpRelative());
3223 }
3225 stack_arguments_size_in_words);
3226
3227 for (auto move_arg : *arguments) {
3228 // Insert all MoveArgument instructions immediately before call.
3229 // MoveArgumentInstr::EmitNativeCode may generate more efficient
3230 // code for subsequent MoveArgument instructions (ARM, ARM64).
3231 if (!move_arg->is_register_move()) {
3232 InsertBefore(instruction, move_arg, /*env=*/nullptr, kEffect);
3233 }
3234 }
3235 instruction->ReplaceInputsWithMoveArguments(arguments);
3236 if (instruction->env() != nullptr) {
3237 instruction->RepairArgumentUsesInEnvironment();
3238 }
3239 }
3240 }
3242}
intptr_t max_argument_slot_count() const
Definition flow_graph.h:564
void set_max_argument_slot_count(intptr_t count)
Definition flow_graph.h:568
void CheckForSafepoint()
Definition thread.h:1091
static constexpr T Maximum(T x, T y)
Definition utils.h:26
GrowableArray< std::pair< Location, Representation > > ParameterInfoArray
ZoneGrowableArray< MoveArgumentInstr * > MoveArgumentsArray
Definition il.h:896

◆ InsertSpeculativeAfter()

void dart::FlowGraph::InsertSpeculativeAfter ( Instruction prev,
Instruction instr,
Environment env,
UseKind  use_kind 
)

Definition at line 293 of file flow_graph.cc.

296 {
297 InsertAfter(prev, instr, env, use_kind);
298 if (instr->env() != nullptr) {
299 instr->env()->MarkAsLazyDeoptToBeforeDeoptId();
300 }
301}

◆ InsertSpeculativeBefore()

void dart::FlowGraph::InsertSpeculativeBefore ( Instruction next,
Instruction instr,
Environment env,
UseKind  use_kind 
)
inline

Definition at line 318 of file flow_graph.h.

321 {
322 InsertSpeculativeAfter(next->previous(), instr, env, use_kind);
323 }
void InsertSpeculativeAfter(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)

◆ InstructionCount()

intptr_t dart::FlowGraph::InstructionCount ( ) const

Definition at line 1898 of file flow_graph.cc.

1898 {
1899 intptr_t size = 0;
1900 // Iterate each block, skipping the graph entry.
1901 for (intptr_t i = 1; i < preorder_.length(); ++i) {
1902 BlockEntryInstr* block = preorder_[i];
1903
1904 // Skip any blocks from the prologue to make them not count towards the
1905 // inlining instruction budget.
1906 const intptr_t block_id = block->block_id();
1907 if (prologue_info_.Contains(block_id)) {
1908 continue;
1909 }
1910
1911 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1912 ++size;
1913 }
1914 }
1915 return size;
1916}
bool Contains(intptr_t block_id) const
Definition flow_graph.h:108

◆ is_huge_method()

bool dart::FlowGraph::is_huge_method ( ) const
inline

Definition at line 423 of file flow_graph.h.

423{ return huge_method_; }

◆ is_licm_allowed()

bool dart::FlowGraph::is_licm_allowed ( ) const
inline

Definition at line 404 of file flow_graph.h.

404{ return licm_allowed_; }

◆ IsCompiledForOsr()

bool dart::FlowGraph::IsCompiledForOsr ( ) const
inline

Definition at line 460 of file flow_graph.h.

460{ return graph_entry()->IsCompiledForOsr(); }
bool IsCompiledForOsr() const
Definition il.cc:1255

◆ IsConstantRepresentable()

bool dart::FlowGraph::IsConstantRepresentable ( const Object value,
Representation  target_rep,
bool  tagged_value_must_be_smi 
)
static

Definition at line 210 of file flow_graph.cc.

212 {
213 switch (target_rep) {
214 case kTagged:
215 return !tagged_value_must_be_smi || value.IsSmi();
216
217 case kUnboxedInt32:
218 if (value.IsInteger()) {
219 return Utils::IsInt(32, Integer::Cast(value).AsInt64Value());
220 }
221 return false;
222
223 case kUnboxedUint32:
224 if (value.IsInteger()) {
225 return Utils::IsUint(32, Integer::Cast(value).AsInt64Value());
226 }
227 return false;
228
229 case kUnboxedInt64:
230 return value.IsInteger();
231
232 case kUnboxedFloat:
233 case kUnboxedDouble:
234 return value.IsInteger() || value.IsDouble();
235
236 default:
237 return false;
238 }
239}
static bool IsInt(intptr_t N, T value)
Definition utils.h:298
static bool IsUint(intptr_t N, T value)
Definition utils.h:313
uint8_t value

◆ IsImmortalVariable()

bool dart::FlowGraph::IsImmortalVariable ( intptr_t  env_index) const
inline

Definition at line 196 of file flow_graph.h.

196 {
197 return (env_index == CurrentContextEnvIndex()) ||
198 (SuspendStateVar() != nullptr &&
199 env_index == SuspendStateEnvIndex());
200 }
intptr_t SuspendStateEnvIndex() const
Definition flow_graph.h:171
intptr_t CurrentContextEnvIndex() const
Definition flow_graph.h:177
LocalVariable * SuspendStateVar() const
Definition flow_graph.h:167

◆ IsIrregexpFunction()

bool dart::FlowGraph::IsIrregexpFunction ( ) const
inline

Definition at line 165 of file flow_graph.h.

165{ return function().IsIrregexpFunction(); }
bool IsIrregexpFunction() const
Definition object.h:3878

◆ isolate_group()

IsolateGroup * dart::FlowGraph::isolate_group ( ) const
inline

Definition at line 262 of file flow_graph.h.

262{ return thread()->isolate_group(); }
IsolateGroup * isolate_group() const
Definition thread.h:540

◆ IsReceiver()

bool dart::FlowGraph::IsReceiver ( Definition def) const

Definition at line 483 of file flow_graph.cc.

483 {
484 def = def->OriginalDefinition(); // Could be redefined.
485 if (def->IsParameter()) return (def->AsParameter()->env_index() == 0);
486 if (!def->IsPhi() || graph_entry()->HasSingleEntryPoint()) {
487 return false;
488 }
489 PhiInstr* phi = def->AsPhi();
490 if (phi->is_receiver() != PhiInstr::kUnknownReceiver) {
491 return (phi->is_receiver() == PhiInstr::kReceiver);
492 }
493 // Not known if this phi is the receiver yet. Compute it now.
494 ComputeIsReceiver(phi);
495 return (phi->is_receiver() == PhiInstr::kReceiver);
496}
@ kUnknownReceiver
Definition il.h:2866

◆ loop_hierarchy()

const LoopHierarchy & dart::FlowGraph::loop_hierarchy ( ) const
inline

Definition at line 437 of file flow_graph.h.

437{ return *loop_hierarchy_; }

◆ loop_invariant_loads()

ZoneGrowableArray< BitVector * > * dart::FlowGraph::loop_invariant_loads ( ) const
inline

Definition at line 452 of file flow_graph.h.

452 {
453 return loop_invariant_loads_;
454 }

◆ mark_huge_method()

void dart::FlowGraph::mark_huge_method ( )
inline

Definition at line 425 of file flow_graph.h.

425{ huge_method_ = true; }

◆ max_argument_slot_count()

intptr_t dart::FlowGraph::max_argument_slot_count ( ) const
inline

Definition at line 564 of file flow_graph.h.

564 {
565 RELEASE_ASSERT(max_argument_slot_count_ >= 0);
566 return max_argument_slot_count_;
567 }

◆ max_block_id()

intptr_t dart::FlowGraph::max_block_id ( ) const
inline

Definition at line 264 of file flow_graph.h.

264{ return max_block_id_; }

◆ max_vreg()

intptr_t dart::FlowGraph::max_vreg ( ) const
inline

Definition at line 248 of file flow_graph.h.

248 {
250 }
static constexpr intptr_t kMaxLocationCount
Definition locations.h:73

◆ MergeBlocks()

void dart::FlowGraph::MergeBlocks ( )

Definition at line 394 of file flow_graph.cc.

394 {
395 bool changed = false;
396 BitVector* merged = new (zone()) BitVector(zone(), postorder().length());
397 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
398 block_it.Advance()) {
399 BlockEntryInstr* block = block_it.Current();
400 if (block->IsGraphEntry()) continue;
401 if (merged->Contains(block->postorder_number())) continue;
402
403 Instruction* last = block->last_instruction();
404 BlockEntryInstr* last_merged_block = nullptr;
405 while (auto goto_instr = last->AsGoto()) {
406 JoinEntryInstr* successor = goto_instr->successor();
407 if (successor->PredecessorCount() > 1) break;
408 if (block->try_index() != successor->try_index()) break;
409
410 // Replace all phis with their arguments prior to removing successor.
411 for (PhiIterator it(successor); !it.Done(); it.Advance()) {
412 PhiInstr* phi = it.Current();
413 Value* input = phi->InputAt(0);
414 phi->ReplaceUsesWith(input->definition());
415 input->RemoveFromUseList();
416 }
417
418 // Remove environment uses and unlink goto and block entry.
419 successor->UnuseAllInputs();
420 last->previous()->LinkTo(successor->next());
421 last->UnuseAllInputs();
422
423 last = successor->last_instruction();
424 merged->Add(successor->postorder_number());
425 last_merged_block = successor;
426 changed = true;
427 if (FLAG_trace_optimization && should_print()) {
428 THR_Print("Merged blocks B%" Pd " and B%" Pd "\n", block->block_id(),
429 successor->block_id());
430 }
431 }
432 // The new block inherits the block id of the last successor to maintain
433 // the order of phi inputs at its successors consistent with block ids.
434 if (last_merged_block != nullptr) {
435 block->set_block_id(last_merged_block->block_id());
436 }
437 }
438 // Recompute block order after changes were made.
439 if (changed) DiscoverBlocks();
440}
bool should_print() const
Definition flow_graph.h:505
const GrowableArray< BlockEntryInstr * > & postorder() const
Definition flow_graph.h:204
#define Pd
Definition globals.h:408

◆ NewDiamond() [1/2]

JoinEntryInstr * dart::FlowGraph::NewDiamond ( Instruction instruction,
Instruction inherit,
ComparisonInstr compare,
TargetEntryInstr **  block_true,
TargetEntryInstr **  block_false 
)

Definition at line 3090 of file flow_graph.cc.

3094 {
3095 BlockEntryInstr* entry = instruction->GetBlock();
3096
3097 TargetEntryInstr* bt = NewTarget(this, inherit);
3098 TargetEntryInstr* bf = NewTarget(this, inherit);
3099 JoinEntryInstr* join = NewJoin(this, inherit);
3100 GotoInstr* gotot = NewGoto(this, join, inherit);
3101 GotoInstr* gotof = NewGoto(this, join, inherit);
3102 BranchInstr* bra = NewBranch(this, compare, inherit);
3103
3104 instruction->AppendInstruction(bra);
3105 entry->set_last_instruction(bra);
3106
3107 *bra->true_successor_address() = bt;
3108 *bra->false_successor_address() = bf;
3109
3110 bt->AppendInstruction(gotot);
3111 bt->set_last_instruction(gotot);
3112
3113 bf->AppendInstruction(gotof);
3114 bf->set_last_instruction(gotof);
3115
3116 // Update dominance relation incrementally.
3117 for (intptr_t i = 0, n = entry->dominated_blocks().length(); i < n; ++i) {
3118 join->AddDominatedBlock(entry->dominated_blocks()[i]);
3119 }
3120 entry->ClearDominatedBlocks();
3121 entry->AddDominatedBlock(bt);
3122 entry->AddDominatedBlock(bf);
3123 entry->AddDominatedBlock(join);
3124
3125 // TODO(ajcbik): update pred/succ/ordering incrementally too.
3126
3127 // Return new blocks.
3128 *b_true = bt;
3129 *b_false = bf;
3130 return join;
3131}
static bool compare(const SkBitmap &ref, const SkIRect &iref, const SkBitmap &test, const SkIRect &itest)
Definition BlurTest.cpp:100
static JoinEntryInstr * NewJoin(FlowGraph *graph, Instruction *inherit)
static GotoInstr * NewGoto(FlowGraph *graph, JoinEntryInstr *target, Instruction *inherit)
static BranchInstr * NewBranch(FlowGraph *graph, ComparisonInstr *cmp, Instruction *inherit)
static TargetEntryInstr * NewTarget(FlowGraph *graph, Instruction *inherit)

◆ NewDiamond() [2/2]

JoinEntryInstr * dart::FlowGraph::NewDiamond ( Instruction instruction,
Instruction inherit,
const LogicalAnd condition,
TargetEntryInstr **  block_true,
TargetEntryInstr **  block_false 
)

Definition at line 3133 of file flow_graph.cc.

3137 {
3138 // First diamond for first comparison.
3139 TargetEntryInstr* bt = nullptr;
3140 TargetEntryInstr* bf = nullptr;
3141 JoinEntryInstr* mid_point =
3142 NewDiamond(instruction, inherit, condition.oper1, &bt, &bf);
3143
3144 // Short-circuit second comparison and connect through phi.
3145 condition.oper2->InsertAfter(bt);
3146 AllocateSSAIndex(condition.oper2);
3147 condition.oper2->InheritDeoptTarget(zone(), inherit); // must inherit
3148 PhiInstr* phi =
3149 AddPhi(mid_point, condition.oper2, GetConstant(Bool::False()));
3150 StrictCompareInstr* circuit = new (zone()) StrictCompareInstr(
3151 inherit->source(), Token::kEQ_STRICT, new (zone()) Value(phi),
3152 new (zone()) Value(GetConstant(Bool::True())), false,
3153 DeoptId::kNone); // don't inherit
3154
3155 // Return new blocks through the second diamond.
3156 return NewDiamond(mid_point, inherit, circuit, b_true, b_false);
3157}
static const Bool & False()
Definition object.h:10778
static const Bool & True()
Definition object.h:10776
static constexpr intptr_t kNone
Definition deopt_id.h:27
JoinEntryInstr * NewDiamond(Instruction *instruction, Instruction *inherit, ComparisonInstr *compare, TargetEntryInstr **block_true, TargetEntryInstr **block_false)
PhiInstr * AddPhi(JoinEntryInstr *join, Definition *d1, Definition *d2)

◆ num_direct_parameters()

intptr_t dart::FlowGraph::num_direct_parameters ( ) const
inline

Definition at line 137 of file flow_graph.h.

137{ return num_direct_parameters_; }

◆ num_stack_locals()

intptr_t dart::FlowGraph::num_stack_locals ( ) const
inline

Definition at line 161 of file flow_graph.h.

161 {
162 return parsed_function_.num_stack_locals();
163 }
int num_stack_locals() const
Definition parser.h:194

◆ optimized_block_order()

const GrowableArray< BlockEntryInstr * > & dart::FlowGraph::optimized_block_order ( ) const
inline

Definition at line 210 of file flow_graph.h.

210 {
211 return optimized_block_order_;
212 }

◆ osr_variable_count()

intptr_t dart::FlowGraph::osr_variable_count ( ) const
inline

Definition at line 149 of file flow_graph.h.

149 {
152 }
intptr_t stack_depth() const
Definition il.h:1750
bool IsCompiledForOsr() const
Definition flow_graph.h:460
OsrEntryInstr * osr_entry() const
Definition il.h:1992

◆ ParameterRepresentationAt()

Representation dart::FlowGraph::ParameterRepresentationAt ( const Function function,
intptr_t  index 
)
static

Definition at line 114 of file flow_graph.cc.

115 {
116 if (function.IsNull()) {
117 return kTagged;
118 }
119 ASSERT(index < function.NumParameters());
121 return kUnboxedInt64;
122 } else if (function.is_unboxed_double_parameter_at(index)) {
123 return kUnboxedDouble;
124 } else {
126 return kTagged;
127 }
128}
bool is_unboxed_integer_parameter_at(intptr_t index) const
Definition object.h:3763
bool is_unboxed_parameter_at(intptr_t index) const
Definition object.h:3753
bool is_unboxed_double_parameter_at(intptr_t index) const
Definition object.h:3773
bool IsNull() const
Definition object.h:363

◆ parsed_function()

const ParsedFunction & dart::FlowGraph::parsed_function ( ) const
inline

Definition at line 129 of file flow_graph.h.

129{ return parsed_function_; }

◆ PopulateWithICData()

void dart::FlowGraph::PopulateWithICData ( const Function function)

Definition at line 2760 of file flow_graph.cc.

2760 {
2761 Zone* zone = Thread::Current()->zone();
2762
2763 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2764 block_it.Advance()) {
2765 ForwardInstructionIterator it(block_it.Current());
2766 for (; !it.Done(); it.Advance()) {
2767 Instruction* instr = it.Current();
2768 if (instr->IsInstanceCall()) {
2769 InstanceCallInstr* call = instr->AsInstanceCall();
2770 if (!call->HasICData()) {
2771 const Array& arguments_descriptor =
2772 Array::Handle(zone, call->GetArgumentsDescriptor());
2773 const ICData& ic_data = ICData::ZoneHandle(
2774 zone,
2775 ICData::New(function, call->function_name(), arguments_descriptor,
2776 call->deopt_id(), call->checked_argument_count(),
2777 ICData::kInstance));
2778 call->set_ic_data(&ic_data);
2779 }
2780 } else if (instr->IsStaticCall()) {
2781 StaticCallInstr* call = instr->AsStaticCall();
2782 if (!call->HasICData()) {
2783 const Array& arguments_descriptor =
2784 Array::Handle(zone, call->GetArgumentsDescriptor());
2785 const Function& target = call->function();
2786 int num_args_checked =
2788 const ICData& ic_data = ICData::ZoneHandle(
2790 function, target, arguments_descriptor,
2791 call->deopt_id(), num_args_checked, ICData::kStatic));
2792 call->set_ic_data(&ic_data);
2793 }
2794 }
2795 }
2796 }
2797}
static ICDataPtr NewForStaticCall(const Function &owner, const Function &target, const Array &arguments_descriptor, intptr_t deopt_id, intptr_t num_args_tested, RebindRule rebind_rule)
Definition object.cc:17448
static intptr_t NumArgsCheckedForStaticCall(const Function &function)
Zone * zone() const

◆ postorder()

const GrowableArray< BlockEntryInstr * > & dart::FlowGraph::postorder ( ) const
inline

Definition at line 204 of file flow_graph.h.

204 {
205 return postorder_;
206 }

◆ postorder_iterator()

BlockIterator dart::FlowGraph::postorder_iterator ( ) const
inline

Definition at line 222 of file flow_graph.h.

222 {
223 return BlockIterator(postorder());
224 }

◆ preorder()

const GrowableArray< BlockEntryInstr * > & dart::FlowGraph::preorder ( ) const
inline

Definition at line 203 of file flow_graph.h.

203{ return preorder_; }

◆ Print()

void dart::FlowGraph::Print ( const char *  phase = "unknown")

Definition at line 3244 of file flow_graph.cc.

3244 {
3245 FlowGraphPrinter::PrintGraph(phase, this);
3246}
static void PrintGraph(const char *phase, FlowGraph *flow_graph)

◆ prologue_info()

PrologueInfo dart::FlowGraph::prologue_info ( ) const
inline

Definition at line 427 of file flow_graph.h.

427{ return prologue_info_; }

◆ RawTypeArgumentEnvIndex()

intptr_t dart::FlowGraph::RawTypeArgumentEnvIndex ( ) const
inline

Definition at line 181 of file flow_graph.h.

181 {
182 return EnvIndex(parsed_function().RawTypeArgumentsVariable());
183 }

◆ RemoveRedefinitions()

void dart::FlowGraph::RemoveRedefinitions ( bool  keep_checks = false)

Definition at line 1812 of file flow_graph.cc.

1812 {
1813 // Remove redefinition and check instructions that were inserted
1814 // to make a control dependence explicit with a data dependence,
1815 // for example, to inhibit hoisting.
1816 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
1817 block_it.Advance()) {
1819 for (ForwardInstructionIterator instr_it(block_it.Current());
1820 !instr_it.Done(); instr_it.Advance()) {
1821 Instruction* instruction = instr_it.Current();
1822 if (auto redef = instruction->AsRedefinition()) {
1823 redef->ReplaceUsesWith(redef->value()->definition());
1824 instr_it.RemoveCurrentFromGraph();
1825 } else if (keep_checks) {
1826 continue;
1827 } else if (auto def = instruction->AsDefinition()) {
1828 Value* value = def->RedefinedValue();
1829 if (value != nullptr) {
1830 def->ReplaceUsesWith(value->definition());
1831 def->ClearSSATempIndex();
1832 }
1833 }
1834 }
1835 }
1836}

◆ RenameDominatedUses()

void dart::FlowGraph::RenameDominatedUses ( Definition def,
Instruction dom,
Definition other 
)
static

Definition at line 2874 of file flow_graph.cc.

2876 {
2877 for (Value::Iterator it(def->input_use_list()); !it.Done(); it.Advance()) {
2878 Value* use = it.Current();
2879 if (IsDominatedUse(dom, use)) {
2880 use->BindTo(other);
2881 }
2882 }
2883}
static bool IsDominatedUse(Instruction *dom, Value *use)
Definition dom.py:1

◆ RenameUsesDominatedByRedefinitions()

void dart::FlowGraph::RenameUsesDominatedByRedefinitions ( )

Definition at line 2885 of file flow_graph.cc.

2885 {
2886 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2887 block_it.Advance()) {
2888 for (ForwardInstructionIterator instr_it(block_it.Current());
2889 !instr_it.Done(); instr_it.Advance()) {
2890 Definition* definition = instr_it.Current()->AsDefinition();
2891 // CheckArrayBound instructions have their own mechanism for ensuring
2892 // proper dependencies, so we don't rewrite those here.
2893 if (definition != nullptr && !definition->IsCheckArrayBound()) {
2894 Value* redefined = definition->RedefinedValue();
2895 if (redefined != nullptr) {
2896 if (!definition->HasSSATemp()) {
2897 AllocateSSAIndex(definition);
2898 }
2899 Definition* original = redefined->definition();
2900 RenameDominatedUses(original, definition, definition);
2901 }
2902 }
2903 }
2904 }
2905}

◆ ReplaceCurrentInstruction()

void dart::FlowGraph::ReplaceCurrentInstruction ( ForwardInstructionIterator iterator,
Instruction current,
Instruction replacement 
)

Definition at line 146 of file flow_graph.cc.

148 {
149 Definition* current_defn = current->AsDefinition();
150 if ((replacement != nullptr) && (current_defn != nullptr)) {
151 Definition* replacement_defn = replacement->AsDefinition();
152 ASSERT(replacement_defn != nullptr);
153 current_defn->ReplaceUsesWith(replacement_defn);
154 EnsureSSATempIndex(current_defn, replacement_defn);
155
156 if (FLAG_trace_optimization && should_print()) {
157 THR_Print("Replacing v%" Pd " with v%" Pd "\n",
158 current_defn->ssa_temp_index(),
159 replacement_defn->ssa_temp_index());
160 }
161 } else if (FLAG_trace_optimization && should_print()) {
162 if (current_defn == nullptr) {
163 THR_Print("Removing %s\n", current->DebugName());
164 } else {
165 ASSERT(!current_defn->HasUses());
166 THR_Print("Removing v%" Pd ".\n", current_defn->ssa_temp_index());
167 }
168 }
169 if (current->ArgumentCount() != 0) {
170 ASSERT(!current->HasMoveArguments());
171 }
172 iterator->RemoveCurrentFromGraph();
173}
void EnsureSSATempIndex(Definition *defn, Definition *replacement)
Definition flow_graph.cc:95

◆ ResetLoopHierarchy()

void dart::FlowGraph::ResetLoopHierarchy ( )
inline

Definition at line 444 of file flow_graph.h.

444 {
445 loop_hierarchy_ = nullptr;
446 loop_invariant_loads_ = nullptr;
447 }

◆ ReturnRepresentationOf()

Representation dart::FlowGraph::ReturnRepresentationOf ( const Function function)
static

Definition at line 130 of file flow_graph.cc.

130 {
131 if (function.IsNull()) {
132 return kTagged;
133 }
135 return kUnboxedInt64;
136 } else if (function.has_unboxed_double_return()) {
137 return kUnboxedDouble;
138 } else if (function.has_unboxed_record_return()) {
139 return kPairOfTagged;
140 } else {
142 return kTagged;
143 }
144}
bool has_unboxed_return() const
Definition object.h:3783
bool has_unboxed_double_return() const
Definition object.h:3799
bool has_unboxed_integer_return() const
Definition object.h:3791
bool has_unboxed_record_return() const
Definition object.h:3807

◆ reverse_postorder()

const GrowableArray< BlockEntryInstr * > & dart::FlowGraph::reverse_postorder ( ) const
inline

Definition at line 207 of file flow_graph.h.

207 {
208 return reverse_postorder_;
209 }

◆ reverse_postorder_iterator()

BlockIterator dart::FlowGraph::reverse_postorder_iterator ( ) const
inline

Definition at line 219 of file flow_graph.h.

219 {
220 return BlockIterator(reverse_postorder());
221 }
const GrowableArray< BlockEntryInstr * > & reverse_postorder() const
Definition flow_graph.h:207

◆ SelectRepresentations()

void dart::FlowGraph::SelectRepresentations ( )

Definition at line 2307 of file flow_graph.cc.

2307 {
2308 // First we decide for each phi if it is beneficial to unbox it. If so, we
2309 // change it's `phi->representation()`
2310 PhiUnboxingHeuristic phi_unboxing_heuristic(this);
2311 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2312 block_it.Advance()) {
2313 JoinEntryInstr* join_entry = block_it.Current()->AsJoinEntry();
2314 if (join_entry != nullptr) {
2315 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
2316 PhiInstr* phi = it.Current();
2317 phi_unboxing_heuristic.Process(phi);
2318 }
2319 }
2320 }
2321
2322 // Process all initial definitions and insert conversions when needed (depends
2323 // on phi unboxing decision above).
2324 for (intptr_t i = 0; i < graph_entry()->initial_definitions()->length();
2325 i++) {
2326 InsertConversionsFor((*graph_entry()->initial_definitions())[i]);
2327 }
2328 for (intptr_t i = 0; i < graph_entry()->SuccessorCount(); ++i) {
2329 auto successor = graph_entry()->SuccessorAt(i);
2330 if (auto entry = successor->AsBlockEntryWithInitialDefs()) {
2331 auto& initial_definitions = *entry->initial_definitions();
2332 for (intptr_t j = 0; j < initial_definitions.length(); j++) {
2333 InsertConversionsFor(initial_definitions[j]);
2334 }
2335 }
2336 }
2337
2338 // Process all normal definitions and insert conversions when needed (depends
2339 // on phi unboxing decision above).
2340 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2341 block_it.Advance()) {
2342 BlockEntryInstr* entry = block_it.Current();
2343 if (JoinEntryInstr* join_entry = entry->AsJoinEntry()) {
2344 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
2345 PhiInstr* phi = it.Current();
2346 ASSERT(phi != nullptr);
2347 ASSERT(phi->is_alive());
2348 InsertConversionsFor(phi);
2349 }
2350 }
2351 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
2352 Definition* def = it.Current()->AsDefinition();
2353 if (def != nullptr) {
2354 InsertConversionsFor(def);
2355 }
2356 }
2357 }
2358}
virtual BlockEntryInstr * SuccessorAt(intptr_t index) const
Definition il.cc:1985
virtual intptr_t SuccessorCount() const
Definition il.cc:1979

◆ set_coverage_array()

void dart::FlowGraph::set_coverage_array ( const Array array)
inline

Definition at line 553 of file flow_graph.h.

553{ coverage_array_ = &array; }

◆ set_current_ssa_temp_index()

void dart::FlowGraph::set_current_ssa_temp_index ( intptr_t  index)
inline

Definition at line 244 of file flow_graph.h.

244 {
245 current_ssa_temp_index_ = index;
246 }

◆ set_inlining_id()

void dart::FlowGraph::set_inlining_id ( intptr_t  value)
inline

Definition at line 465 of file flow_graph.h.

465{ inlining_id_ = value; }

◆ set_loop_invariant_loads()

void dart::FlowGraph::set_loop_invariant_loads ( ZoneGrowableArray< BitVector * > *  loop_invariant_loads)
inline

Definition at line 455 of file flow_graph.h.

456 {
457 loop_invariant_loads_ = loop_invariant_loads;
458 }
ZoneGrowableArray< BitVector * > * loop_invariant_loads() const
Definition flow_graph.h:452

◆ set_max_argument_slot_count()

void dart::FlowGraph::set_max_argument_slot_count ( intptr_t  count)
inline

Definition at line 568 of file flow_graph.h.

568 {
569 RELEASE_ASSERT(max_argument_slot_count_ == -1);
570 max_argument_slot_count_ = count;
571 }

◆ set_max_block_id()

void dart::FlowGraph::set_max_block_id ( intptr_t  id)
inline

Definition at line 265 of file flow_graph.h.

265{ max_block_id_ = id; }
const uintptr_t id

◆ should_print()

bool dart::FlowGraph::should_print ( ) const
inline

Definition at line 505 of file flow_graph.h.

505{ return should_print_; }

◆ should_remove_all_bounds_checks()

bool dart::FlowGraph::should_remove_all_bounds_checks ( ) const
inline

Definition at line 512 of file flow_graph.h.

512 {
513 return should_remove_all_bounds_checks_;
514 }

◆ should_reorder_blocks()

bool dart::FlowGraph::should_reorder_blocks ( ) const
inline

Definition at line 510 of file flow_graph.h.

510{ return should_reorder_blocks_; }

◆ SuspendStateEnvIndex()

intptr_t dart::FlowGraph::SuspendStateEnvIndex ( ) const
inline

Definition at line 171 of file flow_graph.h.

171{ return EnvIndex(SuspendStateVar()); }

◆ SuspendStateVar()

LocalVariable * dart::FlowGraph::SuspendStateVar ( ) const
inline

Definition at line 167 of file flow_graph.h.

167 {
169 }
LocalVariable * suspend_state_var() const
Definition parser.h:103

◆ thread()

Thread * dart::FlowGraph::thread ( ) const
inline

Definition at line 260 of file flow_graph.h.

260{ return thread_; }

◆ TryCreateConstantReplacementFor()

Definition * dart::FlowGraph::TryCreateConstantReplacementFor ( Definition op,
const Object value 
)

Definition at line 241 of file flow_graph.cc.

242 {
243 // Check that representation of the constant matches expected representation.
244 const auto representation = op->representation();
246 value, representation,
247 /*tagged_value_must_be_smi=*/op->Type()->IsNullableSmi())) {
248 return op;
249 }
250
251 if (((representation == kUnboxedFloat) ||
252 (representation == kUnboxedDouble)) &&
253 value.IsInteger()) {
254 // Convert the boxed constant from int to float/double.
256 Integer::Cast(value).AsDoubleValue())),
257 representation);
258 }
259
260 return GetConstant(value, representation);
261}
static DoublePtr NewCanonical(double d)
Definition object.cc:23497
static bool IsConstantRepresentable(const Object &value, Representation target_rep, bool tagged_value_must_be_smi)

◆ TryOptimizePatterns()

void dart::FlowGraph::TryOptimizePatterns ( )

Definition at line 2802 of file flow_graph.cc.

2802 {
2803 if (!FLAG_truncating_left_shift) return;
2804 GrowableArray<BinarySmiOpInstr*> div_mod_merge;
2805 GrowableArray<InvokeMathCFunctionInstr*> sin_cos_merge;
2806 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2807 block_it.Advance()) {
2808 // Merging only per basic-block.
2809 div_mod_merge.Clear();
2810 sin_cos_merge.Clear();
2811 ForwardInstructionIterator it(block_it.Current());
2812 for (; !it.Done(); it.Advance()) {
2813 if (it.Current()->IsBinarySmiOp()) {
2814 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp();
2815 if (binop->op_kind() == Token::kBIT_AND) {
2816 OptimizeLeftShiftBitAndSmiOp(&it, binop, binop->left()->definition(),
2817 binop->right()->definition());
2818 } else if ((binop->op_kind() == Token::kTRUNCDIV) ||
2819 (binop->op_kind() == Token::kMOD)) {
2820 if (binop->HasUses()) {
2821 div_mod_merge.Add(binop);
2822 }
2823 }
2824 } else if (it.Current()->IsBinaryInt64Op()) {
2825 BinaryInt64OpInstr* mintop = it.Current()->AsBinaryInt64Op();
2826 if (mintop->op_kind() == Token::kBIT_AND) {
2827 OptimizeLeftShiftBitAndSmiOp(&it, mintop,
2828 mintop->left()->definition(),
2829 mintop->right()->definition());
2830 }
2831 } else if (it.Current()->IsInvokeMathCFunction()) {
2832 InvokeMathCFunctionInstr* math_unary =
2833 it.Current()->AsInvokeMathCFunction();
2834 if ((math_unary->recognized_kind() == MethodRecognizer::kMathSin) ||
2835 (math_unary->recognized_kind() == MethodRecognizer::kMathCos)) {
2836 if (math_unary->HasUses()) {
2837 sin_cos_merge.Add(math_unary);
2838 }
2839 }
2840 }
2841 }
2842 TryMergeTruncDivMod(&div_mod_merge);
2843 }
2844}

◆ unmatched_representations_allowed()

bool dart::FlowGraph::unmatched_representations_allowed ( ) const
inline

Definition at line 411 of file flow_graph.h.

411 {
412 return unmatched_representations_allowed_;
413 }

◆ variable_count()

intptr_t dart::FlowGraph::variable_count ( ) const
inline

Definition at line 143 of file flow_graph.h.

143 {
144 return num_direct_parameters_ + parsed_function_.num_stack_locals();
145 }

◆ VerifyRedefinitions()

bool dart::FlowGraph::VerifyRedefinitions ( )

Definition at line 655 of file flow_graph.cc.

655 {
656 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
657 block_it.Advance()) {
658 for (ForwardInstructionIterator instr_it(block_it.Current());
659 !instr_it.Done(); instr_it.Advance()) {
660 RedefinitionInstr* redefinition = instr_it.Current()->AsRedefinition();
661 if (redefinition != nullptr) {
662 Definition* original = redefinition->value()->definition();
663 for (Value::Iterator it(original->input_use_list()); !it.Done();
664 it.Advance()) {
665 Value* original_use = it.Current();
666 if (original_use->instruction() == redefinition) {
667 continue;
668 }
669 if (original_use->instruction()->IsDominatedBy(redefinition)) {
670 FlowGraphPrinter::PrintGraph("VerifyRedefinitions", this);
671 THR_Print("%s\n", redefinition->ToCString());
672 THR_Print("use=%s\n", original_use->instruction()->ToCString());
673 return false;
674 }
675 }
676 }
677 }
678 }
679 return true;
680}

◆ WidenSmiToInt32()

void dart::FlowGraph::WidenSmiToInt32 ( )

Definition at line 2575 of file flow_graph.cc.

2575 {
2576 // TODO(vegorov) ideally on 64-bit platforms we would like to narrow smi
2577 // operations to 32-bit where it saves tagging and untagging and allows
2578 // to use shorted (and faster) instructions. But we currently don't
2579 // save enough range information in the ICData to drive this decision.
2580}

◆ zone()

Zone * dart::FlowGraph::zone ( ) const
inline

Definition at line 261 of file flow_graph.h.

261{ return thread()->zone(); }

Friends And Related Symbol Documentation

◆ BranchSimplifier

friend class BranchSimplifier
friend

Definition at line 608 of file flow_graph.h.

◆ compiler::GraphIntrinsifier

friend class compiler::GraphIntrinsifier
friend

Definition at line 611 of file flow_graph.h.

◆ ConstantPropagator

friend class ConstantPropagator
friend

Definition at line 609 of file flow_graph.h.

◆ DeadCodeElimination

friend class DeadCodeElimination
friend

Definition at line 610 of file flow_graph.h.

◆ FlowGraphChecker

friend class FlowGraphChecker
friend

Definition at line 606 of file flow_graph.h.

◆ FlowGraphCompiler

friend class FlowGraphCompiler
friend

Definition at line 605 of file flow_graph.h.

◆ IfConverter

friend class IfConverter
friend

Definition at line 607 of file flow_graph.h.


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