20 const char* kScript = R
"(
22 String toInline() { return "A"; }
28 String toInline() { return "C";}
37 for (var i = 0; i < 10; i++) {
49 Invoke(root_library,
"main");
53 CompilerPass::kComputeSSA,
54 CompilerPass::kApplyICData,
55 CompilerPass::kTryOptimizePatterns,
56 CompilerPass::kSetOuterInliningId,
57 CompilerPass::kTypePropagation,
58 CompilerPass::kApplyClassIds,
59 CompilerPass::kInlining,
65 EXPECT(entry->initial_definitions()->length() == 1);
66 EXPECT(entry->initial_definitions()->At(0)->IsParameter());
67 ParameterInstr* param = entry->initial_definitions()->At(0)->AsParameter();
77 {kMatchLoadClassId, &lcid},
78 {kMatchBranch, &prelude},
86 Instruction* current = prelude;
92 EXPECT(current->IsBranch());
93 const ComparisonInstr*
check = current->AsBranch()->comparison();
95 if (
check->right()->definition() == cid_B)
break;
96 current = current->SuccessorAt(1);
103 current = current->next();
104 if (!current->IsBranch()) {
110 if (current->IsBranch()) {
111 current = current->SuccessorAt(0);
116 EXPECT(current->IsRedefinition());
117 const auto redef = current->AsRedefinition();
118 EXPECT(redef->value()->definition() == lcid);
119 current = current->next();
120 EXPECT(current->IsCheckClassId());
121 EXPECT(current->AsCheckClassId()->value()->definition() == redef);
123 current = current->next();
124 EXPECT(current->IsGoto());
125 current = current->AsGoto()->successor();
132 current = current->next();
133 EXPECT(current->IsRedefinition());
134 EXPECT(current->AsRedefinition()->value()->definition() == param);
139 const char* kScript = R
"(
140 import 'dart:typed_data';
142 setValue(Int32List list, int value) {
147 final list = Int32List(10);
148 setValue(list, 0x1122334455);
152 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
154 Function::Handle(
GetFunction(root_library,
"setValue"));
156 Invoke(root_library,
"main");
160 CompilerPass::kComputeSSA,
161 CompilerPass::kApplyICData,
162 CompilerPass::kTryOptimizePatterns,
163 CompilerPass::kSetOuterInliningId,
164 CompilerPass::kTypePropagation,
165 CompilerPass::kApplyClassIds,
166 CompilerPass::kInlining,
171 EXPECT(entry->initial_definitions()->length() == 2);
172 EXPECT(entry->initial_definitions()->At(0)->IsParameter());
173 EXPECT(entry->initial_definitions()->At(1)->IsParameter());
175 entry->initial_definitions()->At(0)->AsParameter();
177 entry->initial_definitions()->At(1)->AsParameter();
187 {kMatchAndMoveCheckArrayBound, &bounds_check_instr},
188 {kMatchAndMoveUnboxInt32, &unbox_instr},
189 {kMatchAndMoveStoreIndexed, &store_instr},
192 RELEASE_ASSERT(unbox_instr->InputAt(0)->definition()->OriginalDefinition() ==
194 RELEASE_ASSERT(store_instr->InputAt(0)->definition() == list_param);
195 RELEASE_ASSERT(store_instr->InputAt(2)->definition() == unbox_instr);
199#if defined(DART_PRECOMPILER)
204 const char* kScript = R
"(
205 foo(n) => List<int>.generate(n, (int x) => x, growable: false);
211 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
214 TestPipeline pipeline(
function, CompilerPass::kAOT);
215 FlowGraph* flow_graph = pipeline.RunPasses({});
217 auto entry = flow_graph->graph_entry()->normal_entry();
218 ILMatcher cursor(flow_graph, entry,
true,
219 ParallelMovesHandling::kSkip);
223 kMatchAndMoveCreateArray,
224 kMatchAndMoveUnboxInt64,
228 kMatchAndMoveJoinEntry,
229 kMatchAndMoveCheckStackOverflow,
230 kMatchAndMoveBranchTrue,
233 kMatchAndMoveTargetEntry,
234 kMatchAndMoveBoxInt64,
235 kMatchAndMoveStoreIndexed,
236 kMatchAndMoveBinaryInt64Op,
240 kMatchAndMoveJoinEntry,
241 kMatchAndMoveCheckStackOverflow,
242 kMatchAndMoveBranchFalse,
245 kMatchAndMoveTargetEntry,
252 const char* kScript = R
"(
258 @pragma("vm:always-consider-inlining")
268 for (int i = 0; i < 1024; i++) {
276 bbar(bbaz, something) {
284 print(bbar(42, "something"));
285 print(bbar(choice() ? "abc": 42, "something"));
286 print(bbar("abc", "something"));
290 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
293 TestPipeline pipeline(
function, CompilerPass::kAOT);
294 FlowGraph* flow_graph = pipeline.RunPasses({});
296 auto entry = flow_graph->graph_entry()->normal_entry();
297 ILMatcher cursor(flow_graph, entry,
true);
299 StaticCallInstr* call_print1;
300 StaticCallInstr* call_print2;
301 StaticCallInstr* call_print3;
302 StaticCallInstr* call_bar;
305 {kMatchAndMoveStaticCall, &call_print1},
307 {kMatchAndMoveStaticCall, &call_bar},
309 {kMatchAndMoveStaticCall, &call_print2},
311 {kMatchAndMoveStaticCall, &call_print3},
315 EXPECT(strcmp(call_print1->function().UserVisibleNameCString(),
"print") ==
317 EXPECT(strcmp(call_print2->function().UserVisibleNameCString(),
"print") ==
319 EXPECT(strcmp(call_print3->function().UserVisibleNameCString(),
"print") ==
321 EXPECT(strcmp(call_bar->function().UserVisibleNameCString(),
"bar") == 0);
326 const char* kScript = R
"(
328 final foo = List<String>.filled(100, "bar");
329 final the_copy1 = List.of(foo, growable: false);
330 print('${the_copy1.length}');
334 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
337 TestPipeline pipeline(
function, CompilerPass::kAOT);
338 FlowGraph* flow_graph = pipeline.RunPasses({});
340 auto entry = flow_graph->graph_entry()->normal_entry();
341 ILMatcher cursor(flow_graph, entry,
true);
343 StaticCallInstr* call_print;
346 kMatchAndMoveJoinEntry,
348 kMatchAndMoveBranchTrue,
350 kMatchAndMoveJoinEntry,
351 kMatchAndMoveCheckStackOverflow,
352 kMatchAndMoveBranchFalse,
353 kMatchAndMoveTargetEntry,
355 kMatchAndMoveJoinEntry,
357 kMatchAndMoveBranchFalse,
359 {kMatchAndMoveStaticCall, &call_print},
363 EXPECT(strcmp(call_print->function().UserVisibleNameCString(),
"print") == 0);
366 it.IsConstant() && it.AsConstant()->value().IsString() &&
367 String::Cast(it.AsConstant()->value()).Equals(
"100"));
376 const char* kScript = R
"(
379 @pragma('vm:never-inline')
381 dynamic ptr = Pointer.fromAddress(x);
382 return x + ptr.hashCode;
386 for (int i = 0; i < 1000; i++) {
393 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
396 Invoke(root_library,
"main");
400 CompilerPass::kComputeSSA,
401 CompilerPass::kApplyICData,
402 CompilerPass::kTryOptimizePatterns,
403 CompilerPass::kSetOuterInliningId,
404 CompilerPass::kTypePropagation,
405 CompilerPass::kApplyClassIds,
414 {kMatchAndMoveStaticCall, &call_instr},
417 "Pointer.fromAddress") == 0);
420 pipeline.RunAdditionalPasses({
421 CompilerPass::kInlining,
424 AllocateObjectInstr* allocate_object_instr =
nullptr;
426 ILMatcher cursor(flow_graph, entry);
429 {kMatchAndMoveAllocateObject, &allocate_object_instr},
435 EXPECT(call_instr->deopt_id() == allocate_object_instr->deopt_id());
436 EXPECT(DeoptId::IsDeoptBefore(call_instr->deopt_id()));
438 auto allocate_object_instr_env = allocate_object_instr->env();
439 EXPECT(allocate_object_instr_env->LazyDeoptToBeforeDeoptId());
440 EXPECT(allocate_object_instr_env->Outermost()->GetDeoptId() ==
441 call_instr->deopt_id());
442 const auto call_instr_env = call_instr->env();
443 const intptr_t call_first_index =
444 call_instr_env->Length() - call_instr->InputCount();
445 const intptr_t allocate_first_index =
446 allocate_object_instr_env->Length() - call_instr->InputCount();
447 for (intptr_t
i = 0;
i < call_instr->InputCount();
i++) {
448 EXPECT(call_instr_env->ValueAt(call_first_index +
i)->definition() ==
449 allocate_object_instr_env->ValueAt(allocate_first_index +
i)
457 const char* str =
nullptr;
459 OS::Print(
"%s\n", str);
471 intptr_t frame_count = 0;
474 EXPECT_EQ(3, frame_count);
477 EXPECT(102 > StackTrace::kPreallocatedStackdepth);
481 intptr_t line_number = 0;
482 intptr_t column_number = 0;
483 const char* cstr =
"";
484 const char* test_lib =
"file:///test-lib";
491 &line_number, &column_number);
494 EXPECT_STREQ(
"InspectStack", cstr);
496 EXPECT_STREQ(test_lib, cstr);
497 EXPECT_EQ(11, line_number);
498 EXPECT_EQ(24, column_number);
504 &line_number, &column_number);
507 EXPECT_STREQ(
"foo", cstr);
509 EXPECT_STREQ(test_lib, cstr);
515 &line_number, &column_number);
518 EXPECT_STREQ(
"main", cstr);
520 EXPECT_STREQ(test_lib, cstr);
535 bool* auto_setup_scope) {
536 ASSERT(auto_setup_scope !=
nullptr);
537 *auto_setup_scope =
true;
538 const char* cstr =
nullptr;
541 if (strcmp(cstr,
"testPrint") == 0) {
551 OS::PrintErr(
"Encountered unexpected error: %s\n",
Dart_GetError(handle));
559 check_handle(handle);
563 check_handle(handle);
568 const char* kScriptChars = R
"(
570import 'dart:_internal';
572int _add(int a, int b) => a + b;
574@pragma('vm:external-name', "testPrint")
575external void print(String s);
577@pragma("vm:external-name", "InspectStack")
578external InspectStack();
580@pragma('vm:never-inline')
583int prologueCount = 0;
584int epilogueCount = 0;
586@pragma('vm:never-inline')
587void countPrologue() {
589 print('countPrologue: $prologueCount');
592@pragma('vm:never-inline')
593void countEpilogue() {
595 print('countEpilogue: $epilogueCount');
598@pragma('vm:force-optimize')
599@pragma('vm:idempotent')
600@pragma('vm:prefer-inline')
601int idempotentForceOptimizedFunction(int x) {
603 print('deoptimizing');
606 VMInternalsForTesting.deoptimizeFunctionsOnStack();
608 print('deoptimizing after');
613@pragma('vm:never-inline')
614int foo(int x, {bool onlyOptimizeFunction = false}) {
615 if (onlyOptimizeFunction) {
616 print('Optimizing `foo`');
617 for (int i = 0; i < 100000; i++) nop();
619 print('Running `foo`');
620 return x + idempotentForceOptimizedFunction(x+1) + 1;
624 for (int i = 0; i < 100; i++) {
625 print('\n\nround=$i');
627 // Get the `foo` function optimized while leaving prologue/epilogue counters
629 final (a, b) = (prologueCount, epilogueCount);
630 foo(i, onlyOptimizeFunction: true);
634 // Execute the optimized function `foo` function (which has the
635 // `idempotentForceOptimizedFunction` inlined).
636 final result = foo(i);
637 if (result != (2 * i + 3)) throw 'Expected ${2 * i + 3} but got $result!';
650 IsolateGroup::Current()->set_use_osr(
false);
656 const int64_t prologue_count = get_integer(lib,
"prologueCount");
657 const int64_t epilogue_count = get_integer(lib,
"epilogueCount");
667 EXPECT_EQ(epilogue_count * 2, prologue_count);
#define check(reporter, ref, unref, make, kill)
#define RELEASE_ASSERT(cond)
GraphEntryInstr * graph_entry() const
const char * UserVisibleNameCString() const
FunctionEntryInstr * normal_entry() const
bool TryMatch(std::initializer_list< MatchCode > match_codes, MatchOpCode insert_before=kInvalidMatchOpCode)
static SmiPtr New(intptr_t value)
const Function & function() const
static StringPtr New(Thread *thread, const char *cstr)
FlowGraph * RunPasses(std::initializer_list< CompilerPass::Id > passes)
DART_EXPORT Dart_Handle Dart_SetNativeResolver(Dart_Handle library, Dart_NativeEntryResolver resolver, Dart_NativeEntrySymbol symbol)
DART_EXPORT void Dart_EnterScope(void)
DART_EXPORT void Dart_ExitScope(void)
DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer, int64_t *value)
struct _Dart_Handle * Dart_Handle
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
struct _Dart_NativeArguments * Dart_NativeArguments
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle str, const char **cstr)
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT const char * Dart_GetError(Dart_Handle handle)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Dart_NativeFunction function
#define EXPECT_PROPERTY(entity, property)
LibraryPtr LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri)
Dart_Handle Dart_StackTraceLength(Dart_StackTrace trace, intptr_t *length)
Dart_Handle Dart_ActivationFrameInfo(Dart_ActivationFrame activation_frame, Dart_Handle *function_name, Dart_Handle *script_url, intptr_t *line_number, intptr_t *column_number)
Dart_Handle Dart_GetStackTrace(Dart_StackTrace *trace)
ObjectPtr Invoke(const Library &lib, const char *name)
FunctionPtr GetFunction(const Library &lib, const char *name)
void InspectStack(Dart_NativeArguments args)
struct _Dart_ActivationFrame * Dart_ActivationFrame
Dart_Handle Dart_GetActivationFrame(Dart_StackTrace trace, int frame_index, Dart_ActivationFrame *frame)
ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction)
static void TestPrint(Dart_NativeArguments args)
struct _Dart_StackTrace * Dart_StackTrace
const char *const function_name
static Dart_NativeFunction PrintAndInspectResolver(Dart_Handle name, int argument_count, bool *auto_setup_scope)
DEF_SWITCHES_START aot vmservice shared library name
#define ISOLATE_UNIT_TEST_CASE(name)
Dart_Handle NewString(const char *str)
#define EXPECT_VALID(handle)