17#ifdef DART_TARGET_OS_WINDOWS
29 return kTypedDataUint8ArrayCid;
31 return kTypedDataUint16ArrayCid;
33 return kTypedDataUint32ArrayCid;
35 return kTypedDataUint64ArrayCid;
37 return kTypedDataInt32x4ArrayCid;
49 const bool use_same_buffer = input ==
output;
52 if (!use_same_buffer) {
66 expect.LessThan<intptr_t>(0, elem_size);
68 expect.
Fail(
"Expected %" Pd " to be a power of two", elem_size);
70 expect.LessEqual<intptr_t>(0,
length);
71 expect.LessEqual<intptr_t>(0, dest_start);
72 expect.LessEqual<intptr_t>(dest_start +
length,
74 expect.LessEqual<intptr_t>(0, src_start);
76 const bool use_same_buffer = input ==
output;
77 const intptr_t dest_start_in_bytes = dest_start * elem_size;
78 const intptr_t dest_end_in_bytes = dest_start_in_bytes +
length * elem_size;
79 const intptr_t index_diff = dest_start_in_bytes - src_start * elem_size;
81 if (!use_same_buffer) {
83 const intptr_t got = input[
i];
84 if (expected != got) {
85 expect.
Fail(
"Unexpected change to input buffer at index %" Pd
86 ", expected %" Pd ", got %" Pd "",
90 const intptr_t unchanged =
93 if (dest_start_in_bytes <=
i &&
i < dest_end_in_bytes) {
96 if (expected != got) {
97 if (got == unchanged) {
98 expect.
Fail(
"No change to output buffer at index %" Pd
99 ", expected %" Pd ", got %" Pd "",
102 expect.
Fail(
"Incorrect change to output buffer at index %" Pd
103 ", expected %" Pd ", got %" Pd "",
109 if (got != unchanged) {
110 expect.
Fail(
"Unexpected change to input buffer at index %" Pd
111 ", expected %" Pd ", got %" Pd "",
119#define CHECK_DEFAULT_MEMORY(in, out) \
121 if (CheckMemory(dart::Expect(__FILE__, __LINE__), in, out, 0, 0, 0, 1)) { \
125#define CHECK_MEMORY(in, out, start, skip, len, size) \
127 if (CheckMemory(dart::Expect(__FILE__, __LINE__), in, out, start, skip, \
138 bool use_same_buffer) {
139 OS::Print(
"==================================================\n");
140 OS::Print(
"RunMemoryCopyInstrTest src_start %" Pd " dest_start %" Pd
142 "%" Pd "%s elem_size %" Pd "\n",
143 src_start, dest_start,
length, unboxed_inputs ?
" (unboxed)" :
"",
145 OS::Print(
"==================================================\n");
149 uint8_t* ptr2 = use_same_buffer
154 OS::Print(
"&ptr %p &ptr2 %p\n", ptr, ptr2);
161 final pointer = Pointer<Uint8>.fromAddress(%s%p);
162 final pointer2 = Pointer<Uint8>.fromAddress(%s%p);
166 void callNonConstCopy() {
167 final pointer = Pointer<Uint8>.fromAddress(%s%p);
168 final pointer2 = Pointer<Uint8>.fromAddress(%s%p);
169 final src_start = %)" Pd R"(;
170 final dest_start = %)" Pd R"(;
171 final length = %)" Pd R"(;
173 pointer, pointer2, src_start, dest_start, length);
178 void copyNonConst(Pointer<Uint8> ptr1,
185 src_start, dest_start, length));
192 Invoke(root_library,
"copyConst");
196 const auto& const_copy =
201 CompilerPass::kComputeSSA,
212 kMatchAndMoveRecordCoverage,
213 {kMatchAndMoveStaticCall, &pointer},
214 kMatchAndMoveRecordCoverage,
215 {kMatchAndMoveStaticCall, &pointer2},
216 kMatchAndMoveRecordCoverage,
217 {kMatchAndMoveStaticCall, &another_function_call},
224 auto*
const src_start_constant_instr = flow_graph->GetConstant(
227 auto*
const dest_start_constant_instr = flow_graph->GetConstant(
230 auto*
const length_constant_instr = flow_graph->GetConstant(
235 cid,
new (zone)
Value(src_start_constant_instr),
236 new (zone)
Value(dest_start_constant_instr),
237 new (zone)
Value(length_constant_instr), unboxed_inputs,
239 flow_graph->
InsertBefore(another_function_call, memory_copy_instr,
nullptr,
242 another_function_call->RemoveFromGraph();
246 ILMatcher cursor(flow_graph, flow_graph->graph_entry()->normal_entry());
249 kMatchAndMoveRecordCoverage,
250 kMatchAndMoveStaticCall,
251 kMatchAndMoveRecordCoverage,
252 kMatchAndMoveStaticCall,
253 kMatchAndMoveRecordCoverage,
254 kMatchAndMoveMemoryCopy,
259#if !defined(PRODUCT) && !defined(USING_THREAD_SANITIZER)
263 pipeline.RunForcedOptimizedAfterSSAPasses();
264 pipeline.CompileGraphAndAttachFunction();
269 ILMatcher cursor(flow_graph, flow_graph->graph_entry()->normal_entry());
273 {kMatchAndMoveMemoryCopy, &memory_copy},
275 EXPECT_EQ(kUntagged, memory_copy->src()->definition()->representation());
276 EXPECT_EQ(kUntagged, memory_copy->dest()->definition()->representation());
277 EXPECT(memory_copy->src_start()->BindsToConstant());
278 EXPECT(memory_copy->dest_start()->BindsToConstant());
279 EXPECT(memory_copy->length()->BindsToConstant());
283 Invoke(root_library,
"copyConst");
292 Invoke(root_library,
"callNonConstCopy");
296 const auto& copy_non_const =
297 Function::Handle(
GetFunction(root_library,
"copyNonConst"));
299 TestPipeline pipeline(copy_non_const, CompilerPass::kJIT);
300 FlowGraph* flow_graph = pipeline.RunPasses({
301 CompilerPass::kComputeSSA,
304 auto*
const entry_instr = flow_graph->graph_entry()->normal_entry();
305 auto*
const initial_defs = entry_instr->initial_definitions();
306 EXPECT(initial_defs !=
nullptr);
307 EXPECT_EQ(5, initial_defs->length());
309 auto*
const param_ptr = initial_defs->At(0)->AsParameter();
310 EXPECT(param_ptr !=
nullptr);
311 auto*
const param_ptr2 = initial_defs->At(1)->AsParameter();
312 EXPECT(param_ptr2 !=
nullptr);
313 auto*
const param_src_start = initial_defs->At(2)->AsParameter();
314 EXPECT(param_src_start !=
nullptr);
315 auto*
const param_dest_start = initial_defs->At(3)->AsParameter();
316 EXPECT(param_dest_start !=
nullptr);
317 auto*
const param_length = initial_defs->At(4)->AsParameter();
318 EXPECT(param_length !=
nullptr);
320 DartReturnInstr* return_instr;
322 ILMatcher cursor(flow_graph, entry_instr);
326 {kMatchDartReturn, &return_instr},
330 Zone*
const zone = Thread::Current()->zone();
332 Definition* src_start_def = param_src_start;
333 Definition* dest_start_def = param_dest_start;
334 Definition* length_def = param_length;
335 if (unboxed_inputs) {
341 flow_graph->InsertBefore(return_instr, length_def,
nullptr,
346 flow_graph->InsertBefore(length_def, dest_start_def,
nullptr,
351 flow_graph->InsertBefore(dest_start_def, src_start_def,
nullptr,
355 auto*
const memory_copy_instr =
new (zone) MemoryCopyInstr(
358 new (zone)
Value(src_start_def),
new (zone)
Value(dest_start_def),
359 new (zone)
Value(length_def),
361 unboxed_inputs, use_same_buffer);
362 flow_graph->InsertBefore(return_instr, memory_copy_instr,
nullptr,
367 ILMatcher cursor(flow_graph, flow_graph->graph_entry()->normal_entry());
368 if (unboxed_inputs) {
374 kMatchAndMoveMemoryCopy,
380 kMatchAndMoveMemoryCopy,
387#if !defined(PRODUCT) && !defined(USING_THREAD_SANITIZER)
388 SetFlagScope<bool> sfs(&FLAG_disassemble_optimized,
true);
391 pipeline.RunForcedOptimizedAfterSSAPasses();
392 pipeline.CompileGraphAndAttachFunction();
397 ILMatcher cursor(flow_graph, flow_graph->graph_entry()->normal_entry());
398 MemoryCopyInstr* memory_copy;
401 {kMatchAndMoveMemoryCopy, &memory_copy},
403 EXPECT_EQ(kUntagged, memory_copy->src()->definition()->representation());
404 EXPECT_EQ(kUntagged, memory_copy->dest()->definition()->representation());
405 EXPECT(!memory_copy->src_start()->BindsToConstant());
406 EXPECT(!memory_copy->dest_start()->BindsToConstant());
407 EXPECT(!memory_copy->length()->BindsToConstant());
411 Invoke(root_library,
"callNonConstCopy");
416 if (!use_same_buffer) {
421#define MEMORY_COPY_TEST_BOXED(src_start, dest_start, length, elem_size) \
422 ISOLATE_UNIT_TEST_CASE( \
423 IRTest_MemoryCopy_##src_start##_##dest_start##_##length##_##elem_size) { \
424 RunMemoryCopyInstrTest(src_start, dest_start, length, elem_size, false, \
428#define MEMORY_COPY_TEST_UNBOXED(src_start, dest_start, length, el_si) \
429 ISOLATE_UNIT_TEST_CASE( \
430 IRTest_MemoryCopy_##src_start##_##dest_start##_##length##_##el_si##_u) { \
431 RunMemoryCopyInstrTest(src_start, dest_start, length, el_si, true, false); \
434#define MEMORY_MOVE_TEST_BOXED(src_start, dest_start, length, elem_size) \
435 ISOLATE_UNIT_TEST_CASE( \
436 IRTest_MemoryMove_##src_start##_##dest_start##_##length##_##elem_size) { \
437 RunMemoryCopyInstrTest(src_start, dest_start, length, elem_size, false, \
441#define MEMORY_MOVE_TEST_UNBOXED(src_start, dest_start, length, el_si) \
442 ISOLATE_UNIT_TEST_CASE( \
443 IRTest_MemoryMove_##src_start##_##dest_start##_##length##_##el_si##_u) { \
444 RunMemoryCopyInstrTest(src_start, dest_start, length, el_si, true, true); \
447#define MEMORY_COPY_TEST(src_start, dest_start, length, elem_size) \
448 MEMORY_COPY_TEST_BOXED(src_start, dest_start, length, elem_size) \
449 MEMORY_COPY_TEST_UNBOXED(src_start, dest_start, length, elem_size)
451#define MEMORY_MOVE_TEST(src_start, dest_start, length, elem_size) \
452 MEMORY_MOVE_TEST_BOXED(src_start, dest_start, length, elem_size) \
453 MEMORY_MOVE_TEST_UNBOXED(src_start, dest_start, length, elem_size)
455#define MEMORY_TEST(src_start, dest_start, length, elem_size) \
456 MEMORY_MOVE_TEST(src_start, dest_start, length, elem_size) \
457 MEMORY_COPY_TEST(src_start, dest_start, length, elem_size)
static sk_sp< Effect > Create()
void Fail(const char *format,...) const PRINTF_ATTRIBUTE(2
void static bool failed()
GraphEntryInstr * graph_entry() const
FunctionEntryInstr * normal_entry() const
bool TryMatch(std::initializer_list< MatchCode > match_codes, MatchOpCode insert_before=kInvalidMatchOpCode)
void InsertBefore(Instruction *next)
static IntegerPtr New(const String &str, Heap::Space space=Heap::kNew)
static void Print(const char *format,...) PRINTF_ATTRIBUTE(1
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
static Object & ZoneHandle()
FlowGraph * RunPasses(std::initializer_list< CompilerPass::Id > passes)
static Thread * Current()
static constexpr bool IsPowerOfTwo(T x)
#define CHECK_DEFAULT_MEMORY(in, out)
#define MEMORY_TEST(src_start, dest_start, length, elem_size)
#define CHECK_MEMORY(in, out, start, skip, len, size)
LibraryPtr LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri)
static void InitializeMemory(uint8_t *input, uint8_t *output)
void * malloc(size_t size)
static classid_t TypedDataCidForElementSize(intptr_t elem_size)
static constexpr uint8_t kUnInitialized
ObjectPtr Invoke(const Library &lib, const char *name)
static constexpr intptr_t kMemoryTestLength
FunctionPtr GetFunction(const Library &lib, const char *name)
static bool CheckMemory(Expect expect, const uint8_t *input, const uint8_t *output, intptr_t dest_start, intptr_t src_start, intptr_t length, intptr_t elem_size)
const char * pointer_prefix
static intptr_t ExpectedValue(intptr_t i)
static constexpr Representation kUnboxedIntPtr
static constexpr Representation kUnboxedWord
static void RunMemoryCopyInstrTest(intptr_t src_start, intptr_t dest_start, intptr_t length, intptr_t elem_size, bool unboxed_inputs, bool use_same_buffer)