Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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 >

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 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
 

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)
 

Additional Inherited Members

- Public Types inherited from dart::TemplateDefinition< N, Throws >
using BaseClass = typename NoCSE< Definition, PureDefinition >::Base
 
- Protected Attributes inherited from dart::TemplateDefinition< N, Throws >
EmbeddedArray< Value *, Ninputs_
 

Detailed Description

Definition at line 8053 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 8055 of file il.h.

8063 deopt_id,
8064 slot.IsDartField() ? &slot.field() : nullptr),
8065 slot_(slot),
8066 loads_inner_pointer_(loads_inner_pointer) {
8067 switch (loads_inner_pointer) {
8069 ASSERT(slot.representation() != kUntagged);
8070 break;
8072 ASSERT(slot.representation() == kUntagged);
8074 break;
8076 ASSERT(slot.representation() == kUntagged);
8077 break;
8078 }
8079 SetInputAt(0, instance);
8080 }
const Slot & slot() const
Definition il.h:8096
InnerPointerAccess loads_inner_pointer() const
Definition il.h:8098
Value * instance() const
Definition il.h:8095
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:6579
TemplateLoadField(const InstructionSource &source, bool calls_initializer=false, intptr_t deopt_id=DeoptId::kNone, const Field *field=nullptr)
Definition il.h:6565
#define ASSERT(E)
SkBitmap source
Definition examples.cpp:28

◆ 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 8083 of file il.h.

8089 slot,
8091 source,
8093 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:8055

Member Function Documentation

◆ AllowsCSE()

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

Definition at line 8162 of file il.h.

8162{ return slot_.is_immutable(); }

◆ AttributesEqual()

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

Definition at line 1119 of file il.cc.

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

◆ Canonicalize()

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

Definition at line 2859 of file il.cc.

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

◆ CanTriggerGC()

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

Reimplemented from dart::TemplateLoadField< 1 >.

Definition at line 8164 of file il.h.

8164{ return calls_initializer(); }

◆ ComputeType()

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

Definition at line 1709 of file type_propagator.cc.

1709 {
1710 if (slot().IsRecordField()) {
1711 const intptr_t index = compiler::target::Record::field_index_at_offset(
1712 slot().offset_in_bytes());
1713 if (auto* alloc = instance()->definition()->AsAllocateSmallRecord()) {
1714 if (index < alloc->num_fields()) {
1715 return *(alloc->InputAt(index)->Type());
1716 }
1717 }
1718 const AbstractType* instance_type = instance()->Type()->ToAbstractType();
1719 if (instance_type->IsRecordType()) {
1720 const auto& record_type = RecordType::Cast(*instance_type);
1721 if (index < record_type.NumFields()) {
1722 const auto& field_type =
1723 AbstractType::ZoneHandle(record_type.FieldTypeAt(index));
1724 return CompileType::FromAbstractType(field_type,
1727 }
1728 }
1729 }
1730 CompileType type = slot().type();
1731 if (calls_initializer()) {
1733 }
1734 TraceStrongModeType(this, &type);
1735 return type;
1736}
static constexpr bool kCannotBeSentinel
static constexpr bool kCanBeNull
CompileType CopyNonSentinel()
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 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 2855 of file il.cc.

2855 {
2856 return TryEvaluateLoad(instance, slot(), result);
2857}
static bool TryEvaluateLoad(const Object &instance, const Field &field, Object *result)
Definition il.cc:2803

◆ 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(
2834 RangeBoundary::FromConstant(compiler::target::Array::kMaxElements));
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),
2850 compiler::target::TypeArguments::kMaxElements));
2851 break;
2852
2853 case Slot::Kind::kRecord_shape:
2855 break;
2856
2857 case Slot::Kind::kString_length:
2858 *range = Range(
2860 RangeBoundary::FromConstant(compiler::target::String::kMaxElements));
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:919
static RangeBoundary MaxSmi()
static RangeBoundary MinSmi()
static RangeBoundary FromConstant(int64_t val)
static Range Full(RangeBoundary::RangeSize size)
#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 8095 of file il.h.

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

◆ IsFixedLengthArrayCid()

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

Definition at line 2659 of file il.cc.

2659 {
2661 return true;
2662 }
2663
2664 switch (cid) {
2665 case kArrayCid:
2666 case kImmutableArrayCid:
2667 case kTypeArgumentsCid:
2668 return true;
2669 default:
2670 return false;
2671 }
2672}
bool IsTypedDataBaseClassId(intptr_t index)
Definition class_id.h:429

◆ IsImmutableLengthLoad()

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

Definition at line 8139 of file il.h.

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

◆ IsImmutableLoad()

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

Definition at line 8129 of file il.h.

8129 {
8130 // The data() field in PointerBase is marked mutable, but is not actually
8131 // mutable if it doesn't contain an inner pointer (e.g., for external
8132 // typed data and Pointer objects).
8133 if (slot().IsIdentical(Slot::PointerBase_data())) {
8135 }
8136 return slot().is_immutable();
8137 }
bool is_immutable() const
Definition slot.h:521

◆ IsTypedDataViewFactory()

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

Definition at line 2674 of file il.cc.

2674 {
2675 auto kind = function.recognized_kind();
2676 switch (kind) {
2677 case MethodRecognizer::kTypedData_ByteDataView_factory:
2678 case MethodRecognizer::kTypedData_Int8ArrayView_factory:
2679 case MethodRecognizer::kTypedData_Uint8ArrayView_factory:
2680 case MethodRecognizer::kTypedData_Uint8ClampedArrayView_factory:
2681 case MethodRecognizer::kTypedData_Int16ArrayView_factory:
2682 case MethodRecognizer::kTypedData_Uint16ArrayView_factory:
2683 case MethodRecognizer::kTypedData_Int32ArrayView_factory:
2684 case MethodRecognizer::kTypedData_Uint32ArrayView_factory:
2685 case MethodRecognizer::kTypedData_Int64ArrayView_factory:
2686 case MethodRecognizer::kTypedData_Uint64ArrayView_factory:
2687 case MethodRecognizer::kTypedData_Float32ArrayView_factory:
2688 case MethodRecognizer::kTypedData_Float64ArrayView_factory:
2689 case MethodRecognizer::kTypedData_Float32x4ArrayView_factory:
2690 case MethodRecognizer::kTypedData_Int32x4ArrayView_factory:
2691 case MethodRecognizer::kTypedData_Float64x2ArrayView_factory:
2692 return true;
2693 default:
2694 return false;
2695 }
2696}
Dart_NativeFunction function
Definition fuchsia.cc:51

◆ IsUnmodifiableTypedDataViewFactory()

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

Definition at line 2698 of file il.cc.

2699 {
2700 auto kind = function.recognized_kind();
2701 switch (kind) {
2702 case MethodRecognizer::kTypedData_UnmodifiableByteDataView_factory:
2703 case MethodRecognizer::kTypedData_UnmodifiableInt8ArrayView_factory:
2704 case MethodRecognizer::kTypedData_UnmodifiableUint8ArrayView_factory:
2705 case MethodRecognizer::kTypedData_UnmodifiableUint8ClampedArrayView_factory:
2706 case MethodRecognizer::kTypedData_UnmodifiableInt16ArrayView_factory:
2707 case MethodRecognizer::kTypedData_UnmodifiableUint16ArrayView_factory:
2708 case MethodRecognizer::kTypedData_UnmodifiableInt32ArrayView_factory:
2709 case MethodRecognizer::kTypedData_UnmodifiableUint32ArrayView_factory:
2710 case MethodRecognizer::kTypedData_UnmodifiableInt64ArrayView_factory:
2711 case MethodRecognizer::kTypedData_UnmodifiableUint64ArrayView_factory:
2712 case MethodRecognizer::kTypedData_UnmodifiableFloat32ArrayView_factory:
2713 case MethodRecognizer::kTypedData_UnmodifiableFloat64ArrayView_factory:
2714 case MethodRecognizer::kTypedData_UnmodifiableFloat32x4ArrayView_factory:
2715 case MethodRecognizer::kTypedData_UnmodifiableInt32x4ArrayView_factory:
2716 case MethodRecognizer::kTypedData_UnmodifiableFloat64x2ArrayView_factory:
2717 return true;
2718 default:
2719 return false;
2720 }
2721}

◆ loads_inner_pointer()

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

Definition at line 8098 of file il.h.

8098 {
8099 return loads_inner_pointer_;
8100 }

◆ MayCreateUnsafeUntaggedPointer()

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

Definition at line 2842 of file il.cc.

2842 {
2844 // The load is guaranteed to never retrieve a GC-moveable address.
2845 return false;
2846 }
2847 if (slot().IsIdentical(Slot::PointerBase_data())) {
2848 // If we know statically that the instance is an external array, then
2849 // the load retrieves a pointer to external memory.
2850 return !IsExternalPayloadClassId(instance()->Type()->ToNullableCid());
2851 }
2852 return true;
2853}
bool IsExternalPayloadClassId(classid_t cid)
Definition class_id.h:472

◆ MayCreateUntaggedAlias()

bool dart::LoadFieldInstr::MayCreateUntaggedAlias ( ) const

Definition at line 2826 of file il.cc.

2826 {
2828 // If the load is guaranteed to never retrieve a GC-moveable address,
2829 // then the returned address can't alias the (GC-moveable) instance.
2830 return false;
2831 }
2832 if (slot().IsIdentical(Slot::PointerBase_data())) {
2833 // If we know statically that the instance is a typed data view, then the
2834 // data field doesn't alias the instance (but some other typed data object).
2835 const intptr_t cid = instance()->Type()->ToNullableCid();
2836 if (IsUnmodifiableTypedDataViewClassId(cid)) return false;
2837 if (IsTypedDataViewClassId(cid)) return false;
2838 }
2839 return true;
2840}
virtual bool MayCreateUnsafeUntaggedPointer() const
Definition il.cc:2842
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

Definition at line 919 of file il.cc.

919 {
920 return slot().representation();
921}

◆ RequiredInputRepresentation()

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

Definition at line 8109 of file il.h.

8109 {
8110 ASSERT_EQUAL(idx, 0);
8111 return slot_.has_untagged_instance() ? kUntagged : kTagged;
8112 }
#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 8101 of file il.h.

8101 {
8102 // We should never change this for a non-untagged field.
8103 ASSERT(loads_inner_pointer_ != InnerPointerAccess::kNotUntagged);
8104 // We only convert from may to cannot, never the other direction.
8106 loads_inner_pointer_ = value;
8107 }
uint8_t value

◆ slot()

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

Definition at line 8096 of file il.h.

8096{ return slot_; }

◆ TryEvaluateLoad() [1/2]

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

Definition at line 2803 of file il.cc.

2805 {
2806 if (!field.is_final() || !instance.IsInstance()) {
2807 return false;
2808 }
2809
2810 // Check that instance really has the field which we
2811 // are trying to load from.
2812 Class& cls = Class::Handle(instance.clazz());
2813 while (cls.ptr() != Class::null() && cls.ptr() != field.Owner()) {
2814 cls = cls.SuperClass();
2815 }
2816 if (cls.ptr() != field.Owner()) {
2817 // Failed to find the field in class or its superclasses.
2818 return false;
2819 }
2820
2821 // Object has the field: execute the load.
2822 *result = Instance::Cast(instance).GetField(field);
2823 return true;
2824}
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 2727 of file il.cc.

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

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