Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | List of all members
dart::LoadFieldInstr Class Reference

#include <il.h>

Inheritance diagram for dart::LoadFieldInstr:
dart::TemplateLoadField< 1 > dart::TemplateDefinition< N, Throws > dart::Instruction dart::ZoneAllocated

Public Member Functions

 LoadFieldInstr (Value *instance, const Slot &slot, InnerPointerAccess loads_inner_pointer, const InstructionSource &source, bool calls_initializer=false, intptr_t deopt_id=DeoptId::kNone)
 
 LoadFieldInstr (Value *instance, const Slot &slot, const InstructionSource &source, bool calls_initializer=false, intptr_t deopt_id=DeoptId::kNone)
 
Valueinstance () const
 
const Slotslot () const
 
InnerPointerAccess loads_inner_pointer () const
 
void set_loads_inner_pointer (InnerPointerAccess value)
 
virtual Representation RequiredInputRepresentation (intptr_t idx) const
 
virtual Representation representation () const
 
virtual CompileType ComputeType () const
 
virtual void InferRange (RangeAnalysis *analysis, Range *range)
 
bool MayCreateUntaggedAlias () const
 
virtual bool MayCreateUnsafeUntaggedPointer () const
 
bool IsImmutableLoad () const
 
bool IsImmutableLengthLoad () const
 
bool Evaluate (const Object &instance_value, Object *result)
 
virtual DefinitionCanonicalize (FlowGraph *flow_graph)
 
virtual bool AllowsCSE () const
 
virtual bool CanTriggerGC () const
 
virtual bool AttributesEqual (const Instruction &other) const
 
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadFieldInstr, TemplateLoadField, FIELD_LIST) private DISALLOW_COPY_AND_ASSIGN (LoadFieldInstr)
 
- Public Member Functions inherited from dart::TemplateLoadField< 1 >
 TemplateLoadField (const InstructionSource &source, bool calls_initializer=false, intptr_t deopt_id=DeoptId::kNone, const Field *field=nullptr)
 
virtual TokenPosition token_pos () const
 
bool calls_initializer () const
 
void set_calls_initializer (bool value)
 
bool throw_exception_on_initialization () const
 
virtual bool UseSharedSlowPathStub (bool is_optimizing) const
 
virtual intptr_t DeoptimizationTarget () const
 
virtual bool ComputeCanDeoptimize () const
 
virtual bool ComputeCanDeoptimizeAfterCall () const
 
virtual intptr_t NumberOfInputsConsumedBeforeCall () const
 
virtual bool HasUnknownSideEffects () const
 
virtual bool CanCallDart () const
 
virtual bool CanTriggerGC () const
 
virtual bool MayThrow () const
 
- Public Member Functions inherited from dart::TemplateDefinition< N, Throws >
 TemplateDefinition (intptr_t deopt_id=DeoptId::kNone)
 
 TemplateDefinition (const InstructionSource &source, intptr_t deopt_id=DeoptId::kNone)
 
virtual intptr_t InputCount () const
 
virtual ValueInputAt (intptr_t i) const
 
virtual bool MayThrow () const
 
- Public Member Functions inherited from dart::Instruction
 Instruction (const InstructionSource &source, intptr_t deopt_id=DeoptId::kNone)
 
 Instruction (intptr_t deopt_id=DeoptId::kNone)
 
virtual ~Instruction ()
 
virtual Tag tag () const =0
 
virtual intptr_t statistics_tag () const
 
intptr_t deopt_id () const
 
virtual TokenPosition token_pos () const
 
InstructionSource source () const
 
virtual intptr_t InputCount () const =0
 
virtual ValueInputAt (intptr_t i) const =0
 
void SetInputAt (intptr_t i, Value *value)
 
InputsIterable inputs ()
 
void UnuseAllInputs ()
 
virtual intptr_t ArgumentCount () const
 
ValueArgumentValueAt (intptr_t index) const
 
DefinitionArgumentAt (intptr_t index) const
 
virtual void SetMoveArguments (MoveArgumentsArray *move_arguments)
 
virtual MoveArgumentsArrayGetMoveArguments () const
 
virtual void ReplaceInputsWithMoveArguments (MoveArgumentsArray *move_arguments)
 
bool HasMoveArguments () const
 
void RepairArgumentUsesInEnvironment () const
 
virtual bool ComputeCanDeoptimize () const =0
 
virtual bool ComputeCanDeoptimizeAfterCall () const
 
bool CanDeoptimize () const
 
virtual void Accept (InstructionVisitor *visitor)=0
 
Instructionprevious () const
 
void set_previous (Instruction *instr)
 
Instructionnext () const
 
void set_next (Instruction *instr)
 
void LinkTo (Instruction *next)
 
InstructionRemoveFromGraph (bool return_previous=true)
 
virtual intptr_t SuccessorCount () const
 
virtual BlockEntryInstrSuccessorAt (intptr_t index) const
 
SuccessorsIterable successors () const
 
void Goto (JoinEntryInstr *entry)
 
virtual const char * DebugName () const =0
 
void CheckField (const Field &field) const
 
const char * ToCString () const
 
 DECLARE_INSTRUCTION_TYPE_CHECK (BlockEntryWithInitialDefs, BlockEntryWithInitialDefs) template< typename T > T *Cast()
 
template<typename T >
const TCast () const
 
LocationSummarylocs ()
 
bool HasLocs () const
 
virtual LocationSummaryMakeLocationSummary (Zone *zone, bool is_optimizing) const =0
 
void InitializeLocationSummary (Zone *zone, bool optimizing)
 
virtual void EmitNativeCode (FlowGraphCompiler *compiler)
 
Environmentenv () const
 
void SetEnvironment (Environment *deopt_env)
 
void RemoveEnvironment ()
 
void ReplaceInEnvironment (Definition *current, Definition *replacement)
 
virtual intptr_t NumberOfInputsConsumedBeforeCall () const
 
intptr_t GetPassSpecificId (CompilerPass::Id pass) const
 
void SetPassSpecificId (CompilerPass::Id pass, intptr_t id)
 
bool HasPassSpecificId (CompilerPass::Id pass) const
 
bool HasUnmatchedInputRepresentations () const
 
virtual Representation RequiredInputRepresentation (intptr_t idx) const
 
SpeculativeMode SpeculativeModeOfInputs () const
 
virtual SpeculativeMode SpeculativeModeOfInput (intptr_t index) const
 
virtual Representation representation () const
 
bool WasEliminated () const
 
virtual intptr_t DeoptimizationTarget () const
 
virtual InstructionCanonicalize (FlowGraph *flow_graph)
 
void InsertBefore (Instruction *next)
 
void InsertAfter (Instruction *prev)
 
InstructionAppendInstruction (Instruction *tail)
 
virtual bool AllowsCSE () const
 
virtual bool HasUnknownSideEffects () const =0
 
virtual bool CanCallDart () const
 
virtual bool CanTriggerGC () const
 
virtual BlockEntryInstrGetBlock ()
 
virtual intptr_t inlining_id () const
 
virtual void set_inlining_id (intptr_t value)
 
virtual bool has_inlining_id () const
 
virtual uword Hash () const
 
bool Equals (const Instruction &other) const
 
virtual bool AttributesEqual (const Instruction &other) const
 
void InheritDeoptTarget (Zone *zone, Instruction *other)
 
bool NeedsEnvironment () const
 
virtual bool CanBecomeDeoptimizationTarget () const
 
void InheritDeoptTargetAfter (FlowGraph *flow_graph, Definition *call, Definition *result)
 
virtual bool MayThrow () const =0
 
virtual bool MayHaveVisibleEffect () const
 
virtual bool CanEliminate (const BlockEntryInstr *block) const
 
bool CanEliminate ()
 
bool IsDominatedBy (Instruction *dom)
 
void ClearEnv ()
 
void Unsupported (FlowGraphCompiler *compiler)
 
virtual bool UseSharedSlowPathStub (bool is_optimizing) const
 
Location::Kind RegisterKindForResult () const
 
- 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 bool TryEvaluateLoad (const Object &instance, const Field &field, Object *result)
 
static bool TryEvaluateLoad (const Object &instance, const Slot &field, Object *result)
 
static bool IsFixedLengthArrayCid (intptr_t cid)
 
static bool IsTypedDataViewFactory (const Function &function)
 
static bool IsUnmodifiableTypedDataViewFactory (const Function &function)
 
- Static Public Member Functions inherited from dart::Instruction
static const ICDataGetICData (const ZoneGrowableArray< const ICData * > &ic_data_array, intptr_t deopt_id, bool is_static_call)
 
static LocationSummaryMakeCallSummary (Zone *zone, const Instruction *instr, LocationSummary *locs=nullptr)
 
static bool SlowPathSharingSupported (bool is_optimizing)
 

Additional Inherited Members

- Public Types inherited from dart::TemplateDefinition< N, Throws >
using BaseClass = typename NoCSE< Definition, PureDefinition >::Base
 
- Public Types inherited from dart::Instruction
enum  Tag { FOR_EACH_INSTRUCTION =(DECLARE_TAG) kNumInstructions }
 
enum  SpeculativeMode { kGuardInputs , kNotSpeculative }
 
using InputsIterable = InstructionIndexedPropertyIterable< InputsTrait >
 
using SuccessorsIterable = InstructionIndexedPropertyIterable< SuccessorsTrait >
 
- Static Public Attributes inherited from dart::Instruction
static const intptr_t kInstructionAttrs [kNumInstructions]
 
- Protected Member Functions inherited from dart::Instruction
intptr_t GetDeoptId () const
 
virtual void CopyDeoptIdFrom (const Instruction &instr)
 
void WriteExtraWithoutInputs (FlowGraphSerializer *s)
 
void ReadExtraWithoutInputs (FlowGraphDeserializer *d)
 
- Protected Attributes inherited from dart::TemplateDefinition< N, Throws >
EmbeddedArray< Value *, Ninputs_
 

Detailed Description

Definition at line 8101 of file il.h.

Constructor & Destructor Documentation

◆ LoadFieldInstr() [1/2]

dart::LoadFieldInstr::LoadFieldInstr ( Value instance,
const Slot slot,
InnerPointerAccess  loads_inner_pointer,
const InstructionSource source,
bool  calls_initializer = false,
intptr_t  deopt_id = DeoptId::kNone 
)
inline

Definition at line 8103 of file il.h.

8111 deopt_id,
8112 slot.IsDartField() ? &slot.field() : nullptr),
8113 slot_(slot),
8114 loads_inner_pointer_(loads_inner_pointer) {
8115 switch (loads_inner_pointer) {
8117 ASSERT(slot.representation() != kUntagged);
8118 break;
8120 ASSERT(slot.representation() == kUntagged);
8122 break;
8124 ASSERT(slot.representation() == kUntagged);
8125 break;
8126 }
8127 SetInputAt(0, instance);
8128 }
void SetInputAt(intptr_t i, Value *value)
Definition: il.h:1014
InstructionSource source() const
Definition: il.h:1008
intptr_t deopt_id() const
Definition: il.h:993
const Slot & slot() const
Definition: il.h:8144
InnerPointerAccess loads_inner_pointer() const
Definition: il.h:8146
Value * instance() const
Definition: il.h:8143
bool IsDartField() const
Definition: slot.h:503
const Field & field() const
Definition: slot.h:540
Representation representation() const
Definition: slot.h:519
bool may_contain_inner_pointer() const
Definition: slot.h:533
bool calls_initializer() const
Definition: il.h:6623
TemplateLoadField(const InstructionSource &source, bool calls_initializer=false, intptr_t deopt_id=DeoptId::kNone, const Field *field=nullptr)
Definition: il.h:6609
#define ASSERT(E)

◆ LoadFieldInstr() [2/2]

dart::LoadFieldInstr::LoadFieldInstr ( Value instance,
const Slot slot,
const InstructionSource source,
bool  calls_initializer = false,
intptr_t  deopt_id = DeoptId::kNone 
)
inline

Definition at line 8131 of file il.h.

8137 slot,
8139 source,
8141 deopt_id) {}
LoadFieldInstr(Value *instance, const Slot &slot, InnerPointerAccess loads_inner_pointer, const InstructionSource &source, bool calls_initializer=false, intptr_t deopt_id=DeoptId::kNone)
Definition: il.h:8103

Member Function Documentation

◆ AllowsCSE()

virtual bool dart::LoadFieldInstr::AllowsCSE ( ) const
inlinevirtual

Reimplemented from dart::Instruction.

Definition at line 8210 of file il.h.

8210{ return slot_.is_immutable(); }

◆ AttributesEqual()

bool dart::LoadFieldInstr::AttributesEqual ( const Instruction other) const
virtual

Reimplemented from dart::Instruction.

Definition at line 1121 of file il.cc.

1121 {
1122 auto const other_load = other.AsLoadField();
1123 ASSERT(other_load != nullptr);
1124 return &this->slot_ == &other_load->slot_;
1125}

◆ Canonicalize()

Definition * dart::LoadFieldInstr::Canonicalize ( FlowGraph flow_graph)
virtual

Reimplemented from dart::Instruction.

Definition at line 2868 of file il.cc.

2868 {
2869 if (!HasUses() && !calls_initializer()) return nullptr;
2870
2871 Definition* orig_instance = instance()->definition()->OriginalDefinition();
2872 if (IsImmutableLengthLoad()) {
2874 if (StaticCallInstr* call = orig_instance->AsStaticCall()) {
2875 // For fixed length arrays if the array is the result of a known
2876 // constructor call we can replace the length load with the length
2877 // argument passed to the constructor.
2878 if (call->is_known_list_constructor() &&
2879 IsFixedLengthArrayCid(call->Type()->ToCid())) {
2880 return call->ArgumentAt(1);
2881 } else if (call->function().recognized_kind() ==
2882 MethodRecognizer::kByteDataFactory) {
2883 // Similarly, we check for the ByteData constructor and forward its
2884 // explicit length argument appropriately.
2885 return call->ArgumentAt(1);
2886 } else if (IsTypedDataViewFactory(call->function())) {
2887 // Typed data view factories all take three arguments (after
2888 // the implicit type arguments parameter):
2889 //
2890 // 1) _TypedList buffer -- the underlying data for the view
2891 // 2) int offsetInBytes -- the offset into the buffer to start viewing
2892 // 3) int length -- the number of elements in the view
2893 //
2894 // Here, we forward the third.
2895 return call->ArgumentAt(3);
2896 }
2897 } else if (LoadFieldInstr* load_array = orig_instance->AsLoadField()) {
2898 // For arrays with guarded lengths, replace the length load
2899 // with a constant.
2900 const Slot& slot = load_array->slot();
2901 if (slot.IsDartField()) {
2902 if (slot.field().guarded_list_length() >= 0) {
2903 return flow_graph->GetConstant(
2905 }
2906 }
2907 }
2908 }
2909
2910 switch (slot().kind()) {
2911 case Slot::Kind::kArray_length:
2912 if (CreateArrayInstr* create_array = orig_instance->AsCreateArray()) {
2913 return create_array->num_elements()->definition();
2914 }
2915 break;
2916 case Slot::Kind::kTypedDataBase_length:
2917 if (AllocateTypedDataInstr* alloc_typed_data =
2918 orig_instance->AsAllocateTypedData()) {
2919 return alloc_typed_data->num_elements()->definition();
2920 }
2921 break;
2922 case Slot::Kind::kTypedDataView_typed_data:
2923 // This case cover the first explicit argument to typed data view
2924 // factories, the data (buffer).
2926 if (StaticCallInstr* call = orig_instance->AsStaticCall()) {
2927 if (IsTypedDataViewFactory(call->function()) ||
2929 return call->ArgumentAt(1);
2930 }
2931 }
2932 break;
2933 case Slot::Kind::kTypedDataView_offset_in_bytes:
2934 // This case cover the second explicit argument to typed data view
2935 // factories, the offset into the buffer.
2937 if (StaticCallInstr* call = orig_instance->AsStaticCall()) {
2938 if (IsTypedDataViewFactory(call->function())) {
2939 return call->ArgumentAt(2);
2940 } else if (call->function().recognized_kind() ==
2941 MethodRecognizer::kByteDataFactory) {
2942 // A _ByteDataView returned from the ByteData constructor always
2943 // has an offset of 0.
2944 return flow_graph->GetConstant(Object::smi_zero());
2945 }
2946 }
2947 break;
2948 case Slot::Kind::kRecord_shape:
2950 if (auto* alloc_rec = orig_instance->AsAllocateRecord()) {
2951 return flow_graph->GetConstant(Smi::Handle(alloc_rec->shape().AsSmi()));
2952 } else if (auto* alloc_rec = orig_instance->AsAllocateSmallRecord()) {
2953 return flow_graph->GetConstant(Smi::Handle(alloc_rec->shape().AsSmi()));
2954 } else {
2955 const AbstractType* type = instance()->Type()->ToAbstractType();
2956 if (type->IsRecordType()) {
2957 return flow_graph->GetConstant(
2958 Smi::Handle(RecordType::Cast(*type).shape().AsSmi()));
2959 }
2960 }
2961 break;
2964 if (StaticCallInstr* call = orig_instance->AsStaticCall()) {
2965 if (call->is_known_list_constructor()) {
2966 return call->ArgumentAt(0);
2967 } else if (IsTypedDataViewFactory(call->function()) ||
2969 return flow_graph->constant_null();
2970 }
2971 switch (call->function().recognized_kind()) {
2972 case MethodRecognizer::kByteDataFactory:
2973 case MethodRecognizer::kLinkedHashBase_getData:
2974 case MethodRecognizer::kImmutableLinkedHashBase_getData:
2975 return flow_graph->constant_null();
2976 default:
2977 break;
2978 }
2979 } else if (CreateArrayInstr* create_array =
2980 orig_instance->AsCreateArray()) {
2981 return create_array->type_arguments()->definition();
2982 } else if (LoadFieldInstr* load_array = orig_instance->AsLoadField()) {
2983 const Slot& slot = load_array->slot();
2984 switch (slot.kind()) {
2986 // For trivially exact fields we know that type arguments match
2987 // static type arguments exactly.
2988 const Field& field = slot.field();
2989 if (field.static_type_exactness_state().IsTriviallyExact()) {
2990 return flow_graph->GetConstant(TypeArguments::Handle(
2991 Type::Cast(AbstractType::Handle(field.type()))
2992 .GetInstanceTypeArguments(flow_graph->thread())));
2993 }
2994 break;
2995 }
2996
2997 case Slot::Kind::kLinkedHashBase_data:
2998 return flow_graph->constant_null();
2999
3000 default:
3001 break;
3002 }
3003 }
3004 break;
3005 case Slot::Kind::kPointerBase_data:
3008 const intptr_t cid = instance()->Type()->ToNullableCid();
3009 // Pointers and ExternalTypedData objects never contain inner pointers.
3010 if (cid == kPointerCid || IsExternalTypedDataClassId(cid)) {
3012 }
3013 }
3014 break;
3015 default:
3016 break;
3017 }
3018
3019 // Try folding away loads from constant objects.
3020 if (instance()->BindsToConstant()) {
3021 Object& result = Object::Handle();
3022 if (Evaluate(instance()->BoundConstant(), &result)) {
3023 if (result.IsSmi() || result.IsOld()) {
3024 return flow_graph->GetConstant(result);
3025 }
3026 }
3027 }
3028
3029 if (instance()->definition()->IsAllocateObject() && IsImmutableLoad()) {
3030 StoreFieldInstr* initializing_store = nullptr;
3031 for (auto use : instance()->definition()->input_uses()) {
3032 if (auto store = use->instruction()->AsStoreField()) {
3033 if ((use->use_index() == StoreFieldInstr::kInstancePos) &&
3034 store->slot().IsIdentical(slot())) {
3035 if (initializing_store == nullptr) {
3036 initializing_store = store;
3037 } else {
3038 initializing_store = nullptr;
3039 break;
3040 }
3041 }
3042 }
3043 }
3044
3045 // If we find an initializing store then it *must* by construction
3046 // dominate the load.
3047 if (initializing_store != nullptr &&
3048 initializing_store->is_initialization()) {
3049 ASSERT(IsDominatedBy(initializing_store));
3050 return initializing_store->value()->definition();
3051 }
3052 }
3053
3054 return this;
3055}
SI void store(P *ptr, const T &val)
GLenum type
intptr_t ToNullableCid()
const AbstractType * ToAbstractType()
Definition * OriginalDefinition()
Definition: il.cc:532
intptr_t guarded_list_length() const
Definition: object.cc:12101
bool IsDominatedBy(Instruction *dom)
Definition: il.cc:1581
bool IsImmutableLengthLoad() const
Definition: il.h:8187
void set_loads_inner_pointer(InnerPointerAccess value)
Definition: il.h:8149
bool IsImmutableLoad() const
Definition: il.h:8177
static bool IsUnmodifiableTypedDataViewFactory(const Function &function)
Definition: il.cc:2707
bool Evaluate(const Object &instance_value, Object *result)
Definition: il.cc:2864
static bool IsFixedLengthArrayCid(intptr_t cid)
Definition: il.cc:2668
static bool IsTypedDataViewFactory(const Function &function)
Definition: il.cc:2683
static Object & Handle()
Definition: object.h:407
Kind kind() const
Definition: slot.h:502
static SmiPtr New(intptr_t value)
Definition: object.h:10006
Definition * definition() const
Definition: il.h:103
CompileType * Type()
GAsyncResult * result
const intptr_t cid
bool IsExternalTypedDataClassId(intptr_t index)
Definition: class_id.h:447
def call(args)
Definition: dom.py:159

◆ CanTriggerGC()

virtual bool dart::LoadFieldInstr::CanTriggerGC ( ) const
inlinevirtual

Reimplemented from dart::TemplateLoadField< 1 >.

Definition at line 8212 of file il.h.

8212{ return calls_initializer(); }

◆ ComputeType()

CompileType dart::LoadFieldInstr::ComputeType ( ) const
virtual

Definition at line 1701 of file type_propagator.cc.

1701 {
1702 if (slot().IsRecordField()) {
1704 slot().offset_in_bytes());
1705 if (auto* alloc = instance()->definition()->AsAllocateSmallRecord()) {
1706 if (index < alloc->num_fields()) {
1707 return *(alloc->InputAt(index)->Type());
1708 }
1709 }
1710 const AbstractType* instance_type = instance()->Type()->ToAbstractType();
1711 if (instance_type->IsRecordType()) {
1712 const auto& record_type = RecordType::Cast(*instance_type);
1713 if (index < record_type.NumFields()) {
1714 const auto& field_type =
1715 AbstractType::ZoneHandle(record_type.FieldTypeAt(index));
1716 return CompileType::FromAbstractType(field_type,
1719 }
1720 }
1721 }
1722 CompileType type = slot().type();
1723 if (calls_initializer()) {
1724 type = type.CopyNonSentinel();
1725 }
1726 TraceStrongModeType(this, &type);
1727 return type;
1728}
static constexpr bool kCannotBeSentinel
Definition: compile_type.h:49
static constexpr bool kCanBeNull
Definition: compile_type.h:45
static CompileType FromAbstractType(const AbstractType &type, bool can_be_null, bool can_be_sentinel)
static Object & ZoneHandle()
Definition: object.h:419
CompileType type() const
Definition: slot.h:538
static intptr_t field_index_at_offset(intptr_t offset_in_bytes)
static void TraceStrongModeType(const Instruction *instr, const AbstractType &type)

◆ DISALLOW_COPY_AND_ASSIGN()

DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadFieldInstr, TemplateLoadField, FIELD_LIST) private dart::LoadFieldInstr::DISALLOW_COPY_AND_ASSIGN ( LoadFieldInstr  )

◆ Evaluate()

bool dart::LoadFieldInstr::Evaluate ( const Object instance_value,
Object result 
)

Definition at line 2864 of file il.cc.

2864 {
2865 return TryEvaluateLoad(instance, slot(), result);
2866}
static bool TryEvaluateLoad(const Object &instance, const Field &field, Object *result)
Definition: il.cc:2812

◆ InferRange()

void dart::LoadFieldInstr::InferRange ( RangeAnalysis analysis,
Range range 
)
virtual

Definition at line 2828 of file range_analysis.cc.

2828 {
2829 switch (slot().kind()) {
2830 case Slot::Kind::kArray_length:
2831 case Slot::Kind::kGrowableObjectArray_length:
2832 *range = Range(
2835 break;
2836
2837 case Slot::Kind::kTypedDataBase_length:
2838 case Slot::Kind::kTypedDataView_offset_in_bytes:
2840 break;
2841
2842 case Slot::Kind::kAbstractType_hash:
2843 case Slot::Kind::kTypeArguments_hash:
2844 *range = Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi());
2845 break;
2846
2847 case Slot::Kind::kTypeArguments_length:
2848 *range = Range(RangeBoundary::FromConstant(0),
2851 break;
2852
2853 case Slot::Kind::kRecord_shape:
2855 break;
2856
2857 case Slot::Kind::kString_length:
2858 *range = Range(
2861 break;
2862
2866 // Use default value.
2867 Definition::InferRange(analysis, range);
2868 break;
2869
2872#define NATIVE_SLOT_CASE(ClassName, __, FieldName, ___, ____) \
2873 case Slot::Kind::k##ClassName##_##FieldName:
2875#undef NATIVE_SLOT_CASE
2876 // Not an integer valued field.
2877 UNREACHABLE();
2878 break;
2879
2881 // Should not be used in LoadField instructions.
2882 UNREACHABLE();
2883 break;
2884
2885#define UNBOXED_NATIVE_SLOT_CASE(Class, __, Field, ___, ____) \
2886 case Slot::Kind::k##Class##_##Field:
2888#undef UNBOXED_NATIVE_SLOT_CASE
2889 *range = Range::Full(slot().representation());
2890 break;
2891
2892 case Slot::Kind::kClosure_hash:
2893 case Slot::Kind::kLinkedHashBase_hash_mask:
2894 case Slot::Kind::kLinkedHashBase_used_data:
2895 case Slot::Kind::kLinkedHashBase_deleted_keys:
2897 break;
2898
2899 case Slot::Kind::kArgumentsDescriptor_type_args_len:
2900 case Slot::Kind::kArgumentsDescriptor_positional_count:
2901 case Slot::Kind::kArgumentsDescriptor_count:
2902 case Slot::Kind::kArgumentsDescriptor_size:
2904 break;
2905 }
2906}
#define UNREACHABLE()
Definition: assert.h:248
virtual void InferRange(RangeAnalysis *analysis, Range *range)
virtual Representation representation() const
Definition: il.cc:921
static RangeBoundary MaxSmi()
static RangeBoundary MinSmi()
static RangeBoundary FromConstant(int64_t val)
static Range Full(RangeBoundary::RangeSize size)
static const word kMaxElements
Definition: runtime_api.h:594
static const word kMaxElements
Definition: runtime_api.h:783
#define UNBOXED_NATIVE_SLOT_CASE(Class, __, Field, ___, ____)
#define NATIVE_SLOT_CASE(ClassName, __, FieldName, ___, ____)
#define UNBOXED_NATIVE_SLOTS_LIST(V)
Definition: slot.h:297
#define NOT_INT_NATIVE_SLOTS_LIST(V)
Definition: slot.h:335

◆ instance()

Value * dart::LoadFieldInstr::instance ( ) const
inline

Definition at line 8143 of file il.h.

8143{ return inputs_[0]; }
EmbeddedArray< Value *, N > inputs_
Definition: il.h:2762

◆ IsFixedLengthArrayCid()

bool dart::LoadFieldInstr::IsFixedLengthArrayCid ( intptr_t  cid)
static

Definition at line 2668 of file il.cc.

2668 {
2670 return true;
2671 }
2672
2673 switch (cid) {
2674 case kArrayCid:
2675 case kImmutableArrayCid:
2676 case kTypeArgumentsCid:
2677 return true;
2678 default:
2679 return false;
2680 }
2681}
bool IsTypedDataBaseClassId(intptr_t index)
Definition: class_id.h:429

◆ IsImmutableLengthLoad()

bool dart::LoadFieldInstr::IsImmutableLengthLoad ( ) const
inline

Definition at line 8187 of file il.h.

8187{ return slot().IsImmutableLengthSlot(); }
bool IsImmutableLengthSlot() const
Definition: slot.cc:208

◆ IsImmutableLoad()

bool dart::LoadFieldInstr::IsImmutableLoad ( ) const
inline

Definition at line 8177 of file il.h.

8177 {
8178 // The data() field in PointerBase is marked mutable, but is not actually
8179 // mutable if it doesn't contain an inner pointer (e.g., for external
8180 // typed data and Pointer objects).
8181 if (slot().IsIdentical(Slot::PointerBase_data())) {
8183 }
8184 return slot().is_immutable();
8185 }
bool is_immutable() const
Definition: slot.h:521

◆ IsTypedDataViewFactory()

bool dart::LoadFieldInstr::IsTypedDataViewFactory ( const Function function)
static

Definition at line 2683 of file il.cc.

2683 {
2684 auto kind = function.recognized_kind();
2685 switch (kind) {
2686 case MethodRecognizer::kTypedData_ByteDataView_factory:
2687 case MethodRecognizer::kTypedData_Int8ArrayView_factory:
2688 case MethodRecognizer::kTypedData_Uint8ArrayView_factory:
2689 case MethodRecognizer::kTypedData_Uint8ClampedArrayView_factory:
2690 case MethodRecognizer::kTypedData_Int16ArrayView_factory:
2691 case MethodRecognizer::kTypedData_Uint16ArrayView_factory:
2692 case MethodRecognizer::kTypedData_Int32ArrayView_factory:
2693 case MethodRecognizer::kTypedData_Uint32ArrayView_factory:
2694 case MethodRecognizer::kTypedData_Int64ArrayView_factory:
2695 case MethodRecognizer::kTypedData_Uint64ArrayView_factory:
2696 case MethodRecognizer::kTypedData_Float32ArrayView_factory:
2697 case MethodRecognizer::kTypedData_Float64ArrayView_factory:
2698 case MethodRecognizer::kTypedData_Float32x4ArrayView_factory:
2699 case MethodRecognizer::kTypedData_Int32x4ArrayView_factory:
2700 case MethodRecognizer::kTypedData_Float64x2ArrayView_factory:
2701 return true;
2702 default:
2703 return false;
2704 }
2705}
Dart_NativeFunction function
Definition: fuchsia.cc:51

◆ IsUnmodifiableTypedDataViewFactory()

bool dart::LoadFieldInstr::IsUnmodifiableTypedDataViewFactory ( const Function function)
static

Definition at line 2707 of file il.cc.

2708 {
2709 auto kind = function.recognized_kind();
2710 switch (kind) {
2711 case MethodRecognizer::kTypedData_UnmodifiableByteDataView_factory:
2712 case MethodRecognizer::kTypedData_UnmodifiableInt8ArrayView_factory:
2713 case MethodRecognizer::kTypedData_UnmodifiableUint8ArrayView_factory:
2714 case MethodRecognizer::kTypedData_UnmodifiableUint8ClampedArrayView_factory:
2715 case MethodRecognizer::kTypedData_UnmodifiableInt16ArrayView_factory:
2716 case MethodRecognizer::kTypedData_UnmodifiableUint16ArrayView_factory:
2717 case MethodRecognizer::kTypedData_UnmodifiableInt32ArrayView_factory:
2718 case MethodRecognizer::kTypedData_UnmodifiableUint32ArrayView_factory:
2719 case MethodRecognizer::kTypedData_UnmodifiableInt64ArrayView_factory:
2720 case MethodRecognizer::kTypedData_UnmodifiableUint64ArrayView_factory:
2721 case MethodRecognizer::kTypedData_UnmodifiableFloat32ArrayView_factory:
2722 case MethodRecognizer::kTypedData_UnmodifiableFloat64ArrayView_factory:
2723 case MethodRecognizer::kTypedData_UnmodifiableFloat32x4ArrayView_factory:
2724 case MethodRecognizer::kTypedData_UnmodifiableInt32x4ArrayView_factory:
2725 case MethodRecognizer::kTypedData_UnmodifiableFloat64x2ArrayView_factory:
2726 return true;
2727 default:
2728 return false;
2729 }
2730}

◆ loads_inner_pointer()

InnerPointerAccess dart::LoadFieldInstr::loads_inner_pointer ( ) const
inline

Definition at line 8146 of file il.h.

8146 {
8147 return loads_inner_pointer_;
8148 }

◆ MayCreateUnsafeUntaggedPointer()

bool dart::LoadFieldInstr::MayCreateUnsafeUntaggedPointer ( ) const
virtual

Definition at line 2851 of file il.cc.

2851 {
2853 // The load is guaranteed to never retrieve a GC-moveable address.
2854 return false;
2855 }
2856 if (slot().IsIdentical(Slot::PointerBase_data())) {
2857 // If we know statically that the instance is an external array, then
2858 // the load retrieves a pointer to external memory.
2859 return !IsExternalPayloadClassId(instance()->Type()->ToNullableCid());
2860 }
2861 return true;
2862}
Type
Definition: SortBench.cpp:56
bool IsExternalPayloadClassId(classid_t cid)
Definition: class_id.h:472

◆ MayCreateUntaggedAlias()

bool dart::LoadFieldInstr::MayCreateUntaggedAlias ( ) const

Definition at line 2835 of file il.cc.

2835 {
2837 // If the load is guaranteed to never retrieve a GC-moveable address,
2838 // then the returned address can't alias the (GC-moveable) instance.
2839 return false;
2840 }
2841 if (slot().IsIdentical(Slot::PointerBase_data())) {
2842 // If we know statically that the instance is a typed data view, then the
2843 // data field doesn't alias the instance (but some other typed data object).
2844 const intptr_t cid = instance()->Type()->ToNullableCid();
2845 if (IsUnmodifiableTypedDataViewClassId(cid)) return false;
2846 if (IsTypedDataViewClassId(cid)) return false;
2847 }
2848 return true;
2849}
virtual bool MayCreateUnsafeUntaggedPointer() const
Definition: il.cc:2851
bool IsTypedDataViewClassId(intptr_t index)
Definition: class_id.h:439
bool IsUnmodifiableTypedDataViewClassId(intptr_t index)
Definition: class_id.h:453

◆ representation()

Representation dart::LoadFieldInstr::representation ( ) const
virtual

Reimplemented from dart::Instruction.

Definition at line 921 of file il.cc.

921 {
922 return slot().representation();
923}

◆ RequiredInputRepresentation()

virtual Representation dart::LoadFieldInstr::RequiredInputRepresentation ( intptr_t  idx) const
inlinevirtual

Reimplemented from dart::Instruction.

Definition at line 8157 of file il.h.

8157 {
8158 ASSERT_EQUAL(idx, 0);
8159 return slot_.has_untagged_instance() ? kUntagged : kTagged;
8160 }
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309

◆ set_loads_inner_pointer()

void dart::LoadFieldInstr::set_loads_inner_pointer ( InnerPointerAccess  value)
inline

Definition at line 8149 of file il.h.

8149 {
8150 // We should never change this for a non-untagged field.
8151 ASSERT(loads_inner_pointer_ != InnerPointerAccess::kNotUntagged);
8152 // We only convert from may to cannot, never the other direction.
8154 loads_inner_pointer_ = value;
8155 }
uint8_t value

◆ slot()

const Slot & dart::LoadFieldInstr::slot ( ) const
inline

Definition at line 8144 of file il.h.

8144{ return slot_; }

◆ TryEvaluateLoad() [1/2]

bool dart::LoadFieldInstr::TryEvaluateLoad ( const Object instance,
const Field field,
Object result 
)
static

Definition at line 2812 of file il.cc.

2814 {
2815 if (!field.is_final() || !instance.IsInstance()) {
2816 return false;
2817 }
2818
2819 // Check that instance really has the field which we
2820 // are trying to load from.
2821 Class& cls = Class::Handle(instance.clazz());
2822 while (cls.ptr() != Class::null() && cls.ptr() != field.Owner()) {
2823 cls = cls.SuperClass();
2824 }
2825 if (cls.ptr() != field.Owner()) {
2826 // Failed to find the field in class or its superclasses.
2827 return false;
2828 }
2829
2830 // Object has the field: execute the load.
2831 *result = Instance::Cast(instance).GetField(field);
2832 return true;
2833}
static ObjectPtr null()
Definition: object.h:433

◆ TryEvaluateLoad() [2/2]

bool dart::LoadFieldInstr::TryEvaluateLoad ( const Object instance,
const Slot field,
Object result 
)
static

Definition at line 2736 of file il.cc.

2738 {
2739 switch (field.kind()) {
2741 return TryEvaluateLoad(instance, field.field(), result);
2742
2743 case Slot::Kind::kArgumentsDescriptor_type_args_len:
2744 if (instance.IsArray() && Array::Cast(instance).IsImmutable()) {
2745 ArgumentsDescriptor desc(Array::Cast(instance));
2746 *result = Smi::New(desc.TypeArgsLen());
2747 return true;
2748 }
2749 return false;
2750
2751 case Slot::Kind::kArgumentsDescriptor_count:
2752 if (instance.IsArray() && Array::Cast(instance).IsImmutable()) {
2753 ArgumentsDescriptor desc(Array::Cast(instance));
2754 *result = Smi::New(desc.Count());
2755 return true;
2756 }
2757 return false;
2758
2759 case Slot::Kind::kArgumentsDescriptor_positional_count:
2760 if (instance.IsArray() && Array::Cast(instance).IsImmutable()) {
2761 ArgumentsDescriptor desc(Array::Cast(instance));
2762 *result = Smi::New(desc.PositionalCount());
2763 return true;
2764 }
2765 return false;
2766
2767 case Slot::Kind::kArgumentsDescriptor_size:
2768 // If a constant arguments descriptor appears, then either it is from
2769 // a invocation dispatcher (which always has tagged arguments and so
2770 // [host]Size() == [target]Size() == Count()) or the constant should
2771 // have the correct Size() in terms of the target architecture if any
2772 // spill slots are involved.
2773 if (instance.IsArray() && Array::Cast(instance).IsImmutable()) {
2774 ArgumentsDescriptor desc(Array::Cast(instance));
2775 *result = Smi::New(desc.Size());
2776 return true;
2777 }
2778 return false;
2779
2780 case Slot::Kind::kTypeArguments_length:
2781 if (instance.IsTypeArguments()) {
2782 *result = Smi::New(TypeArguments::Cast(instance).Length());
2783 return true;
2784 }
2785 return false;
2786
2787 case Slot::Kind::kRecord_shape:
2788 if (instance.IsRecord()) {
2789 *result = Record::Cast(instance).shape().AsSmi();
2790 return true;
2791 }
2792 return false;
2793
2795 if (instance.IsRecord()) {
2797 field.offset_in_bytes());
2798 const Record& record = Record::Cast(instance);
2799 if (index < record.num_fields()) {
2800 *result = record.FieldAt(index);
2801 }
2802 return true;
2803 }
2804 return false;
2805
2806 default:
2807 break;
2808 }
2809 return false;
2810}

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