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

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

Static Public Member Functions

static bool IsArrayTypeSupported (classid_t array_cid)
 

Additional Inherited Members

- Protected Attributes inherited from dart::TemplateInstruction< 5, NoThrow >
EmbeddedArray< Value *, Ninputs_
 

Detailed Description

Definition at line 3128 of file il.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
kSrcPos 
kDestPos 
kSrcStartPos 
kDestStartPos 
kLengthPos 

Definition at line 3155 of file il.h.

3155 {
3156 kSrcPos = 0,
3157 kDestPos = 1,
3158 kSrcStartPos = 2,
3159 kDestStartPos = 3,
3160 kLengthPos = 4
3161 };

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

3139 : src_cid_(src_cid),
3140 dest_cid_(dest_cid),
3141 element_size_(Instance::ElementSizeFor(src_cid)),
3142 unboxed_inputs_(unboxed_inputs),
3143 can_overlap_(can_overlap) {
3148 SetInputAt(kSrcPos, src);
3149 SetInputAt(kDestPos, dest);
3150 SetInputAt(kSrcStartPos, src_start);
3151 SetInputAt(kDestStartPos, dest_start);
3152 SetInputAt(kLengthPos, length);
3153 }
#define ASSERT_EQUAL(expected, actual)
Definition assert.h:309
static intptr_t ElementSizeFor(intptr_t cid)
Definition object.cc:21008
Value * length() const
Definition il.h:3193
bool unboxed_inputs() const
Definition il.h:3198
Value * dest() const
Definition il.h:3190
classid_t src_cid() const
Definition il.h:3195
classid_t dest_cid() const
Definition il.h:3196
Value * src_start() const
Definition il.h:3191
bool can_overlap() const
Definition il.h:3199
Value * src() const
Definition il.h:3189
static bool IsArrayTypeSupported(classid_t array_cid)
Definition il.h:3265
Value * dest_start() const
Definition il.h:3192
#define ASSERT(E)

Member Function Documentation

◆ AttributesEqual()

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

Definition at line 3177 of file il.h.

3177 {
3178 if (auto* const copy = other.AsMemoryCopy()) {
3179 if (element_size_ != copy->element_size_) return false;
3180 if (unboxed_inputs_ != copy->unboxed_inputs_) return false;
3181 if (can_overlap_ != copy->can_overlap_) return false;
3182 if (src_cid_ != copy->src_cid_) return false;
3183 if (dest_cid_ != copy->dest_cid_) return false;
3184 return true;
3185 }
3186 return false;
3187 }
Definition copy.py:1

◆ can_overlap()

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

Definition at line 3199 of file il.h.

3199{ return can_overlap_; }

◆ Canonicalize()

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

Definition at line 6961 of file il.cc.

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

◆ ComputeCanDeoptimize()

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

Definition at line 3174 of file il.h.

3174{ return false; }

◆ DECLARE_ATTRIBUTE()

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

◆ dest()

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

Definition at line 3190 of file il.h.

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

◆ dest_cid()

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

Definition at line 3196 of file il.h.

3196{ return dest_cid_; }

◆ dest_start()

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

Definition at line 3192 of file il.h.

3192{ 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 3197 of file il.h.

3197{ 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 7110 of file il.cc.

7114 {
7115 ASSERT(element_size_ <= 16);
7116 const intptr_t num_bytes = num_elements * element_size_;
7117#if defined(TARGET_ARCH_ARM64)
7118 // We use LDP/STP with TMP/TMP2 to handle 16-byte moves.
7119 const intptr_t mov_size = element_size_;
7120#else
7121 const intptr_t mov_size =
7122 Utils::Minimum<intptr_t>(element_size_, compiler::target::kWordSize);
7123#endif
7124 const intptr_t mov_repeat = num_bytes / mov_size;
7125 ASSERT(num_bytes % mov_size == 0);
7126
7127#if defined(TARGET_ARCH_IA32)
7128 // No TMP on IA32, so we have to allocate one instead.
7129 const Register temp_reg = locs()->temp(0).reg();
7130#else
7131 const Register temp_reg = TMP;
7132#endif
7133 for (intptr_t i = 0; i < mov_repeat; i++) {
7134 const intptr_t offset = (reversed ? (mov_repeat - (i + 1)) : i) * mov_size;
7135 switch (mov_size) {
7136 case 1:
7137 __ LoadFromOffset(temp_reg, src_reg, offset, compiler::kUnsignedByte);
7138 __ StoreToOffset(temp_reg, dest_reg, offset, compiler::kUnsignedByte);
7139 break;
7140 case 2:
7141 __ LoadFromOffset(temp_reg, src_reg, offset,
7143 __ StoreToOffset(temp_reg, dest_reg, offset,
7145 break;
7146 case 4:
7147 __ LoadFromOffset(temp_reg, src_reg, offset,
7149 __ StoreToOffset(temp_reg, dest_reg, offset,
7151 break;
7152 case 8:
7153#if defined(TARGET_ARCH_IS_64_BIT)
7154 __ LoadFromOffset(temp_reg, src_reg, offset, compiler::kEightBytes);
7155 __ StoreToOffset(temp_reg, dest_reg, offset, compiler::kEightBytes);
7156#else
7157 UNREACHABLE();
7158#endif
7159 break;
7160 case 16: {
7161#if defined(TARGET_ARCH_ARM64)
7162 __ ldp(
7163 TMP, TMP2,
7164 compiler::Address(src_reg, offset, compiler::Address::PairOffset));
7165 __ stp(
7166 TMP, TMP2,
7167 compiler::Address(dest_reg, offset, compiler::Address::PairOffset));
7168#else
7169 UNREACHABLE();
7170#endif
7171 break;
7172 }
7173 default:
7174 UNREACHABLE();
7175 }
7176 }
7177
7178#if defined(USING_MEMORY_SANITIZER) && defined(TARGET_ARCH_X64)
7179 RegisterSet kVolatileRegisterSet(CallingConventions::kVolatileCpuRegisters,
7181 __ PushRegisters(kVolatileRegisterSet);
7182 __ MsanUnpoison(dest_reg, num_bytes);
7183 __ PopRegisters(kVolatileRegisterSet);
7184#endif
7185}
#define __
#define UNREACHABLE()
Definition assert.h:248
static constexpr RegList kVolatileXmmRegisters
static constexpr intptr_t kVolatileCpuRegisters
const Register TMP2
const Register TMP
Point offset

◆ HasUnknownSideEffects()

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

Definition at line 3175 of file il.h.

3175{ return true; }

◆ IsArrayTypeSupported()

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

Definition at line 3265 of file il.h.

3265 {
3266 // We don't handle clamping negative values in this instruction, instead
3267 // those are handled via a native call.
3268 if (IsClampedTypedDataBaseClassId(array_cid)) return false;
3269 // We don't support the following cids for the given reasons:
3270 // * kStringCid: doesn't give element size information or information
3271 // about how the payload address is calculated.
3272 // * kPointerCid: doesn't give element size or signedness information.
3273 if (array_cid == kPointerCid || array_cid == kStringCid) return false;
3274 return IsTypedDataBaseClassId(array_cid) || IsStringClassId(array_cid);
3275 }
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 3193 of file il.h.

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

Definition at line 3165 of file il.h.

3165 {
3166 if (index == kSrcPos || index == kDestPos) {
3167 // Can be either tagged or untagged.
3168 return kNoRepresentation;
3169 }
3170 ASSERT(index <= kLengthPos);
3171 return unboxed_inputs() ? kUnboxedIntPtr : kTagged;
3172 }
static constexpr Representation kUnboxedIntPtr
Definition locations.h:176

◆ src()

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

Definition at line 3189 of file il.h.

3189{ return inputs_[kSrcPos]; }

◆ src_cid()

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

Definition at line 3195 of file il.h.

3195{ return src_cid_; }

◆ src_start()

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

Definition at line 3191 of file il.h.

3191{ return inputs_[kSrcStartPos]; }

◆ unboxed_inputs()

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

Definition at line 3198 of file il.h.

3198{ return unboxed_inputs_; }

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