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

#include <il.h>

Inheritance diagram for dart::MemoryCopyInstr:
dart::TemplateInstruction< 5, NoThrow > dart::Instruction dart::ZoneAllocated

Public Types

enum  {
  kSrcPos = 0 , kDestPos = 1 , kSrcStartPos = 2 , kDestStartPos = 3 ,
  kLengthPos = 4
}
 
- Public Types inherited from dart::TemplateInstruction< 5, NoThrow >
using BaseClass = typename NoCSE< Instruction, PureInstruction >::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 >
 

Public Member Functions

 MemoryCopyInstr (Value *src, classid_t src_cid, Value *dest, classid_t dest_cid, Value *src_start, Value *dest_start, Value *length, bool unboxed_inputs, bool can_overlap=true)
 
virtual Representation RequiredInputRepresentation (intptr_t index) const
 
virtual bool ComputeCanDeoptimize () const
 
virtual bool HasUnknownSideEffects () const
 
virtual bool AttributesEqual (const Instruction &other) const
 
Valuesrc () const
 
Valuedest () const
 
Valuesrc_start () const
 
Valuedest_start () const
 
Valuelength () const
 
classid_t src_cid () const
 
classid_t dest_cid () const
 
intptr_t element_size () const
 
bool unboxed_inputs () const
 
bool can_overlap () const
 
virtual InstructionCanonicalize (FlowGraph *flow_graph)
 
PRINT_OPERANDS_TO_SUPPORT DECLARE_ATTRIBUTE (element_size())
 
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(MemoryCopyInstr, TemplateInstruction, FIELD_LIST) private void EmitUnrolledCopy (FlowGraphCompiler *compiler, Register dest_reg, Register src_reg, intptr_t num_elements, bool reversed)
 
void PrepareLengthRegForLoop (FlowGraphCompiler *compiler, Register length_reg, compiler::Label *done)
 
void EmitLoopCopy (FlowGraphCompiler *compiler, Register dest_reg, Register src_reg, Register length_reg, compiler::Label *done, compiler::Label *copy_forwards=nullptr)
 
 DISALLOW_COPY_AND_ASSIGN (MemoryCopyInstr)
 
- Public Member Functions inherited from dart::TemplateInstruction< 5, NoThrow >
 TemplateInstruction (intptr_t deopt_id=DeoptId::kNone)
 
 TemplateInstruction (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 IsArrayTypeSupported (classid_t array_cid)
 
- 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

- 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::TemplateInstruction< 5, NoThrow >
EmbeddedArray< Value *, Ninputs_
 

Detailed Description

Definition at line 3146 of file il.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
kSrcPos 
kDestPos 
kSrcStartPos 
kDestStartPos 
kLengthPos 

Definition at line 3173 of file il.h.

3173 {
3174 kSrcPos = 0,
3175 kDestPos = 1,
3176 kSrcStartPos = 2,
3177 kDestStartPos = 3,
3178 kLengthPos = 4
3179 };

Constructor & Destructor Documentation

◆ MemoryCopyInstr()

dart::MemoryCopyInstr::MemoryCopyInstr ( Value src,
classid_t  src_cid,
Value dest,
classid_t  dest_cid,
Value src_start,
Value dest_start,
Value length,
bool  unboxed_inputs,
bool  can_overlap = true 
)
inline

Definition at line 3148 of file il.h.

3157 : src_cid_(src_cid),
3158 dest_cid_(dest_cid),
3159 element_size_(Instance::ElementSizeFor(src_cid)),
3160 unboxed_inputs_(unboxed_inputs),
3161 can_overlap_(can_overlap) {
3171 }
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309
static intptr_t ElementSizeFor(intptr_t cid)
Definition: object.cc:20967
void SetInputAt(intptr_t i, Value *value)
Definition: il.h:1014
Value * length() const
Definition: il.h:3211
bool unboxed_inputs() const
Definition: il.h:3216
Value * dest() const
Definition: il.h:3208
classid_t src_cid() const
Definition: il.h:3213
classid_t dest_cid() const
Definition: il.h:3214
Value * src_start() const
Definition: il.h:3209
bool can_overlap() const
Definition: il.h:3217
Value * src() const
Definition: il.h:3207
static bool IsArrayTypeSupported(classid_t array_cid)
Definition: il.h:3283
Value * dest_start() const
Definition: il.h:3210
#define ASSERT(E)

Member Function Documentation

◆ AttributesEqual()

virtual bool dart::MemoryCopyInstr::AttributesEqual ( const Instruction other) const
inlinevirtual

Reimplemented from dart::Instruction.

Definition at line 3195 of file il.h.

3195 {
3196 if (auto* const copy = other.AsMemoryCopy()) {
3197 if (element_size_ != copy->element_size_) return false;
3198 if (unboxed_inputs_ != copy->unboxed_inputs_) return false;
3199 if (can_overlap_ != copy->can_overlap_) return false;
3200 if (src_cid_ != copy->src_cid_) return false;
3201 if (dest_cid_ != copy->dest_cid_) return false;
3202 return true;
3203 }
3204 return false;
3205 }
Definition: copy.py:1

◆ can_overlap()

bool dart::MemoryCopyInstr::can_overlap ( ) const
inline

Definition at line 3217 of file il.h.

3217{ return can_overlap_; }

◆ Canonicalize()

Instruction * dart::MemoryCopyInstr::Canonicalize ( FlowGraph flow_graph)
virtual

Reimplemented from dart::Instruction.

Definition at line 6954 of file il.cc.

6954 {
6955 flow_graph->ExtractExternalUntaggedPayload(this, src(), src_cid_);
6956 flow_graph->ExtractExternalUntaggedPayload(this, dest(), dest_cid_);
6957
6958 if (!length()->BindsToSmiConstant()) {
6959 return this;
6960 } else if (length()->BoundSmiConstant() == 0) {
6961 // Nothing to copy.
6962 return nullptr;
6963 }
6964
6965 if (!src_start()->BindsToSmiConstant() ||
6966 !dest_start()->BindsToSmiConstant()) {
6967 // TODO(https://dartbug.com/51031): Consider adding support for src/dest
6968 // starts to be in bytes rather than element size.
6969 return this;
6970 }
6971
6972 intptr_t new_length = length()->BoundSmiConstant();
6973 intptr_t new_src_start = src_start()->BoundSmiConstant();
6974 intptr_t new_dest_start = dest_start()->BoundSmiConstant();
6975 intptr_t new_element_size = element_size_;
6976 while (((new_length | new_src_start | new_dest_start) & 1) == 0 &&
6977 new_element_size < kMaxElementSizeForEfficientCopy) {
6978 new_length >>= 1;
6979 new_src_start >>= 1;
6980 new_dest_start >>= 1;
6981 new_element_size <<= 1;
6982 }
6983 if (new_element_size == element_size_) {
6984 return this;
6985 }
6986
6987 // The new element size is larger than the original one, so it must be > 1.
6988 // That means unboxed integers will always require a shift, but Smis
6989 // may not if element_size == 2, so always use Smis.
6990 auto* const Z = flow_graph->zone();
6991 auto* const length_instr =
6992 flow_graph->GetConstant(Smi::ZoneHandle(Z, Smi::New(new_length)));
6993 auto* const src_start_instr =
6994 flow_graph->GetConstant(Smi::ZoneHandle(Z, Smi::New(new_src_start)));
6995 auto* const dest_start_instr =
6996 flow_graph->GetConstant(Smi::ZoneHandle(Z, Smi::New(new_dest_start)));
6997 length()->BindTo(length_instr);
6998 src_start()->BindTo(src_start_instr);
6999 dest_start()->BindTo(dest_start_instr);
7000 element_size_ = new_element_size;
7001 unboxed_inputs_ = false;
7002 return this;
7003}
static Object & ZoneHandle()
Definition: object.h:419
static SmiPtr New(intptr_t value)
Definition: object.h:10006
intptr_t BoundSmiConstant() const
Definition: il.cc:1212
void BindTo(Definition *definition)
Definition: il.h:2718
#define Z
Definition: il.cc:7430
static const intptr_t kMaxElementSizeForEfficientCopy
Definition: il.cc:6950

◆ ComputeCanDeoptimize()

virtual bool dart::MemoryCopyInstr::ComputeCanDeoptimize ( ) const
inlinevirtual

Implements dart::Instruction.

Definition at line 3192 of file il.h.

3192{ return false; }

◆ DECLARE_ATTRIBUTE()

PRINT_OPERANDS_TO_SUPPORT dart::MemoryCopyInstr::DECLARE_ATTRIBUTE ( element_size()  )

◆ dest()

Value * dart::MemoryCopyInstr::dest ( ) const
inline

Definition at line 3208 of file il.h.

3208{ return inputs_[kDestPos]; }
EmbeddedArray< Value *, N > inputs_
Definition: il.h:1522

◆ dest_cid()

classid_t dart::MemoryCopyInstr::dest_cid ( ) const
inline

Definition at line 3214 of file il.h.

3214{ return dest_cid_; }

◆ dest_start()

Value * dart::MemoryCopyInstr::dest_start ( ) const
inline

Definition at line 3210 of file il.h.

3210{ return inputs_[kDestStartPos]; }

◆ DISALLOW_COPY_AND_ASSIGN()

dart::MemoryCopyInstr::DISALLOW_COPY_AND_ASSIGN ( MemoryCopyInstr  )

◆ element_size()

intptr_t dart::MemoryCopyInstr::element_size ( ) const
inline

Definition at line 3215 of file il.h.

3215{ return element_size_; }

◆ EmitLoopCopy()

void dart::MemoryCopyInstr::EmitLoopCopy ( FlowGraphCompiler compiler,
Register  dest_reg,
Register  src_reg,
Register  length_reg,
compiler::Label done,
compiler::Label copy_forwards = nullptr 
)

◆ EmitUnrolledCopy()

void dart::MemoryCopyInstr::EmitUnrolledCopy ( FlowGraphCompiler compiler,
Register  dest_reg,
Register  src_reg,
intptr_t  num_elements,
bool  reversed 
)

Definition at line 7101 of file il.cc.

7105 {
7106 ASSERT(element_size_ <= 16);
7107 const intptr_t num_bytes = num_elements * element_size_;
7108#if defined(TARGET_ARCH_ARM64)
7109 // We use LDP/STP with TMP/TMP2 to handle 16-byte moves.
7110 const intptr_t mov_size = element_size_;
7111#else
7112 const intptr_t mov_size =
7113 Utils::Minimum<intptr_t>(element_size_, compiler::target::kWordSize);
7114#endif
7115 const intptr_t mov_repeat = num_bytes / mov_size;
7116 ASSERT(num_bytes % mov_size == 0);
7117
7118#if defined(TARGET_ARCH_IA32)
7119 // No TMP on IA32, so we have to allocate one instead.
7120 const Register temp_reg = locs()->temp(0).reg();
7121#else
7122 const Register temp_reg = TMP;
7123#endif
7124 for (intptr_t i = 0; i < mov_repeat; i++) {
7125 const intptr_t offset = (reversed ? (mov_repeat - (i + 1)) : i) * mov_size;
7126 switch (mov_size) {
7127 case 1:
7128 __ LoadFromOffset(temp_reg, src_reg, offset, compiler::kUnsignedByte);
7129 __ StoreToOffset(temp_reg, dest_reg, offset, compiler::kUnsignedByte);
7130 break;
7131 case 2:
7132 __ LoadFromOffset(temp_reg, src_reg, offset,
7134 __ StoreToOffset(temp_reg, dest_reg, offset,
7136 break;
7137 case 4:
7138 __ LoadFromOffset(temp_reg, src_reg, offset,
7140 __ StoreToOffset(temp_reg, dest_reg, offset,
7142 break;
7143 case 8:
7144#if defined(TARGET_ARCH_IS_64_BIT)
7145 __ LoadFromOffset(temp_reg, src_reg, offset, compiler::kEightBytes);
7146 __ StoreToOffset(temp_reg, dest_reg, offset, compiler::kEightBytes);
7147#else
7148 UNREACHABLE();
7149#endif
7150 break;
7151 case 16: {
7152#if defined(TARGET_ARCH_ARM64)
7153 __ ldp(
7154 TMP, TMP2,
7155 compiler::Address(src_reg, offset, compiler::Address::PairOffset));
7156 __ stp(
7157 TMP, TMP2,
7158 compiler::Address(dest_reg, offset, compiler::Address::PairOffset));
7159#else
7160 UNREACHABLE();
7161#endif
7162 break;
7163 }
7164 default:
7165 UNREACHABLE();
7166 }
7167 }
7168
7170#if defined(TARGET_ARCH_X64)
7171 RegisterSet kVolatileRegisterSet(CallingConventions::kVolatileCpuRegisters,
7173 __ PushRegisters(kVolatileRegisterSet);
7174 __ MsanUnpoison(dest_reg, num_bytes);
7175 __ PopRegisters(kVolatileRegisterSet);
7176#endif
7177 }
7178}
#define UNREACHABLE()
Definition: assert.h:248
static constexpr RegList kVolatileXmmRegisters
static constexpr intptr_t kVolatileCpuRegisters
LocationSummary * locs()
Definition: il.h:1192
Location temp(intptr_t index) const
Definition: locations.h:882
Register reg() const
Definition: locations.h:404
#define __
Definition: il.cc:4271
static constexpr intptr_t kWordSize
Definition: runtime_api.h:274
const Register TMP2
const Register TMP
constexpr bool FLAG_target_memory_sanitizer
Definition: flags.h:174
SeparatedVector2 offset

◆ HasUnknownSideEffects()

virtual bool dart::MemoryCopyInstr::HasUnknownSideEffects ( ) const
inlinevirtual

Implements dart::Instruction.

Definition at line 3193 of file il.h.

3193{ return true; }

◆ IsArrayTypeSupported()

static bool dart::MemoryCopyInstr::IsArrayTypeSupported ( classid_t  array_cid)
inlinestatic

Definition at line 3283 of file il.h.

3283 {
3284 // We don't handle clamping negative values in this instruction, instead
3285 // those are handled via a native call.
3286 if (IsClampedTypedDataBaseClassId(array_cid)) return false;
3287 // We don't support the following cids for the given reasons:
3288 // * kStringCid: doesn't give element size information or information
3289 // about how the payload address is calculated.
3290 // * kPointerCid: doesn't give element size or signedness information.
3291 if (array_cid == kPointerCid || array_cid == kStringCid) return false;
3292 return IsTypedDataBaseClassId(array_cid) || IsStringClassId(array_cid);
3293 }
bool IsTypedDataBaseClassId(intptr_t index)
Definition: class_id.h:429
bool IsClampedTypedDataBaseClassId(intptr_t index)
Definition: class_id.h:461
bool IsStringClassId(intptr_t index)
Definition: class_id.h:350

◆ length()

Value * dart::MemoryCopyInstr::length ( ) const
inline

Definition at line 3211 of file il.h.

3211{ return inputs_[kLengthPos]; }

◆ PrepareLengthRegForLoop()

void dart::MemoryCopyInstr::PrepareLengthRegForLoop ( FlowGraphCompiler compiler,
Register  length_reg,
compiler::Label done 
)

◆ RequiredInputRepresentation()

virtual Representation dart::MemoryCopyInstr::RequiredInputRepresentation ( intptr_t  index) const
inlinevirtual

Reimplemented from dart::Instruction.

Definition at line 3183 of file il.h.

3183 {
3184 if (index == kSrcPos || index == kDestPos) {
3185 // Can be either tagged or untagged.
3186 return kNoRepresentation;
3187 }
3188 ASSERT(index <= kLengthPos);
3189 return unboxed_inputs() ? kUnboxedIntPtr : kTagged;
3190 }
static constexpr Representation kUnboxedIntPtr
Definition: locations.h:176

◆ src()

Value * dart::MemoryCopyInstr::src ( ) const
inline

Definition at line 3207 of file il.h.

3207{ return inputs_[kSrcPos]; }

◆ src_cid()

classid_t dart::MemoryCopyInstr::src_cid ( ) const
inline

Definition at line 3213 of file il.h.

3213{ return src_cid_; }

◆ src_start()

Value * dart::MemoryCopyInstr::src_start ( ) const
inline

Definition at line 3209 of file il.h.

3209{ return inputs_[kSrcStartPos]; }

◆ unboxed_inputs()

bool dart::MemoryCopyInstr::unboxed_inputs ( ) const
inline

Definition at line 3216 of file il.h.

3216{ return unboxed_inputs_; }

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