Flutter Engine
The Flutter Engine
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 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.

116 {
117 kUnoptimized,
118 kOptimized,
119 kIntrinsic,
120 };

◆ ToCheck

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

Definition at line 252 of file flow_graph.h.

252{ kNoCheck, kCheckNull, kCheckCid };

◆ 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 46 of file flow_graph.cc.

51 : thread_(Thread::Current()),
52 parent_(),
53 current_ssa_temp_index_(0),
54 max_block_id_(max_block_id),
55 parsed_function_(parsed_function),
56 num_direct_parameters_(parsed_function.function().MakesCopyOfParameters()
57 ? 0
59 direct_parameter_locations_(
61 graph_entry_(graph_entry),
62 preorder_(),
63 postorder_(),
64 reverse_postorder_(),
65 optimized_block_order_(),
66 constant_null_(nullptr),
67 constant_dead_(nullptr),
68 licm_allowed_(true),
69 should_reorder_blocks_(
70 ShouldReorderBlocks(parsed_function.function(), compilation_mode)),
71 prologue_info_(prologue_info),
72 loop_hierarchy_(nullptr),
73 loop_invariant_loads_(nullptr),
74 captured_parameters_(new(zone()) BitVector(zone(), variable_count())),
75 inlining_id_(-1),
76 should_print_(false),
77 should_remove_all_bounds_checks_(
78 CompilerState::Current().is_aot() &&
81 &compiler_pass_filters_);
83 zone(), function(),
84 /*should_assign_stack_locations=*/
86 &direct_parameter_locations_);
88}
static CompilerState & Current()
static bool ShouldPrint(const Function &function, uint8_t **compiler_pass_filter=nullptr)
Definition: il_printer.cc:1715
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()
Definition: flow_graph.cc:346
static intptr_t ComputeLocationsOfFixedParameters(Zone *zone, const Function &function, bool should_assign_stack_locations=false, compiler::ParameterInfoArray *parameter_info=nullptr)
Definition: flow_graph.cc:1204
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:3514
intptr_t num_fixed_parameters() const
Definition: object.cc:8856
intptr_t NumParameters() const
Definition: object.cc:8877
const Function & function() const
Definition: parser.h:73
static Thread * Current()
Definition: thread.h:362
static bool ShouldReorderBlocks(const Function &function, FlowGraph::CompilationMode mode)
Definition: flow_graph.cc:32
static bool IsMarkedWithNoBoundsChecks(const Function &function)
Definition: flow_graph.cc:38

Member Function Documentation

◆ AddExactnessGuard()

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

Definition at line 627 of file flow_graph.cc.

628 {
629 const Class& cls =
630 Class::Handle(zone(), isolate_group()->class_table()->At(receiver_cid));
631
632 Definition* load_type_args = new (zone()) LoadFieldInstr(
633 call->Receiver()->CopyWithType(),
634 Slot::GetTypeArgumentsSlotFor(thread(), cls), call->source());
635 InsertBefore(call, load_type_args, call->env(), FlowGraph::kValue);
636
637 const AbstractType& type =
638 AbstractType::Handle(zone(), call->ic_data()->receivers_static_type());
639 ASSERT(!type.IsNull());
640 const TypeArguments& args = TypeArguments::Handle(
641 zone(), Type::Cast(type).GetInstanceTypeArguments(thread()));
642 Instruction* guard = new (zone()) CheckConditionInstr(
643 new StrictCompareInstr(call->source(), Token::kEQ_STRICT,
644 new (zone()) Value(load_type_args),
645 new (zone()) Value(GetConstant(args)),
646 /*needs_number_check=*/false, call->deopt_id()),
647 call->deopt_id());
648 InsertBefore(call, guard, call->env(), FlowGraph::kEffect);
649}
GLenum type
ConstantInstr * GetConstant(const Object &object, Representation representation=kTagged)
Definition: flow_graph.cc:187
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
def call(args)
Definition: dom.py:159

◆ AddPhi()

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

Definition at line 2927 of file flow_graph.cc.

2929 {
2930 PhiInstr* phi = new (zone()) PhiInstr(join, 2);
2931 Value* v1 = new (zone()) Value(d1);
2932 Value* v2 = new (zone()) Value(d2);
2933
2934 AllocateSSAIndex(phi);
2935
2936 phi->mark_alive();
2937 phi->SetInputAt(0, v1);
2938 phi->SetInputAt(1, v2);
2939 d1->AddInputUse(v1);
2940 d2->AddInputUse(v2);
2941 join->InsertPhi(phi);
2942
2943 return phi;
2944}
Vec2Value v2
void AllocateSSAIndex(Definition *def)
Definition: flow_graph.h:274
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741

◆ AddToGraphInitialDefinitions()

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

Definition at line 258 of file flow_graph.cc.

258 {
259 defn->set_previous(graph_entry_);
260 graph_entry_->initial_definitions()->Add(defn);
261}
GrowableArray< Definition * > * initial_definitions()
Definition: il.h:1917

◆ AddToInitialDefinitions()

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

Definition at line 263 of file flow_graph.cc.

264 {
265 ASSERT(defn->previous() == nullptr);
266 defn->set_previous(entry);
267 if (auto par = defn->AsParameter()) {
268 par->set_block(entry); // set cached block
269 }
270 entry->initial_definitions()->Add(defn);
271}

◆ 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 312 of file flow_graph.cc.

315 {
316 auto result = AppendTo(prev, instr, env, use_kind);
317 if (instr->env() != nullptr) {
318 instr->env()->MarkAsLazyDeoptToBeforeDeoptId();
319 }
320 return result;
321}
static float prev(float f)
Instruction * AppendTo(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
Definition: flow_graph.cc:298
GAsyncResult * result
Definition: __init__.py:1

◆ AppendTo()

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

Definition at line 298 of file flow_graph.cc.

301 {
302 if (use_kind == kValue) {
303 ASSERT(instr->IsDefinition());
304 AllocateSSAIndex(instr->AsDefinition());
305 }
306 ASSERT(instr->env() == nullptr);
307 if (env != nullptr) {
308 env->DeepCopyTo(zone(), instr);
309 }
310 return prev->AppendInstruction(instr);
311}

◆ 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 2466 of file flow_graph.cc.

2466 {
2467 bool changed = false;
2468
2469 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2470 block_it.Advance()) {
2471 BlockEntryInstr* const block = block_it.Current();
2472 if (auto join = block->AsJoinEntry()) {
2473 for (PhiIterator it(join); !it.Done(); it.Advance()) {
2474 PhiInstr* current = it.Current();
2475 if (current->HasUnmatchedInputRepresentations() &&
2476 (current->SpeculativeModeOfInputs() == Instruction::kGuardInputs)) {
2477 // Can't canonicalize this instruction until all conversions for its
2478 // speculative inputs are inserted.
2479 continue;
2480 }
2481
2482 Definition* replacement = current->Canonicalize(this);
2483 ASSERT(replacement != nullptr);
2485 !replacement->HasUnmatchedInputRepresentations());
2486 if (replacement != current) {
2487 current->ReplaceUsesWith(replacement);
2488 it.RemoveCurrentFromGraph();
2489 changed = true;
2490 }
2491 }
2492 }
2493 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2494 Instruction* current = it.Current();
2495 if (current->HasUnmatchedInputRepresentations() &&
2496 (current->SpeculativeModeOfInputs() == Instruction::kGuardInputs)) {
2497 // Can't canonicalize this instruction until all conversions for its
2498 // speculative inputs are inserted.
2499 continue;
2500 }
2501
2502 Instruction* replacement = current->Canonicalize(this);
2503
2504 if (replacement != current) {
2505 // For non-definitions Canonicalize should return either nullptr or
2506 // this.
2507 if (replacement != nullptr) {
2508 ASSERT(current->IsDefinition());
2510 RELEASE_ASSERT(!replacement->HasUnmatchedInputRepresentations());
2511 if ((replacement->representation() != current->representation()) &&
2512 current->AsDefinition()->HasUses()) {
2513 // Can't canonicalize this instruction as unmatched
2514 // representations are not allowed at this point, but
2515 // replacement has a different representation.
2516 continue;
2517 }
2518 }
2519 }
2520 ReplaceCurrentInstruction(&it, current, replacement);
2521 changed = true;
2522 }
2523 }
2524 }
2525 return changed;
2526}
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
bool Done() const
Definition: flow_graph.h:46
void ReplaceCurrentInstruction(ForwardInstructionIterator *iterator, Instruction *current, Instruction *replacement)
Definition: flow_graph.cc:141
bool unmatched_representations_allowed() const
Definition: flow_graph.h:411
BlockIterator reverse_postorder_iterator() const
Definition: flow_graph.h:219
@ kGuardInputs
Definition: il.h:972

◆ 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 493 of file flow_graph.cc.

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

◆ CodegenBlockOrder() [1/2]

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

Definition at line 170 of file flow_graph.cc.

170 {
171 return should_reorder_blocks() ? &optimized_block_order_
172 : &reverse_postorder_;
173}
bool should_reorder_blocks() const
Definition: flow_graph.h:508

◆ CodegenBlockOrder() [2/2]

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

Definition at line 175 of file flow_graph.cc.

175 {
176 return should_reorder_blocks() ? &optimized_block_order_
177 : &reverse_postorder_;
178}

◆ CompactSSA()

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

Definition at line 3123 of file flow_graph.cc.

3123 {
3124 if (detached_defs == nullptr) {
3125 detached_defs = new (Z) ZoneGrowableArray<Definition*>(Z, 0);
3126 }
3127 SSACompactor compactor(max_block_id() + 1, current_ssa_temp_index(),
3128 detached_defs);
3129 compactor.RenumberGraph(this);
3130}
intptr_t current_ssa_temp_index() const
Definition: flow_graph.h:243
#define Z
Definition: flow_graph.cc:30

◆ CompilationModeFrom()

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

◆ compiler_pass_filters()

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

Definition at line 504 of file flow_graph.h.

504 {
505 return compiler_pass_filters_;
506 }

◆ ComputeArgumentsSizeInWords()

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

Definition at line 96 of file flow_graph.cc.

97 {
100
101 const intptr_t fixed_parameters_size_in_bytes =
103
104 // Currently we box all optional parameters.
105 return fixed_parameters_size_in_bytes +
107}
int argument_count
Definition: fuchsia.cc:52

◆ ComputeDominators()

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

Definition at line 975 of file flow_graph.cc.

976 {
977 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass
978 // version of the Lengauer-Tarjan algorithm (LT is normally three passes)
979 // that eliminates a pass by using nearest-common ancestor (NCA) to
980 // compute immediate dominators from semidominators. It also removes a
981 // level of indirection in the link-eval forest data structure.
982 //
983 // The algorithm is described in Georgiadis, Tarjan, and Werneck's
984 // "Finding Dominators in Practice".
985 // https://renatowerneck.files.wordpress.com/2016/06/gtw06-dominators.pdf
986
987 // All arrays are maps between preorder basic-block numbers.
988 intptr_t size = parent_.length();
989 GrowableArray<intptr_t> idom(size); // Immediate dominator.
990 GrowableArray<intptr_t> semi(size); // Semidominator.
991 GrowableArray<intptr_t> label(size); // Label for link-eval forest.
992
993 // 1. First pass: compute semidominators as in Lengauer-Tarjan.
994 // Semidominators are computed from a depth-first spanning tree and are an
995 // approximation of immediate dominators.
996
997 // Use a link-eval data structure with path compression. Implement path
998 // compression in place by mutating the parent array. Each block has a
999 // label, which is the minimum block number on the compressed path.
1000
1001 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the
1002 // dominance frontier output array.
1003 for (intptr_t i = 0; i < size; ++i) {
1004 idom.Add(parent_[i]);
1005 semi.Add(i);
1006 label.Add(i);
1007 dominance_frontier->Add(new (zone()) BitVector(zone(), size));
1008 }
1009
1010 // Loop over the blocks in reverse preorder (not including the graph
1011 // entry). Clear the dominated blocks in the graph entry in case
1012 // ComputeDominators is used to recompute them.
1013 preorder_[0]->ClearDominatedBlocks();
1014 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
1015 // Loop over the predecessors.
1016 BlockEntryInstr* block = preorder_[block_index];
1017 // Clear the immediately dominated blocks in case ComputeDominators is
1018 // used to recompute them.
1019 block->ClearDominatedBlocks();
1020 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) {
1021 BlockEntryInstr* pred = block->PredecessorAt(i);
1022 ASSERT(pred != nullptr);
1023
1024 // Look for the semidominator by ascending the semidominator path
1025 // starting from pred.
1026 intptr_t pred_index = pred->preorder_number();
1027 intptr_t best = pred_index;
1028 if (pred_index > block_index) {
1029 CompressPath(block_index, pred_index, &parent_, &label);
1030 best = label[pred_index];
1031 }
1032
1033 // Update the semidominator if we've found a better one.
1034 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]);
1035 }
1036
1037 // Now use label for the semidominator.
1038 label[block_index] = semi[block_index];
1039 }
1040
1041 // 2. Compute the immediate dominators as the nearest common ancestor of
1042 // spanning tree parent and semidominator, for all blocks except the entry.
1043 for (intptr_t block_index = 1; block_index < size; ++block_index) {
1044 intptr_t dom_index = idom[block_index];
1045 while (dom_index > semi[block_index]) {
1046 dom_index = idom[dom_index];
1047 }
1048 idom[block_index] = dom_index;
1049 preorder_[dom_index]->AddDominatedBlock(preorder_[block_index]);
1050 }
1051
1052 // 3. Now compute the dominance frontier for all blocks. This is
1053 // algorithm in "A Simple, Fast Dominance Algorithm" (Figure 5), which is
1054 // attributed to a paper by Ferrante et al. There is no bookkeeping
1055 // required to avoid adding a block twice to the same block's dominance
1056 // frontier because we use a set to represent the dominance frontier.
1057 for (intptr_t block_index = 0; block_index < size; ++block_index) {
1058 BlockEntryInstr* block = preorder_[block_index];
1059 intptr_t count = block->PredecessorCount();
1060 if (count <= 1) continue;
1061 for (intptr_t i = 0; i < count; ++i) {
1062 BlockEntryInstr* runner = block->PredecessorAt(i);
1063 while (runner != block->dominator()) {
1064 (*dominance_frontier)[runner->preorder_number()]->Add(block_index);
1065 runner = runner->dominator();
1066 }
1067 }
1068 }
1069}
int count
Definition: FontMgrTest.cpp:50
intptr_t length() const
static T Minimum(T x, T y)
Definition: utils.h:36
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 1204 of file flow_graph.cc.

1208 {
1211 [&](intptr_t i) {
1212 const intptr_t index = (function.IsFactory() ? (i - 1) : i);
1213 return index >= 0 ? ParameterRepresentationAt(function, index)
1214 : kTagged;
1215 },
1216 should_assign_stack_locations, parameter_info);
1217}
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 926 of file flow_graph.cc.

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

◆ 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 550 of file flow_graph.h.

550{ return *coverage_array_; }

◆ CreateCheckBound()

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

Definition at line 616 of file flow_graph.cc.

618 {
619 Value* val1 = new (zone()) Value(length);
620 Value* val2 = new (zone()) Value(index);
622 return new (zone()) GenericCheckBoundInstr(val1, val2, deopt_id);
623 }
624 return new (zone()) CheckArrayBoundInstr(val1, val2, deopt_id);
625}
bool is_aot() const
size_t length

◆ CreateCheckClass()

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

Definition at line 604 of file flow_graph.cc.

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

◆ CreateCommonConstants()

void dart::FlowGraph::CreateCommonConstants ( )

Definition at line 1143 of file flow_graph.cc.

1143 {
1144 constant_null_ = GetConstant(Object::ZoneHandle());
1145 constant_dead_ = GetConstant(Object::optimized_out());
1146}
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 346 of file flow_graph.cc.

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

2351 {
2352 // After this pass we can no longer perform LICM and hoist instructions
2353 // that can deoptimize.
2354
2355 disallow_licm();
2356 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2357 block_it.Advance()) {
2358 BlockEntryInstr* block = block_it.Current();
2359 if (!block->IsCatchBlockEntry()) {
2360 block->RemoveEnvironment();
2361 }
2362 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2363 Instruction* current = it.Current();
2364 // This check is inconsistent with the flow graph checker. The flow graph
2365 // checker does not allow for not having an env if the block is not
2366 // inside a try-catch.
2367 // See FlowGraphChecker::VisitInstruction.
2368 if (!current->ComputeCanDeoptimize() &&
2369 !current->ComputeCanDeoptimizeAfterCall() &&
2370 (!current->MayThrow() || !current->GetBlock()->InsideTryBlock())) {
2371 // Instructions that can throw need an environment for optimized
2372 // try-catch.
2373 // TODO(srdjan): --source-lines needs deopt environments to get at
2374 // the code for this instruction, however, leaving the environment
2375 // changes code.
2376 current->RemoveEnvironment();
2377 }
2378 }
2379 }
2380}
void disallow_licm()
Definition: flow_graph.h:408

◆ EnsureRedefinition()

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

Definition at line 1777 of file flow_graph.cc.

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

◆ EnsureSSATempIndex()

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

Definition at line 90 of file flow_graph.cc.

90 {
91 if ((replacement->ssa_temp_index() == -1) && (defn->ssa_temp_index() != -1)) {
92 AllocateSSAIndex(replacement);
93 }
94}

◆ 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 2393 of file flow_graph.cc.

2395 {
2396 ASSERT(array->instruction() == instr);
2397 // Nothing to do if already untagged.
2398 if (array->definition()->representation() != kTagged) return false;
2399 // If we've determined at compile time that this is an object that has an
2400 // external payload, use the cid of the compile type instead.
2401 if (IsExternalPayloadClassId(array->Type()->ToCid())) {
2402 cid = array->Type()->ToCid();
2403 } else if (!IsExternalPayloadClassId(cid)) {
2404 // Can't extract the payload address if it points to GC-managed memory.
2405 return false;
2406 }
2407
2408 const Slot* slot = nullptr;
2409 if (cid == kPointerCid || IsExternalTypedDataClassId(cid)) {
2410 slot = &Slot::PointerBase_data();
2411 } else {
2412 UNREACHABLE();
2413 }
2414
2415 ExtractUntaggedPayload(instr, array, *slot,
2417 return true;
2418}
#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 2444 of file flow_graph.cc.

2444 {
2445 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2446 block_it.Advance()) {
2447 BlockEntryInstr* block = block_it.Current();
2448 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2449 Instruction* current = it.Current();
2450 if (auto* const load_indexed = current->AsLoadIndexed()) {
2451 ExtractNonInternalTypedDataPayload(load_indexed, load_indexed->array(),
2452 load_indexed->class_id());
2453 } else if (auto* const store_indexed = current->AsStoreIndexed()) {
2454 ExtractNonInternalTypedDataPayload(
2455 store_indexed, store_indexed->array(), store_indexed->class_id());
2456 } else if (auto* const memory_copy = current->AsMemoryCopy()) {
2457 ExtractNonInternalTypedDataPayload(memory_copy, memory_copy->src(),
2458 memory_copy->src_cid());
2459 ExtractNonInternalTypedDataPayload(memory_copy, memory_copy->dest(),
2460 memory_copy->dest_cid());
2461 }
2462 }
2463 }
2464}

◆ 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 187 of file flow_graph.cc.

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

◆ GetDirectParameterInfoAt()

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

Definition at line 571 of file flow_graph.h.

572 {
573 return direct_parameter_locations_[i];
574 }

◆ GetExistingConstant()

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

Definition at line 180 of file flow_graph.cc.

182 {
183 return constant_instr_pool_.LookupValue(
184 ConstantAndRepresentation{object, representation});
185}

◆ 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 273 of file flow_graph.cc.

276 {
277 if (use_kind == kValue) {
278 ASSERT(instr->IsDefinition());
279 AllocateSSAIndex(instr->AsDefinition());
280 }
281 instr->InsertAfter(prev);
282 ASSERT(instr->env() == nullptr);
283 if (env != nullptr) {
284 env->DeepCopyTo(zone(), instr);
285 }
286}

◆ 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 2946 of file flow_graph.cc.

2946 {
2947 compiler::ParameterInfoArray argument_locations;
2948
2949 intptr_t max_argument_slot_count = 0;
2950 auto& target = Function::Handle();
2951
2952 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2953 block_it.Advance()) {
2955 for (ForwardInstructionIterator instr_it(block_it.Current());
2956 !instr_it.Done(); instr_it.Advance()) {
2957 Instruction* instruction = instr_it.Current();
2958 const intptr_t arg_count = instruction->ArgumentCount();
2959 if (arg_count == 0) {
2960 continue;
2961 }
2962
2964 if (auto static_call = instruction->AsStaticCall()) {
2965 target = static_call->function().ptr();
2966 } else if (auto instance_call = instruction->AsInstanceCallBase()) {
2967 target = instance_call->interface_target().ptr();
2968 } else if (auto dispatch_call = instruction->AsDispatchTableCall()) {
2969 target = dispatch_call->interface_target().ptr();
2970 } else if (auto cachable_call = instruction->AsCachableIdempotentCall()) {
2971 target = cachable_call->function().ptr();
2972 }
2973
2974 MoveArgumentsArray* arguments =
2975 new (Z) MoveArgumentsArray(zone(), arg_count);
2976 arguments->EnsureLength(arg_count, nullptr);
2977
2978 const intptr_t stack_arguments_size_in_words =
2980 zone(), target, arg_count,
2981 [&](intptr_t i) {
2982 return instruction->RequiredInputRepresentation(i);
2983 },
2984 /*should_assign_stack_locations=*/true, &argument_locations);
2985
2986 for (intptr_t i = 0; i < arg_count; ++i) {
2987 const auto& [location, rep] = argument_locations[i];
2988 Value* arg = instruction->ArgumentValueAt(i);
2989 (*arguments)[i] = new (Z) MoveArgumentInstr(
2990 arg->CopyWithType(Z), rep, location.ToCallerSpRelative());
2991 }
2993 stack_arguments_size_in_words);
2994
2995 for (auto move_arg : *arguments) {
2996 // Insert all MoveArgument instructions immediately before call.
2997 // MoveArgumentInstr::EmitNativeCode may generate more efficient
2998 // code for subsequent MoveArgument instructions (ARM, ARM64).
2999 if (!move_arg->is_register_move()) {
3000 InsertBefore(instruction, move_arg, /*env=*/nullptr, kEffect);
3001 }
3002 }
3003 instruction->ReplaceInputsWithMoveArguments(arguments);
3004 if (instruction->env() != nullptr) {
3005 instruction->RepairArgumentUsesInEnvironment();
3006 }
3007 }
3008 }
3010}
intptr_t max_argument_slot_count() const
Definition: flow_graph.h:562
void set_max_argument_slot_count(intptr_t count)
Definition: flow_graph.h:566
void CheckForSafepoint()
Definition: thread.h:1104
static constexpr T Maximum(T x, T y)
Definition: utils.h:41
GrowableArray< std::pair< Location, Representation > > ParameterInfoArray
ZoneGrowableArray< MoveArgumentInstr * > MoveArgumentsArray
Definition: il.h:902

◆ InsertSpeculativeAfter()

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

Definition at line 288 of file flow_graph.cc.

291 {
292 InsertAfter(prev, instr, env, use_kind);
293 if (instr->env() != nullptr) {
294 instr->env()->MarkAsLazyDeoptToBeforeDeoptId();
295 }
296}

◆ 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)
Definition: flow_graph.cc:288

◆ InstructionCount()

intptr_t dart::FlowGraph::InstructionCount ( ) const

Definition at line 1896 of file flow_graph.cc.

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

◆ IsConstantRepresentable()

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

Definition at line 205 of file flow_graph.cc.

207 {
208 switch (target_rep) {
209 case kTagged:
210 return !tagged_value_must_be_smi || value.IsSmi();
211
212 case kUnboxedInt32:
213 if (value.IsInteger()) {
214 return Utils::IsInt(32, Integer::Cast(value).AsInt64Value());
215 }
216 return false;
217
218 case kUnboxedUint32:
219 if (value.IsInteger()) {
220 return Utils::IsUint(32, Integer::Cast(value).AsInt64Value());
221 }
222 return false;
223
224 case kUnboxedInt64:
225 return value.IsInteger();
226
227 case kUnboxedFloat:
228 case kUnboxedDouble:
229 return value.IsInteger() || value.IsDouble();
230
231 default:
232 return false;
233 }
234}
static bool IsInt(intptr_t N, T value)
Definition: utils.h:313
static bool IsUint(intptr_t N, T value)
Definition: utils.h:328
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:3898

◆ 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:541

◆ IsReceiver()

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

Definition at line 478 of file flow_graph.cc.

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

◆ 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 562 of file flow_graph.h.

562 {
563 RELEASE_ASSERT(max_argument_slot_count_ >= 0);
564 return max_argument_slot_count_;
565 }

◆ 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 389 of file flow_graph.cc.

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

2862 {
2863 BlockEntryInstr* entry = instruction->GetBlock();
2864
2865 TargetEntryInstr* bt = NewTarget(this, inherit);
2866 TargetEntryInstr* bf = NewTarget(this, inherit);
2867 JoinEntryInstr* join = NewJoin(this, inherit);
2868 GotoInstr* gotot = NewGoto(this, join, inherit);
2869 GotoInstr* gotof = NewGoto(this, join, inherit);
2870 BranchInstr* bra = NewBranch(this, compare, inherit);
2871
2872 instruction->AppendInstruction(bra);
2873 entry->set_last_instruction(bra);
2874
2875 *bra->true_successor_address() = bt;
2876 *bra->false_successor_address() = bf;
2877
2878 bt->AppendInstruction(gotot);
2879 bt->set_last_instruction(gotot);
2880
2881 bf->AppendInstruction(gotof);
2882 bf->set_last_instruction(gotof);
2883
2884 // Update dominance relation incrementally.
2885 for (intptr_t i = 0, n = entry->dominated_blocks().length(); i < n; ++i) {
2886 join->AddDominatedBlock(entry->dominated_blocks()[i]);
2887 }
2888 entry->ClearDominatedBlocks();
2889 entry->AddDominatedBlock(bt);
2890 entry->AddDominatedBlock(bf);
2891 entry->AddDominatedBlock(join);
2892
2893 // TODO(ajcbik): update pred/succ/ordering incrementally too.
2894
2895 // Return new blocks.
2896 *b_true = bt;
2897 *b_false = bf;
2898 return join;
2899}
static JoinEntryInstr * NewJoin(FlowGraph *graph, Instruction *inherit)
Definition: flow_graph.cc:2820
static GotoInstr * NewGoto(FlowGraph *graph, JoinEntryInstr *target, Instruction *inherit)
Definition: flow_graph.cc:2828
static BranchInstr * NewBranch(FlowGraph *graph, ComparisonInstr *cmp, Instruction *inherit)
Definition: flow_graph.cc:2836
static TargetEntryInstr * NewTarget(FlowGraph *graph, Instruction *inherit)
Definition: flow_graph.cc:2812
int compare(const void *untyped_lhs, const void *untyped_rhs)
Definition: skdiff.h:161

◆ NewDiamond() [2/2]

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

Definition at line 2901 of file flow_graph.cc.

2905 {
2906 // First diamond for first comparison.
2907 TargetEntryInstr* bt = nullptr;
2908 TargetEntryInstr* bf = nullptr;
2909 JoinEntryInstr* mid_point =
2910 NewDiamond(instruction, inherit, condition.oper1, &bt, &bf);
2911
2912 // Short-circuit second comparison and connect through phi.
2913 condition.oper2->InsertAfter(bt);
2914 AllocateSSAIndex(condition.oper2);
2915 condition.oper2->InheritDeoptTarget(zone(), inherit); // must inherit
2916 PhiInstr* phi =
2917 AddPhi(mid_point, condition.oper2, GetConstant(Bool::False()));
2918 StrictCompareInstr* circuit = new (zone()) StrictCompareInstr(
2919 inherit->source(), Token::kEQ_STRICT, new (zone()) Value(phi),
2920 new (zone()) Value(GetConstant(Bool::True())), false,
2921 DeoptId::kNone); // don't inherit
2922
2923 // Return new blocks through the second diamond.
2924 return NewDiamond(mid_point, inherit, circuit, b_true, b_false);
2925}
static const Bool & False()
Definition: object.h:10799
static const Bool & True()
Definition: object.h:10797
static constexpr intptr_t kNone
Definition: deopt_id.h:27
JoinEntryInstr * NewDiamond(Instruction *instruction, Instruction *inherit, ComparisonInstr *compare, TargetEntryInstr **block_true, TargetEntryInstr **block_false)
Definition: flow_graph.cc:2858
PhiInstr * AddPhi(JoinEntryInstr *join, Definition *d1, Definition *d2)
Definition: flow_graph.cc:2927

◆ 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:1756
bool IsCompiledForOsr() const
Definition: flow_graph.h:460
OsrEntryInstr * osr_entry() const
Definition: il.h:2007

◆ ParameterRepresentationAt()

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

Definition at line 109 of file flow_graph.cc.

110 {
111 if (function.IsNull()) {
112 return kTagged;
113 }
114 ASSERT(index < function.NumParameters());
116 return kUnboxedInt64;
117 } else if (function.is_unboxed_double_parameter_at(index)) {
118 return kUnboxedDouble;
119 } else {
121 return kTagged;
122 }
123}
bool is_unboxed_integer_parameter_at(intptr_t index) const
Definition: object.h:3783
bool is_unboxed_parameter_at(intptr_t index) const
Definition: object.h:3773
bool is_unboxed_double_parameter_at(intptr_t index) const
Definition: object.h:3793
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 2528 of file flow_graph.cc.

2528 {
2529 Zone* zone = Thread::Current()->zone();
2530
2531 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2532 block_it.Advance()) {
2533 ForwardInstructionIterator it(block_it.Current());
2534 for (; !it.Done(); it.Advance()) {
2535 Instruction* instr = it.Current();
2536 if (instr->IsInstanceCall()) {
2537 InstanceCallInstr* call = instr->AsInstanceCall();
2538 if (!call->HasICData()) {
2539 const Array& arguments_descriptor =
2540 Array::Handle(zone, call->GetArgumentsDescriptor());
2541 const ICData& ic_data = ICData::ZoneHandle(
2542 zone,
2543 ICData::New(function, call->function_name(), arguments_descriptor,
2544 call->deopt_id(), call->checked_argument_count(),
2545 ICData::kInstance));
2546 call->set_ic_data(&ic_data);
2547 }
2548 } else if (instr->IsStaticCall()) {
2549 StaticCallInstr* call = instr->AsStaticCall();
2550 if (!call->HasICData()) {
2551 const Array& arguments_descriptor =
2552 Array::Handle(zone, call->GetArgumentsDescriptor());
2553 const Function& target = call->function();
2554 int num_args_checked =
2556 const ICData& ic_data = ICData::ZoneHandle(
2558 function, target, arguments_descriptor,
2559 call->deopt_id(), num_args_checked, ICData::kStatic));
2560 call->set_ic_data(&ic_data);
2561 }
2562 }
2563 }
2564 }
2565}
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:17401
static intptr_t NumArgsCheckedForStaticCall(const Function &function)
Zone * zone() const
Definition: thread_state.h:37

◆ 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 3012 of file flow_graph.cc.

3012 {
3013 FlowGraphPrinter::PrintGraph(phase, this);
3014}
static void PrintGraph(const char *phase, FlowGraph *flow_graph)
Definition: il_printer.cc:1706

◆ 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 1810 of file flow_graph.cc.

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

◆ RenameDominatedUses()

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

Definition at line 2642 of file flow_graph.cc.

2644 {
2645 for (Value::Iterator it(def->input_use_list()); !it.Done(); it.Advance()) {
2646 Value* use = it.Current();
2647 if (IsDominatedUse(dom, use)) {
2648 use->BindTo(other);
2649 }
2650 }
2651}
static bool IsDominatedUse(Instruction *dom, Value *use)
Definition: flow_graph.cc:2616
Definition: dom.py:1

◆ RenameUsesDominatedByRedefinitions()

void dart::FlowGraph::RenameUsesDominatedByRedefinitions ( )

Definition at line 2653 of file flow_graph.cc.

2653 {
2654 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2655 block_it.Advance()) {
2656 for (ForwardInstructionIterator instr_it(block_it.Current());
2657 !instr_it.Done(); instr_it.Advance()) {
2658 Definition* definition = instr_it.Current()->AsDefinition();
2659 // CheckArrayBound instructions have their own mechanism for ensuring
2660 // proper dependencies, so we don't rewrite those here.
2661 if (definition != nullptr && !definition->IsCheckArrayBound()) {
2662 Value* redefined = definition->RedefinedValue();
2663 if (redefined != nullptr) {
2664 if (!definition->HasSSATemp()) {
2665 AllocateSSAIndex(definition);
2666 }
2667 Definition* original = redefined->definition();
2668 RenameDominatedUses(original, definition, definition);
2669 }
2670 }
2671 }
2672 }
2673}

◆ ReplaceCurrentInstruction()

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

Definition at line 141 of file flow_graph.cc.

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

◆ 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 125 of file flow_graph.cc.

125 {
126 if (function.IsNull()) {
127 return kTagged;
128 }
130 return kUnboxedInt64;
131 } else if (function.has_unboxed_double_return()) {
132 return kUnboxedDouble;
133 } else if (function.has_unboxed_record_return()) {
134 return kPairOfTagged;
135 } else {
137 return kTagged;
138 }
139}
bool has_unboxed_return() const
Definition: object.h:3803
bool has_unboxed_double_return() const
Definition: object.h:3819
bool has_unboxed_integer_return() const
Definition: object.h:3811
bool has_unboxed_record_return() const
Definition: object.h:3827

◆ 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 2298 of file flow_graph.cc.

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

◆ set_coverage_array()

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

Definition at line 551 of file flow_graph.h.

551{ 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 566 of file flow_graph.h.

566 {
567 RELEASE_ASSERT(max_argument_slot_count_ == -1);
568 max_argument_slot_count_ = count;
569 }

◆ 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 503 of file flow_graph.h.

503{ return should_print_; }

◆ should_remove_all_bounds_checks()

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

Definition at line 510 of file flow_graph.h.

510 {
511 return should_remove_all_bounds_checks_;
512 }

◆ should_reorder_blocks()

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

Definition at line 508 of file flow_graph.h.

508{ 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 236 of file flow_graph.cc.

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

◆ TryOptimizePatterns()

void dart::FlowGraph::TryOptimizePatterns ( )

Definition at line 2570 of file flow_graph.cc.

2570 {
2571 if (!FLAG_truncating_left_shift) return;
2572 GrowableArray<BinarySmiOpInstr*> div_mod_merge;
2573 GrowableArray<InvokeMathCFunctionInstr*> sin_cos_merge;
2574 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2575 block_it.Advance()) {
2576 // Merging only per basic-block.
2577 div_mod_merge.Clear();
2578 sin_cos_merge.Clear();
2579 ForwardInstructionIterator it(block_it.Current());
2580 for (; !it.Done(); it.Advance()) {
2581 if (it.Current()->IsBinarySmiOp()) {
2582 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp();
2583 if (binop->op_kind() == Token::kBIT_AND) {
2584 OptimizeLeftShiftBitAndSmiOp(&it, binop, binop->left()->definition(),
2585 binop->right()->definition());
2586 } else if ((binop->op_kind() == Token::kTRUNCDIV) ||
2587 (binop->op_kind() == Token::kMOD)) {
2588 if (binop->HasUses()) {
2589 div_mod_merge.Add(binop);
2590 }
2591 }
2592 } else if (it.Current()->IsBinaryInt64Op()) {
2593 BinaryInt64OpInstr* mintop = it.Current()->AsBinaryInt64Op();
2594 if (mintop->op_kind() == Token::kBIT_AND) {
2595 OptimizeLeftShiftBitAndSmiOp(&it, mintop,
2596 mintop->left()->definition(),
2597 mintop->right()->definition());
2598 }
2599 } else if (it.Current()->IsInvokeMathCFunction()) {
2600 InvokeMathCFunctionInstr* math_unary =
2601 it.Current()->AsInvokeMathCFunction();
2602 if ((math_unary->recognized_kind() == MethodRecognizer::kMathSin) ||
2603 (math_unary->recognized_kind() == MethodRecognizer::kMathCos)) {
2604 if (math_unary->HasUses()) {
2605 sin_cos_merge.Add(math_unary);
2606 }
2607 }
2608 }
2609 }
2610 TryMergeTruncDivMod(&div_mod_merge);
2611 }
2612}

◆ 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 652 of file flow_graph.cc.

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

◆ zone()

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

Definition at line 261 of file flow_graph.h.

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

Friends And Related Function Documentation

◆ BranchSimplifier

friend class BranchSimplifier
friend

Definition at line 606 of file flow_graph.h.

◆ compiler::GraphIntrinsifier

friend class compiler::GraphIntrinsifier
friend

Definition at line 609 of file flow_graph.h.

◆ ConstantPropagator

friend class ConstantPropagator
friend

Definition at line 607 of file flow_graph.h.

◆ DeadCodeElimination

friend class DeadCodeElimination
friend

Definition at line 608 of file flow_graph.h.

◆ FlowGraphChecker

friend class FlowGraphChecker
friend

Definition at line 604 of file flow_graph.h.

◆ FlowGraphCompiler

friend class FlowGraphCompiler
friend

Definition at line 603 of file flow_graph.h.

◆ IfConverter

friend class IfConverter
friend

Definition at line 605 of file flow_graph.h.


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