33 bool* auto_setup_scope) {
34 ASSERT(auto_setup_scope !=
nullptr);
35 *auto_setup_scope =
false;
46 if (var->is_captured()) {
51 env->EnsureLength(index + 1,
nullptr);
55 if (scope->
sibling() !=
nullptr) {
58 if (scope->
child() !=
nullptr) {
68 const char* script_chars,
69 std::initializer_list<const char*>
synchronized) {
71 const auto& root_library =
73 Invoke(root_library,
"main");
76 std::initializer_list<CompilerPass::Id> passes = {
77 CompilerPass::kComputeSSA, CompilerPass::kTypePropagation,
78 CompilerPass::kApplyICData, CompilerPass::kSelectRepresentations,
79 CompilerPass::kTypePropagation, CompilerPass::kCanonicalize,
94 for (intptr_t
i = 0;
i <
env.length();
i++) {
96 for (
auto name :
synchronized) {
112 if (param->location().IsRegister()) {
118 EXPECT(0 <= param->env_index() && param->env_index() <
env.length());
119 EXPECT(
env[param->env_index()] !=
nullptr);
120 if (
env[param->env_index()] ==
nullptr) {
121 OS::PrintErr(
"something is wrong with %s\n", param->ToCString());
132 const char* script_chars = R
"(
133 @pragma("vm:external-name", "BlackholeNative")
134 external dynamic blackhole([dynamic val]);
136 var a = blackhole(), b = blackhole();
152 const char* script_chars = R
"(
153 @pragma("vm:external-name", "BlackholeNative")
154 external dynamic blackhole([dynamic val]);
156 var a = blackhole(), b = blackhole();
160 // a should be synchronized
173 const char* script_chars = R
"(
174 @pragma("vm:external-name", "BlackholeNative")
175 external dynamic blackhole([dynamic val]);
177 var a = blackhole(), b;
178 for (var i = 0; i < 42; i++) {
183 // a and i should be synchronized
196 const char* script_chars = R
"(
197 @pragma("vm:external-name", "BlackholeNative")
198 external dynamic blackhole([dynamic val]);
200 var a = blackhole(), b = blackhole();
201 for (var i = 0; i < 42; i++) {
205 // a, b and i should be synchronized
227 const char* script_chars = R
"(
228 @pragma("vm:external-name", "BlackholeNative")
229 external dynamic blackhole([a, b, c, d, e, f]);
269 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
278 auto& slot =
Slot::Get(field, &
H.flow_graph()->parsed_function());
283 auto v2 =
builder.AddDefinition(make_redefinition(&
S,
H.flow_graph(), v0));
286 if (make_it_escape) {
291 std::move(
args),
S.GetNextDeoptId(), 0, ICData::RebindRule::kStatic));
300 if (make_it_escape) {
312 if (make_it_escape) {
358 LoadOptimizer_RedefinitionAliasing_Redefinition_NoEscape) {
369 LoadOptimizer_RedefinitionAliasing_AssertAssignable_NoEscape) {
375 LoadOptimizer_RedefinitionAliasing_AssertAssignable_Escape) {
389 bool make_host_escape,
392 const char* script_chars = R
"(
393 @pragma("vm:external-name", "BlackholeNative")
394 external dynamic blackhole([a, b, c, d, e, f]);
442 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
452 auto& slot =
Slot::Get(field, &
H.flow_graph()->parsed_function());
457 if (!make_host_escape) {
464 auto v2 =
builder.AddDefinition(make_redefinition(&
S,
H.flow_graph(), v5));
467 if (make_it_escape) {
468 auto v6 =
builder.AddDefinition(
471 }
else if (make_host_escape) {
479 std::move(
args),
S.GetNextDeoptId(), 0, ICData::RebindRule::kStatic));
488 if (make_it_escape || make_host_escape) {
496 if (make_host_escape) {
506 if (make_it_escape || make_host_escape) {
545 LoadOptimizer_AliasingViaStore_Redefinition_EscapeViaHost) {
551 LoadOptimizer_AliasingViaStore_AssertAssignable_NoEscape) {
562 LoadOptimizer_AliasingViaStore_AssertAssignable_EscapeViaHost) {
583 auto zone =
H.flow_graph()->zone();
604 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
633 new Value(array), Slot::PointerBase_data(),
662 kMatchAndMoveFunctionEntry,
663 {kMatchAndMoveStaticCall, &sc},
664 {kMatchAndMoveLoadIndexed, &li},
665 {kMatchAndMoveLoadField, &lf},
666 {kMatchAndMoveStoreIndexed, &s},
667 {kMatchAndMoveLoadIndexed, &li2},
668 {kMatchDartReturn, &r},
688 auto zone =
H.flow_graph()->zone();
706 const auto& lib = Library::Handle(zone, Library::TypedDataLibrary());
708 const Class& view_cls = Class::ZoneHandle(
709 zone, lib.LookupClassAllowPrivate(Symbols::_Uint8ArrayView()));
714 auto vc42 =
H.flow_graph()->GetConstant(Integer::Handle(Integer::New(42)));
715 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
737 new (zone)
Value(array), Slot::PointerBase_data(),
743 Slot::PointerBase_data(),
new (zone)
Value(view),
new (zone)
Value(v1),
753 DominatorBasedCSE::Optimize(
H.flow_graph());
762 kMatchAndMoveFunctionEntry,
763 {kMatchAndMoveAllocateTypedData, &alloc_array},
764 {kMatchAndMoveAllocateObject, &alloc_view},
765 {kMatchAndMoveLoadField, &lf},
766 {kMatchAndMoveStoreField, &sf},
767 {kMatchDartReturn, &r},
769 EXPECT(array == alloc_array);
770 EXPECT(view == alloc_view);
781 const char* script_chars = R
"(
782 import 'dart:typed_data';
785 final Float64List data;
792 const Class& view_cls = Class::ZoneHandle(
793 lib.
LookupClass(String::Handle(Symbols::New(thread,
"View"))));
797 const Field& original_field = Field::Handle(
798 view_cls.
LookupField(String::Handle(Symbols::New(thread,
"data"))));
806 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
818 const auto view =
builder.AddDefinition(
824 &
H.flow_graph()->parsed_function()));
830 Instance::ElementSizeFor(kTypedDataFloat64ArrayCid),
839 new Value(array_alias),
new Value(
H.IntConstant(1)),
842 Instance::ElementSizeFor(kTypedDataFloat32ArrayCid),
847 new Value(array),
new Value(
H.IntConstant(0)),
false,
848 Instance::ElementSizeFor(kTypedDataFloat64ArrayCid),
855 DominatorBasedCSE::Optimize(
H.flow_graph());
865 !block_it.
Done(); block_it.Advance()) {
868 if (it.Current()->IsLoadField()) {
870 }
else if (it.Current()->IsStoreField()) {
878 const char* kScript = R
"(
897 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
898 Invoke(root_library,
"main");
902 CompilerPass::kComputeSSA,
903 CompilerPass::kTypePropagation,
904 CompilerPass::kApplyICData,
905 CompilerPass::kInlining,
906 CompilerPass::kTypePropagation,
907 CompilerPass::kSelectRepresentations,
908 CompilerPass::kCanonicalize,
909 CompilerPass::kConstantPropagation,
912 ASSERT(flow_graph !=
nullptr);
915 intptr_t bef_loads = 0;
916 intptr_t bef_stores = 0;
918 EXPECT_EQ(2, bef_loads);
919 EXPECT_EQ(4, bef_stores);
921 DominatorBasedCSE::Optimize(flow_graph);
924 intptr_t aft_loads = 0;
925 intptr_t aft_stores = 0;
927 EXPECT_EQ(0, aft_loads);
928 EXPECT_EQ(1, aft_stores);
932 const char* kScript = R
"(
943 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
944 Invoke(root_library,
"main");
948 ASSERT(flow_graph !=
nullptr);
955 kMatchAndMoveFunctionEntry,
956 kMatchAndMoveCheckStackOverflow,
957 kMatchAndMoveLoadStaticField,
959 kMatchAndMoveCheckSmi,
961 kMatchAndMoveBinarySmiOp,
968 const char* kScript = R
"(
969 int x = int.parse('1');
971 @pragma('vm:never-inline')
974 foo(bool condition) {
988 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
989 Invoke(root_library,
"main");
993 ASSERT(flow_graph !=
nullptr);
1003 kMatchAndMoveBranchTrue,
1006 kMatchAndMoveJoinEntry,
1008 {kMatchAndMoveLoadStaticField, &load_static_after_if},
1012 EXPECT(!load_static_after_if->calls_initializer());
1016 const char* kScript = R
"(
1018 late int x = int.parse('1');
1022 @pragma('vm:never-inline')
1029 final next = obj.next;
1039 foo(A()..next = A());
1043 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
1044 Invoke(root_library,
"main");
1048 ASSERT(flow_graph !=
nullptr);
1051 EXPECT(entry !=
nullptr);
1060 {kMatchAndMoveLoadField, &load_field_before_loop},
1063 kMatchAndMoveJoinEntry,
1065 {kMatchAndMoveLoadField, &load_field_in_loop1},
1069 {kMatchAndMoveLoadField, &load_field_in_loop2},
1072 EXPECT(load_field_before_loop->calls_initializer());
1073 EXPECT(!load_field_in_loop1->calls_initializer());
1074 EXPECT(load_field_in_loop2->calls_initializer());
1077#if !defined(TARGET_ARCH_IA32)
1080 const char* kScript = R
"(
1082 final double x, y, z;
1084 @pragma('vm:prefer-inline')
1085 const Vec3(this.x, this.y, this.z);
1088 @pragma('vm:prefer-inline')
1089 String toString() => _vec3ToString(x, y, z);
1092@pragma('vm:never-inline')
1093String _vec3ToString(double x, double y, double z) => '';
1095// Boxed storage for Vec3.
1096// Fields are unboxed.
1108 String toString() => _vec3ToString(_x, _y, _z);
1110 @pragma('vm:prefer-inline')
1119 final a = Vec3(3, 4, 5);
1120 final b = Vec3(8, 9, 10);
1121 final c = Vec3(18, 19, 20);
1122 final d = Vec3(180, 190, 200);
1123 final e = Vec3(1800, 1900, 2000);
1124 final v = Vec3Mut(a);
1133 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
1145 ILMatcher cursor(flow_graph, entry,
true, ParallelMovesHandling::kSkip);
1148 {kMatchAndMoveAllocateObject, &allocate},
1149 {kMatchAndMoveStoreField, &store1},
1150 {kMatchAndMoveStoreField, &store2},
1151 {kMatchAndMoveStoreField, &store3},
1155 EXPECT(store1->instance()->definition() == allocate);
1157 EXPECT(store3->instance()->definition() == allocate);
1161 const char* kScript = R
"(
1165 toString() => "Foo x: $x";
1181 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
1182 Invoke(root_library,
"main");
1191 ILMatcher cursor(flow_graph, entry,
true, ParallelMovesHandling::kSkip);
1194 {kMatchAndMoveAllocateObject, &allocate},
1195 {kMatchAndMoveStoreField, &store1},
1199 EXPECT(store1->instance()->definition() == allocate);
1205 const char* kScript = R
"(
1206import 'dart:typed_data';
1209 final Float64List _v2storage;
1211 @pragma('vm:prefer-inline')
1212 Vector2.zero() : _v2storage = Float64List(2);
1214 @pragma('vm:prefer-inline')
1215 factory Vector2(double x, double y) => Vector2.zero()..setValues(x, y);
1217 @pragma('vm:prefer-inline')
1218 factory Vector2.copy(Vector2 other) => Vector2.zero()..setFrom(other);
1220 @pragma('vm:prefer-inline')
1221 Vector2 clone() => Vector2.copy(this);
1223 @pragma('vm:prefer-inline')
1224 void setValues(double x_, double y_) {
1229 @pragma('vm:prefer-inline')
1230 void setFrom(Vector2 other) {
1231 final otherStorage = other._v2storage;
1232 _v2storage[1] = otherStorage[1];
1233 _v2storage[0] = otherStorage[0];
1236 @pragma('vm:prefer-inline')
1237 Vector2 operator +(Vector2 other) => clone()..add(other);
1239 @pragma('vm:prefer-inline')
1240 void add(Vector2 arg) {
1241 final argStorage = arg._v2storage;
1242 _v2storage[0] = _v2storage[0] + argStorage[0];
1243 _v2storage[1] = _v2storage[1] + argStorage[1];
1246 @pragma('vm:prefer-inline')
1247 double get x => _v2storage[0];
1249 @pragma('vm:prefer-inline')
1250 double get y => _v2storage[1];
1253@pragma('vm:never-inline')
1254String foo(double x) {
1255 // All allocations in this function are eliminated by the compiler,
1256 // except array allocation for string interpolation at the end.
1257 List v1 = List.filled(2, null);
1260 Vector2 v2 = new Vector2(1.0, 2.0);
1261 Vector2 v3 = v2 + Vector2(x, x);
1262 double sum = v3.x + v3.y;
1263 return "v1: [${v1[0]},${v1[1]}], v2: [${v2.x},${v2.y}], v3: [${v3.x},${v3.y}], sum: $sum";
1271 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
1272 Invoke(root_library,
"main");
1276 ASSERT(flow_graph !=
nullptr);
1279 EXPECT(entry !=
nullptr);
1330 ILMatcher cursor(flow_graph, entry,
true,
1331 ParallelMovesHandling::kSkip);
1333 kMatchAndMoveFunctionEntry,
1334 kMatchAndMoveCheckStackOverflow,
1338 kMatchAndMoveBinaryDoubleOp,
1339 kMatchAndMoveBinaryDoubleOp,
1342 kMatchAndMoveBinaryDoubleOp,
1343 {kMatchAndMoveCreateArray, &create_array},
1344 kMatchAndMoveStoreIndexed,
1345 kMatchAndMoveStoreIndexed,
1346 kMatchAndMoveStoreIndexed,
1347 kMatchAndMoveStoreIndexed,
1348 kMatchAndMoveStoreIndexed,
1349 kMatchAndMoveStoreIndexed,
1350 kMatchAndMoveStoreIndexed,
1351 kMatchAndMoveStoreIndexed,
1352 kMatchAndMoveStoreIndexed,
1353 kMatchAndMoveStoreIndexed,
1354 kMatchAndMoveStoreIndexed,
1355 kMatchAndMoveStoreIndexed,
1356 kMatchAndMoveStoreIndexed,
1358 kMatchAndMoveStoreIndexed,
1359 kMatchAndMoveMoveArgument,
1360 {kMatchAndMoveStaticCall, &string_interpolate},
1364 EXPECT(string_interpolate->ArgumentAt(0) == create_array);
1368 const char* kScript = R
"(
1370@pragma('vm:prefer-inline')
1371({int field1, String field2}) getRecord(int x, String y) =>
1372 (field1: x, field2: y);
1374@pragma('vm:never-inline')
1375String foo(int x, String y) {
1376 // All allocations in this function are eliminated by the compiler,
1377 // except array allocation for string interpolation at the end.
1378 (int, bool) r1 = (x, true);
1379 final r2 = getRecord(x, y);
1380 int sum = r1.$1 + r2.field1;
1381 return "r1: (${r1.$1}, ${r1.$2}), "
1382 "r2: (field1: ${r2.field1}, field2: ${r2.field2}), sum: $sum";
1387 // Deoptimize on the 2nd run.
1388 return foo(count++ == 0 ? 42 : 9223372036854775807, 'hey');
1392 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
1393 const auto& result1 = Object::Handle(
Invoke(root_library,
"main"));
1394 EXPECT(result1.IsString());
1395 EXPECT_STREQ(result1.ToCString(),
1396 "r1: (42, true), r2: (field1: 42, field2: hey), sum: 84");
1400 ASSERT(flow_graph !=
nullptr);
1403 EXPECT(entry !=
nullptr);
1438 ILMatcher cursor(flow_graph, entry,
true,
1439 ParallelMovesHandling::kSkip);
1441 kMatchAndMoveFunctionEntry,
1442 kMatchAndMoveCheckStackOverflow,
1443 kMatchAndMoveCheckSmi,
1444 kMatchAndMoveBinarySmiOp,
1445 kMatchAndMoveCreateArray,
1446 kMatchAndMoveStoreIndexed,
1447 kMatchAndMoveStoreIndexed,
1448 kMatchAndMoveStoreIndexed,
1449 kMatchAndMoveStoreIndexed,
1450 kMatchAndMoveStoreIndexed,
1451 kMatchAndMoveStoreIndexed,
1452 kMatchAndMoveStoreIndexed,
1453 kMatchAndMoveStoreIndexed,
1454 kMatchAndMoveStoreIndexed,
1455 kMatchAndMoveStoreIndexed,
1456 kMatchAndMoveMoveArgument,
1457 kMatchAndMoveStaticCall,
1461 Compiler::CompileOptimizedFunction(thread,
function);
1462 const auto& result2 = Object::Handle(
Invoke(root_library,
"main"));
1463 EXPECT(result2.IsString());
1464 EXPECT_STREQ(result2.ToCString(),
1465 "r1: (9223372036854775807, true), r2: (field1: "
1466 "9223372036854775807, field2: hey), sum: -2");
1469#if !defined(TARGET_ARCH_IA32)
1472 const char* kScript = R
"(
1480 @pragma("vm:never-inline")
1481 dynamic foo(int i) => count++ < 2 ? i : '$i';
1483 @pragma("vm:never-inline")
1487 A a = new A(foo(1), foo(2));
1492 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
1496 Invoke(root_library,
"test");
1497 Invoke(root_library,
"test");
1509 ILMatcher cursor(flow_graph, entry,
true, ParallelMovesHandling::kSkip);
1512 {kMatchAndMoveStaticCall, &call1},
1514 {kMatchAndMoveStaticCall, &call2},
1516 {kMatchAndMoveAllocateObject, &allocate},
1517 {kMatchAndMoveStoreField, &store1},
1518 {kMatchAndMoveStoreField, &store2},
1521 EXPECT(strcmp(call1->function().UserVisibleNameCString(),
"foo") == 0);
1522 EXPECT(strcmp(call2->function().UserVisibleNameCString(),
"foo") == 0);
1523 EXPECT(store1->instance()->definition() == allocate);
1524 EXPECT(!store1->ShouldEmitStoreBarrier());
1530 const char* kScript = R
"(
1532 Object o = new Object();
1533 for (int i = 0; i < 10; i++) {
1538 @pragma('vm:never-inline')
1539 void use(Object o) {
1544 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
1554 ILMatcher cursor(flow_graph, entry,
true, ParallelMovesHandling::kSkip);
1557 {kMatchAndMoveAllocateObject, &allocate},
1561 {kMatchAndMoveStaticCall, &call},
1564 EXPECT(strcmp(
call->function().UserVisibleNameCString(),
"use") == 0);
1565 EXPECT(
call->Receiver()->definition() == allocate);
1569 const char* kScript = R
"(
1570 @pragma('vm:prefer-inline')
1572 print(''); // Side-effectful operation
1574 for (int i = 0; i < n; i++) {
1580 @pragma('vm:unsafe:no-interrupts')
1583 for (int i = 0; i < 10; i++) {
1590 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
1594 auto flow_graph = pipeline.
RunPasses({});
1595 for (
auto block : flow_graph->postorder()) {
1596 for (
auto instr : block->instructions()) {
1603 const char* kScript = R
"(
1604 import 'dart:typed_data';
1606 @pragma('vm:unsafe:no-bounds-checks')
1607 int test(Uint8List list) {
1609 for (int i = 0; i < 10; i++) {
1616 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
1620 auto flow_graph = pipeline.
RunPasses({});
1621 for (
auto block : flow_graph->postorder()) {
1622 for (
auto instr : block->instructions()) {
1631 const char* script_chars = R
"(
1632 @pragma("vm:external-name", "BlackholeNative")
1633 external dynamic blackhole([a, b, c, d, e, f]);
1642 const Class& cls = Class::ZoneHandle(
1643 lib.
LookupClass(String::Handle(Symbols::New(thread,
"K"))));
1647 const Field& original_field = Field::Handle(
1648 cls.
LookupField(String::Handle(Symbols::New(thread,
"field"))));
1653 Function::ZoneHandle(
GetFunction(lib,
"blackhole"));
1661 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
1673 auto& slot =
Slot::Get(field, &
H.flow_graph()->parsed_function());
1674 auto param0 =
builder.AddParameter(0, kUnboxedDouble);
1675 auto param1 =
builder.AddParameter(1, kTagged);
1689 load0 =
builder.AddDefinition(
1691 load1 =
builder.AddDefinition(
1702 std::move(
args),
S.GetNextDeoptId(), 0, ICData::RebindRule::kStatic));
1710 DominatorBasedCSE::Optimize(
H.flow_graph(),
false);
1726 DominatorBasedCSE::Optimize(
H.flow_graph(),
true);
1734 it.ArgumentAt(1)->OriginalDefinition() == load0);
1736 it.ArgumentAt(2)->OriginalDefinition() == load0);
1740 auto*
const kFunctionName =
"unalignedUint16";
1741 auto*
const kInvokeNoDeoptName =
"no_deopt";
1742 auto*
const kInvokeDeoptName =
"deopt";
1744 import 'dart:_internal';
1745 import 'dart:typed_data';
1747 @pragma("vm:never-inline")
1748 void check(int x, int y) {
1750 throw "Doesn't match";
1754 @pragma("vm:never-inline")
1756 var bytes = new ByteData(64);
1758 for (var i = 2; i < 4; i++) {
1759 bytes.setUint16(i, x + 1, Endian.host);
1760 check(x + 1, bytes.getUint16(i, Endian.host));
1763 // Force a garbage collection after deoptimization. In DEBUG mode,
1764 // the scavenger tests that the view's data field was set correctly
1765 // during deoptimization before recomputing it.
1766 VMInternalsForTesting.collectAllGarbage();
1768 // Make sure the array is also used on the non-int path.
1769 check(0, bytes.getUint16(0, Endian.host));
1781 kFunctionName, kInvokeNoDeoptName,
1782 kFunctionName, kInvokeDeoptName,
1788 if (lib.IsNull())
return;
1795 auto&
result = Object::Handle(
Invoke(lib, kInvokeNoDeoptName));
1800 CompilerPass::kComputeSSA,
1801 CompilerPass::kApplyICData,
1802 CompilerPass::kTryOptimizePatterns,
1803 CompilerPass::kSetOuterInliningId,
1804 CompilerPass::kTypePropagation,
1805 CompilerPass::kApplyClassIds,
1806 CompilerPass::kInlining,
1807 CompilerPass::kTypePropagation,
1808 CompilerPass::kApplyClassIds,
1809 CompilerPass::kTypePropagation,
1810 CompilerPass::kApplyICData,
1811 CompilerPass::kCanonicalize,
1812 CompilerPass::kBranchSimplify,
1813 CompilerPass::kIfConvert,
1814 CompilerPass::kCanonicalize,
1815 CompilerPass::kConstantPropagation,
1816 CompilerPass::kOptimisticallySpecializeSmiPhis,
1817 CompilerPass::kTypePropagation,
1818 CompilerPass::kSelectRepresentations,
1820 CompilerPass::kCanonicalize,
1821 CompilerPass::kLICM,
1822 CompilerPass::kTryOptimizePatterns,
1823 CompilerPass::kSelectRepresentations,
1825 CompilerPass::kTypePropagation,
1826 CompilerPass::kSelectRepresentations,
1827 CompilerPass::kEliminateEnvironments,
1828 CompilerPass::kEliminateDeadPhis,
1830 CompilerPass::kCanonicalize,
1831 CompilerPass::kOptimizeBranches,
1837 EXPECT(entry !=
nullptr);
1847 ILMatcher cursor(flow_graph, entry,
true, ParallelMovesHandling::kSkip);
1850 {kMatchAndMoveAllocateTypedData, &alloc_typed_data},
1851 {kMatchAndMoveAllocateObject, &alloc_view},
1852 {kMatchAndMoveStoreField, &store_view_typed_data},
1853 {kMatchAndMoveStoreField, &store_view_offset_in_bytes},
1854 {kMatchAndMoveStoreField, &store_view_length},
1855 {kMatchAndMoveLoadField, &load_typed_data_payload},
1856 {kMatchAndMoveStoreField, &store_view_payload},
1858 if (store_view_payload ==
nullptr)
return;
1860 EXPECT_EQ(alloc_view, store_view_typed_data->instance()->definition());
1862 store_view_typed_data->slot()));
1863 EXPECT_EQ(alloc_typed_data, store_view_typed_data->value()->definition());
1865 EXPECT_EQ(alloc_view, store_view_length->instance()->definition());
1867 EXPECT_EQ(alloc_typed_data->num_elements()->definition(),
1868 store_view_length->value()->definition());
1870 EXPECT_EQ(alloc_view, store_view_offset_in_bytes->instance()->definition());
1872 store_view_offset_in_bytes->slot()));
1873 EXPECT(store_view_offset_in_bytes->value()->BindsToSmiConstant());
1874 EXPECT_EQ(0, store_view_offset_in_bytes->value()->BoundSmiConstant());
1876 EXPECT_EQ(alloc_typed_data,
1877 load_typed_data_payload->instance()->definition());
1878 EXPECT(Slot::PointerBase_data().IsIdentical(load_typed_data_payload->slot()));
1880 EXPECT_EQ(alloc_view, store_view_payload->instance()->definition());
1881 EXPECT(Slot::PointerBase_data().IsIdentical(store_view_payload->slot()));
1882 EXPECT_EQ(load_typed_data_payload, store_view_payload->value()->definition());
1885 EXPECT(load_typed_data_payload->HasOnlyUse(store_view_payload->value()));
1887 pipeline.RunAdditionalPasses({
1888 CompilerPass::kAllocationSinking_Sink,
1892 EXPECT_EQ(
nullptr, alloc_view->previous());
1893 EXPECT_EQ(
nullptr, alloc_view->next());
1895 intptr_t mat_count = 0;
1896 for (
auto block_it = flow_graph->reverse_postorder_iterator();
1897 !block_it.Done(); block_it.Advance()) {
1898 for (ForwardInstructionIterator it(block_it.Current()); !it.Done();
1900 auto*
const mat = it.Current()->AsMaterializeObject();
1901 if (mat ==
nullptr)
continue;
1902 if (mat->allocation() == alloc_view) {
1904 for (intptr_t
i = 0;
i < mat->InputCount();
i++) {
1906 EXPECT(mat->FieldOffsetAt(
i) !=
1907 Slot::PointerBase_data().offset_in_bytes());
1910 if (
auto*
const load = mat->InputAt(
i)->definition()->AsLoadField()) {
1911 if (
load->instance()->definition() == alloc_typed_data) {
1912 EXPECT(!
load->slot().IsIdentical(Slot::PointerBase_data()));
1922 EXPECT(!load_typed_data_payload->HasUses());
1924 pipeline.RunAdditionalPasses({
1925 CompilerPass::kEliminateDeadPhis,
1927 CompilerPass::kCanonicalize,
1928 CompilerPass::kTypePropagation,
1929 CompilerPass::kSelectRepresentations_Final,
1930 CompilerPass::kUseTableDispatch,
1931 CompilerPass::kEliminateStackOverflowChecks,
1932 CompilerPass::kCanonicalize,
1933 CompilerPass::kAllocationSinking_DetachMaterializations,
1934 CompilerPass::kEliminateWriteBarriers,
1935 CompilerPass::kLoweringAfterCodeMotionDisabled,
1936 CompilerPass::kFinalizeGraph,
1937 CompilerPass::kCanonicalize,
1938 CompilerPass::kReorderBlocks,
1939 CompilerPass::kAllocateRegisters,
1940 CompilerPass::kTestILSerialization,
1944 pipeline.CompileGraphAndAttachFunction();
1966 int n = int.parse('3');
1969 for (int i = 0; i < n; ++i) {
1970 if (i > ((1 << %d)*1024)) {
1977 static_cast<int>(
kSmiBits + 1 - 10)));
1979 const auto& root_library = Library::Handle(
LoadTestScript(kScript.get()));
1983 Invoke(root_library,
"main");
1986 Compiler::CompileOptimizedFunction(thread,
function);
1992 Invoke(root_library,
"main");
1996 Compiler::CompileOptimizedFunction(thread,
function);
1999 Invoke(root_library,
"main");
2007 Invoke(root_library,
"main");
2015 const char* kScript = R
"(
2021 A obj = A([1, 2, 3]);
2022 int n = int.parse('3');
2025 // Make sure A.foo= is compiled.
2028 for (int i = 0; i < n; ++i) {
2029 if (int.parse('1') != 1) {
2030 // Field guard from this unreachable code is moved up
2031 // and causes repeated deoptimization.
2040 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
2044 Invoke(root_library,
"main");
2047 Compiler::CompileOptimizedFunction(thread,
function);
2051 Invoke(root_library,
"main");
2055 Compiler::CompileOptimizedFunction(thread,
function);
2059 Invoke(root_library,
"main");
static sk_sp< Effect > Create()
static volatile float blackhole[4]
static SkV4 v4(SkV3 v, SkScalar w)
#define RELEASE_ASSERT(cond)
bool IsNotAliased() const
virtual AliasIdentity Identity() const
GrowableArray< Definition * > * initial_definitions()
FunctionPtr LookupFactory(const String &name) const
ErrorPtr EnsureIsFinalized(Thread *thread) const
FieldPtr LookupField(const String &name) const
static CompileType FromCid(intptr_t cid)
PRINT_OPERANDS_TO_SUPPORT PRINT_TO_SUPPORT bool UpdateType(CompileType new_type)
static constexpr intptr_t kNone
static bool Optimize(FlowGraph *graph, bool run_load_optimization=true)
FieldPtr CloneFromOriginal() const
GraphEntryInstr * graph_entry() const
ConstantInstr * GetConstant(const Object &object, Representation representation=kTagged)
ConstantInstr * constant_null() const
const ParsedFunction & parsed_function() const
BlockIterator reverse_postorder_iterator() const
intptr_t EnvIndex(const LocalVariable *variable) const
FunctionEntryInstr * normal_entry() const
const GrowableArray< CatchBlockEntryInstr * > & catch_entries() const
bool TryMatch(std::initializer_list< MatchCode > match_codes, MatchOpCode insert_before=kInvalidMatchOpCode)
bool WasEliminated() const
Instruction * next() const
Instruction * previous() const
static IntegerPtr New(const String &str, Heap::Space space=Heap::kNew)
ClassPtr LookupClass(const String &name) const
static LibraryPtr TypedDataLibrary()
LocalScope * sibling() const
LocalVariable * VariableAt(intptr_t index) const
intptr_t num_variables() const
LocalScope * child() const
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static Object & ZoneHandle()
LocalScope * scope() const
static const Slot & Get(const Field &field, const ParsedFunction *parsed_function)
void SetResultType(Zone *zone, CompileType new_type)
void set_is_known_list_constructor(bool value)
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
static const String & Empty()
static StringPtr New(Thread *thread, const char *cstr)
FlowGraph * RunPasses(std::initializer_list< CompilerPass::Id > passes)
static TypePtr ObjectType()
Definition * definition() const
struct _Dart_Handle * Dart_Handle
struct _Dart_NativeArguments * Dart_NativeArguments
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Dart_NativeFunction function
#define EXPECT_PROPERTY(entity, property)
const GrXPFactory * Get(SkBlendMode mode)
SI void load2(const uint16_t *ptr, U16 *r, U16 *g)
SI void store2(uint16_t *ptr, U16 r, U16 g)
const Type & DynamicType()
static bool Equals(const Object &expected, const Object &actual)
LibraryPtr LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri)
@ kMatchAndMoveBranchFalse
@ kMatchAndMoveBranchTrue
static void FlattenScopeIntoEnvironment(FlowGraph *graph, LocalScope *scope, GrowableArray< LocalVariable * > *env)
void OptimizeCatchEntryStates(FlowGraph *flow_graph, bool is_aot)
@ TypedDataView_offset_in_bytes
@ TypedDataView_typed_data
static void NoopNative(Dart_NativeArguments args)
Location LocationExceptionLocation()
GrowableArray< Value * > InputsArray
ObjectPtr Invoke(const Library &lib, const char *name)
FunctionPtr GetFunction(const Library &lib, const char *name)
static void TestAliasingViaStore(Thread *thread, bool make_it_escape, bool make_host_escape, std::function< Definition *(CompilerState *S, FlowGraph *, Definition *)> make_redefinition)
ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction)
static Definition * MakeCheckNull(CompilerState *S, FlowGraph *flow_graph, Definition *defn)
Location LocationStackTraceLocation()
static void TestAliasingViaRedefinition(Thread *thread, bool make_it_escape, std::function< Definition *(CompilerState *S, FlowGraph *, Definition *)> make_redefinition)
static void CountLoadsStores(FlowGraph *flow_graph, intptr_t *loads, intptr_t *stores)
static Definition * MakeRedefinition(CompilerState *S, FlowGraph *flow_graph, Definition *defn)
static void TryCatchOptimizerTest(Thread *thread, const char *script_chars, std::initializer_list< const char * > synchronized)
static Definition * MakeAssertAssignable(CompilerState *S, FlowGraph *flow_graph, Definition *defn)
static Dart_NativeFunction NoopNativeLookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
#define ISOLATE_UNIT_TEST_CASE(name)