5#ifndef RUNTIME_VM_COMPILER_FRONTEND_KERNEL_TO_IL_H_
6#define RUNTIME_VM_COMPILER_FRONTEND_KERNEL_TO_IL_H_
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
26class InlineExitCollector;
30class StreamingFlowGraphBuilder;
31struct InferredTypeMetadata;
34class FlowGraphBuilder;
53 intptr_t first_block_id = 1,
54 bool inlining_unchecked_entry =
false);
95 Fragment TestClosureFunctionNamedParameterRequired(
156 intptr_t first_argument_parameter_offset);
173 Fragment EnterScope(intptr_t kernel_offset,
175 Fragment ExitScope(intptr_t kernel_offset);
177 Fragment AdjustContextTo(
int depth);
182 Fragment LoadInstantiatorTypeArguments();
183 Fragment LoadFunctionTypeArguments();
184 Fragment TranslateInstantiatedTypeArguments(
188 intptr_t handler_index,
189 bool needs_stacktrace,
190 bool is_synthesized);
191 Fragment TryCatch(
int try_handler_index);
199 intptr_t type_args_len,
201 const Array& argument_names,
202 intptr_t checked_argument_count,
203 const Function& interface_target = Function::null_function(),
204 const Function& tearoff_interface_target = Function::null_function(),
206 bool use_unchecked_entry =
false,
208 bool receiver_is_not_smi =
false,
209 bool is_call_on_this =
false);
238 const Array& argument_names,
241 intptr_t type_args_len = 0,
242 bool use_unchecked_entry =
false);
247 const Array& argument_names,
248 intptr_t type_args_len = 0);
257 bool incompatible_arguments,
258 bool receiver_pushed =
false);
263 bool receiver_pushed =
false);
265 const char* throw_method_name,
272 const String& name_symbol);
280 Fragment AssertAssignableLoadTypeArguments(
298 intptr_t index_scale,
303 intptr_t index_scale,
323 Fragment LoadServiceExtensionStream();
341 Fragment FfiConvertPrimitiveToNative(
359 intptr_t offset_in_bytes,
361 Fragment FfiCallConvertCompoundArgumentToNative(
366 Fragment FfiCallConvertCompoundReturnToDart(
373 Fragment FfiCallbackConvertCompoundArgumentToDart(
378 Fragment FfiCallbackConvertCompoundReturnToNative(
387 Fragment LoadTypedDataBaseFromCompound();
388 Fragment LoadOffsetInBytesFromCompound();
398 Fragment PopFromStackToTypedDataBase(
440 void BuildArgumentTypeChecks(
Fragment* explicit_checks,
459 FlowGraph* BuildGraphOfNoSuchMethodForwarder(
461 bool is_implicit_closure_function,
462 bool throw_no_such_method_error);
474 Fragment prologue_from_normal_entry,
526 void SetConstantRangeOfCurrentDefinition(
const Fragment& fragment,
533 template <
typename T>
534 Fragment BuildExtractUnboxedSlotBitFieldIntoSmi(
const Slot& slot) {
549 "Cannot fit results of masking in place into a Smi");
556 SetConstantRangeOfCurrentDefinition(instructions, 0, T::mask_in_place());
559 if (T::shift() != 0) {
568 Fragment BuildIntegerHashCode(
bool smi);
575 const bool optimizing_;
578 intptr_t next_function_id_;
579 intptr_t AllocateFunctionId() {
return next_function_id_++; }
581 intptr_t loop_depth_;
583 intptr_t catch_depth_;
584 intptr_t block_expression_depth_;
606 TryCatchBlock* CurrentTryCatchBlock()
const {
return try_catch_block_; }
608 void SetCurrentTryCatchBlock(
TryCatchBlock* try_catch_block);
637 const Function& PrependTypeArgumentsFunction();
660 intptr_t catch_depth,
661 intptr_t block_expression_depth)
662 : breakable_block_(breakable_block),
663 switch_block_(switch_block),
664 loop_depth_(loop_depth),
665 try_depth_(try_depth),
666 catch_depth_(catch_depth),
667 block_expression_depth_(block_expression_depth) {}
670 builder->breakable_block_ = breakable_block_;
671 builder->switch_block_ = switch_block_;
672 builder->loop_depth_ = loop_depth_;
673 builder->try_depth_ = try_depth_;
674 builder->catch_depth_ = catch_depth_;
675 builder->block_expression_depth_ = block_expression_depth_;
681 const intptr_t loop_depth_;
682 const intptr_t try_depth_;
683 const intptr_t catch_depth_;
684 const intptr_t block_expression_depth_;
691 outer_(
builder->switch_block_),
692 outer_finally_(
builder->try_finally_block_),
693 case_count_(case_count),
694 context_depth_(
builder->context_depth_),
695 try_index_(
builder->CurrentTryIndex()) {
696 builder_->switch_block_ =
this;
697 if (outer_ !=
nullptr) {
698 depth_ = outer_->depth_ + outer_->case_count_;
706 return destinations_.Lookup(case_num) !=
nullptr;
713 intptr_t* context_depth =
nullptr) {
715 ASSERT(builder_->switch_block_ ==
this);
718 while (block->depth_ > target_index) {
719 block = block->outer_;
724 if (outer_finally !=
nullptr) {
725 *outer_finally = block->outer_finally_;
726 *context_depth = block->context_depth_;
730 return block->EnsureDestination(target_index - block->depth_);
737 intptr_t* context_depth =
nullptr) {
739 if (outer_finally !=
nullptr) {
740 *outer_finally = outer_finally_;
741 *context_depth = context_depth_;
745 return EnsureDestination(case_num);
751 if (cached_inst ==
nullptr) {
753 destinations_.Insert(case_num,
inst);
759 FlowGraphBuilder* builder_;
762 IntMap<JoinEntryInstr*> destinations_;
764 TryFinallyBlock* outer_finally_;
765 intptr_t case_count_;
767 intptr_t context_depth_;
774 intptr_t try_handler_index = -1)
776 outer_(
builder->CurrentTryCatchBlock()),
777 try_index_(try_handler_index == -1 ?
builder->AllocateTryIndex()
778 : try_handler_index) {
779 builder->SetCurrentTryCatchBlock(
this);
790 intptr_t
const try_index_;
799 outer_(
builder->try_finally_block_),
801 context_depth_(
builder->context_depth_),
802 try_index_(builder_->CurrentTryIndex()),
806 state_(builder_->breakable_block_,
807 builder_->switch_block_,
808 builder_->loop_depth_,
809 builder_->try_depth_ - 1,
810 builder_->catch_depth_,
811 builder_->block_expression_depth_) {
812 builder_->try_finally_block_ =
this;
825 const intptr_t finalizer_kernel_offset_;
826 const intptr_t context_depth_;
827 const intptr_t try_index_;
837 outer_(
builder->breakable_block_),
838 destination_(nullptr),
839 outer_finally_(
builder->try_finally_block_),
840 context_depth_(
builder->context_depth_),
841 try_index_(
builder->CurrentTryIndex()) {
842 if (builder_->breakable_block_ ==
nullptr) {
845 index_ = builder_->breakable_block_->index_ + 1;
847 builder_->breakable_block_ =
this;
857 intptr_t* context_depth) {
859 ASSERT(builder_->breakable_block_ ==
this);
862 while (block->index_ != label_index) {
863 block = block->outer_;
866 *outer_finally = block->outer_finally_;
867 *context_depth = block->context_depth_;
868 return block->EnsureDestination();
873 if (destination_ ==
nullptr) {
879 FlowGraphBuilder* builder_;
882 JoinEntryInstr* destination_;
883 TryFinallyBlock* outer_finally_;
884 intptr_t context_depth_;
901 builder_->catch_block_ =
this;
914 intptr_t catch_try_index_;
942 ASSERT(integer_ !=
nullptr);
947 ASSERT(integer_ ==
nullptr);
952 intptr_t case_index_;
955 const Integer* integer_ =
nullptr;
976 intptr_t
min()
const {
return min_; }
977 intptr_t
max()
const {
return max_; }
997 Fragment branch_instructions_;
998 bool is_bounds_checked_;
1023 ASSERT(default_case_ == -1);
1024 default_case_ = index;
1031 return case_expression_counts_;
1035 return expressions_;
1039 return sorted_expressions_;
1046 ASSERT(expression_min_ !=
nullptr);
1047 return *expression_min_;
1050 ASSERT(expression_max_ !=
nullptr);
1051 return *expression_max_;
1073 void PrepareForOptimizedSwitch();
1076 bool is_optimizable_ =
false;
1077 bool is_enum_switch_ =
false;
1079 const bool is_exhaustive_;
1082 const intptr_t case_count_;
1083 intptr_t default_case_ = -1;
1088 const Integer* expression_min_ =
nullptr;
1089 const Integer* expression_max_ =
nullptr;
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Representation representation() const
Fragment IntConstant(int64_t value)
JoinEntryInstr * BuildJoinEntry()
Fragment LoadNativeField(const Slot &native_field, InnerPointerAccess loads_inner_pointer, bool calls_initializer=false)
Fragment UnboxedIntConstant(int64_t value, Representation representation)
Fragment Box(Representation from)
Fragment BinaryIntegerOp(Token::Kind op, Representation representation, bool is_truncating=false)
Fragment SmiBinaryOp(Token::Kind op, bool is_truncating=false)
JoinEntryInstr * destination()
JoinEntryInstr * BreakDestination(intptr_t label_index, TryFinallyBlock **outer_finally, intptr_t *context_depth)
BreakableBlock(FlowGraphBuilder *builder)
intptr_t catch_try_index()
LocalVariable * stack_trace_var()
LocalVariable * exception_var()
CatchBlock(FlowGraphBuilder *builder, LocalVariable *exception_var, LocalVariable *stack_trace_var, intptr_t catch_try_index)
virtual ~FlowGraphBuilder()
FlowGraphBuilder(ParsedFunction *parsed_function, ZoneGrowableArray< const ICData * > *ic_data_array, ZoneGrowableArray< intptr_t > *context_level_array, InlineExitCollector *exit_collector, bool optimizing, intptr_t osr_id, intptr_t first_block_id=1, bool inlining_unchecked_entry=false)
static bool IsExpressionTempVarUsedInRecognizedMethodFlowGraph(const Function &function)
static bool IsRecognizedMethodForFlowGraph(const Function &function)
ProgramState(BreakableBlock *breakable_block, SwitchBlock *switch_block, intptr_t loop_depth, intptr_t try_depth, intptr_t catch_depth, intptr_t block_expression_depth)
void assignTo(FlowGraphBuilder *builder) const
GrowableArray< LocalVariable * > catch_context_variables
GrowableArray< LocalVariable * > stack_trace_variables
GrowableArray< LocalVariable * > raw_exception_variables
GrowableArray< LocalVariable * > exception_variables
GrowableArray< LocalVariable * > raw_stack_trace_variables
SwitchBlock(FlowGraphBuilder *builder, intptr_t case_count)
bool HadJumper(intptr_t case_num)
JoinEntryInstr * DestinationDirect(intptr_t case_num, TryFinallyBlock **outer_finally=nullptr, intptr_t *context_depth=nullptr)
JoinEntryInstr * Destination(intptr_t target_index, TryFinallyBlock **outer_finally=nullptr, intptr_t *context_depth=nullptr)
const Instance & value() const
SwitchExpression(intptr_t case_index, TokenPosition position, const Instance &value)
const Integer & integer() const
void set_integer(const Integer &integer)
const TokenPosition & position() const
intptr_t case_index() const
const Integer & expression_max() const
intptr_t default_case() const
const AbstractType & expression_type() const
bool is_optimizable() const
void set_default_case(intptr_t index)
bool is_enum_switch() const
SwitchHelper(Zone *zone, TokenPosition position, bool is_exhaustive, const AbstractType &expression_type, SwitchBlock *switch_block, intptr_t case_count)
void AddExpression(intptr_t case_index, TokenPosition position, const Instance &value)
const GrowableArray< SwitchExpression > & expressions() const
const GrowableArray< SwitchExpression * > & sorted_expressions() const
const GrowableArray< intptr_t > & case_expression_counts() const
int64_t ExpressionRange() const
SwitchBlock * switch_block()
intptr_t case_count() const
bool RequiresUpperBoundCheck() const
SwitchDispatch SelectDispatchStrategy()
bool is_exhaustive() const
const GrowableArray< Fragment > & case_bodies() const
const Integer & expression_min() const
const TokenPosition & position() const
void AddCaseBody(Fragment body)
bool RequiresLowerBoundCheck() const
Fragment branch_instructions() const
bool is_bounds_checked() const
static SwitchRange Leaf(intptr_t index, Fragment branch_instructions, bool is_bounds_checked=false)
static SwitchRange Branch(intptr_t min, intptr_t max, Fragment branch_instructions)
TryCatchBlock * outer() const
TryCatchBlock(FlowGraphBuilder *builder, intptr_t try_handler_index=-1)
const ProgramState & state() const
intptr_t finalizer_kernel_offset() const
intptr_t try_index() const
TryFinallyBlock * outer() const
TryFinallyBlock(FlowGraphBuilder *builder, intptr_t finalizer_kernel_offset)
intptr_t context_depth() const
Dart_NativeFunction function
static float max(float r, float g, float b)
static float min(float r, float g, float b)
@ kCheckCovariantTypeParameterBounds
@ kCheckNonCovariantTypeParameterBounds
@ kCheckAllTypeParameterBounds
@ kSwitchDispatchLinearScan
@ kSwitchDispatchJumpTable
@ kSwitchDispatchBinarySearch
static StackTracePtr CurrentStackTrace(Thread *thread, intptr_t skip_frames=1)
static ObjectPtr ThrowTypeError(const TokenPosition token_pos, const Instance &src_value, const AbstractType &dst_type, const String &dst_name)
Dest BitCast(const Source &source)
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 mode
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
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
std::function< void()> closure
static bool RequiresAllocation(Representation rep)
static constexpr bool IsUnboxedInteger(Representation rep)