Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
reachability_fence_test.cc
Go to the documentation of this file.
1// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include <vector>
6
12#include "vm/object.h"
13#include "vm/unit_test.h"
14
15namespace dart {
16
17ISOLATE_UNIT_TEST_CASE(ReachabilityFence_Simple) {
18 // clang-format off
19 auto kScript =
21 R"(
22 import 'dart:_internal' show reachabilityFence;
23
24 int someGlobal = 0;
25
26 class A {
27 int%s a;
28 }
29
30 void someFunction(int arg) {
31 someGlobal += arg;
32 }
33
34 main() {
35 final object = A()..a = 10;
36 someFunction(object.a%s);
37 reachabilityFence(object);
38 }
39 )",
41 // clang-format on
42
43 const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
44
45 Invoke(root_library, "main");
46
47 const auto& function = Function::Handle(GetFunction(root_library, "main"));
49 FlowGraph* flow_graph = pipeline.RunPasses({});
50 ASSERT(flow_graph != nullptr);
51
52 auto entry = flow_graph->graph_entry()->normal_entry();
53 EXPECT(entry != nullptr);
54
55 // v2 <- AllocateObject(A <not-aliased>) T{A}
56 // ...
57 // [use field of object v2]
58 // ReachabilityFence(v2)
59 AllocateObjectInstr* allocate_object = nullptr;
60 ReachabilityFenceInstr* fence = nullptr;
61
62 ILMatcher cursor(flow_graph, entry);
63 RELEASE_ASSERT(cursor.TryMatch({
64 kMoveGlob,
65 // Allocate the object.
66 {kMatchAndMoveAllocateObject, &allocate_object},
68 // The call.
69 kMatchAndMoveStoreStaticField,
70 // The fence should not be moved before the call.
71 {kMatchAndMoveReachabilityFence, &fence},
72 }));
73
74 EXPECT(fence->value()->definition() == allocate_object);
75}
76
77ISOLATE_UNIT_TEST_CASE(ReachabilityFence_Loop) {
78 // clang-format off
79 auto kScript =
80 Utils::CStringUniquePtr(OS::SCreate(nullptr, R"(
81 import 'dart:_internal' show reachabilityFence;
82
83 int someGlobal = 0;
84
85 class A {
86 int%s a;
87 }
88
89 @pragma('vm:never-inline')
90 A makeSomeA() {
91 return A()..a = 10;
92 }
93
94 void someFunction(int arg) {
95 someGlobal += arg;
96 }
97
98 main() {
99 final object = makeSomeA();
100 for(int i = 0; i < 100000; i++) {
101 someFunction(object.a%s);
102 reachabilityFence(object);
103 }
104 }
105 )", TestCase::NullableTag(), TestCase::NullAssertTag()), std::free);
106 // clang-format on
107
108 const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
109
110 Invoke(root_library, "main");
111
112 const auto& function = Function::Handle(GetFunction(root_library, "main"));
113 TestPipeline pipeline(function, CompilerPass::kJIT);
114 FlowGraph* flow_graph = pipeline.RunPasses({});
115 ASSERT(flow_graph != nullptr);
116
117 auto entry = flow_graph->graph_entry()->normal_entry();
118 EXPECT(entry != nullptr);
119
120 StaticCallInstr* object = nullptr;
121 LoadFieldInstr* field_load = nullptr;
122 ReachabilityFenceInstr* fence = nullptr;
123
124 ILMatcher cursor(flow_graph, entry);
125 RELEASE_ASSERT(cursor.TryMatch(
126 {
127 // Get the object from some method
128 {kMatchAndMoveStaticCall, &object},
129 // Load the field outside the loop.
130 {kMatchAndMoveLoadField, &field_load},
131 // Go into the loop.
132 kMatchAndMoveBranchTrue,
133 // The fence should not be moved outside of the loop.
134 {kMatchAndMoveReachabilityFence, &fence},
135 },
136 /*insert_before=*/kMoveGlob));
137
138 EXPECT(field_load->instance()->definition() == object);
139 EXPECT(fence->value()->definition() == object);
140}
141
142ISOLATE_UNIT_TEST_CASE(ReachabilityFence_NoCanonicalize) {
143 // clang-format off
144 auto kScript =
145 Utils::CStringUniquePtr(OS::SCreate(nullptr, R"(
146 import 'dart:_internal' show reachabilityFence;
147
148 int someGlobal = 0;
149
150 class A {
151 int%s a;
152 }
153
154 @pragma('vm:never-inline')
155 A makeSomeA() {
156 return A()..a = 10;
157 }
158
159 void someFunction(int arg) {
160 someGlobal += arg;
161 }
162
163 main() {
164 final object = makeSomeA();
165 reachabilityFence(object);
166 for(int i = 0; i < 100000; i++) {
167 someFunction(object.a%s);
168 reachabilityFence(object);
169 }
170 reachabilityFence(object);
171 reachabilityFence(object);
172 }
173 )", TestCase::NullableTag(), TestCase::NullAssertTag()), std::free);
174 // clang-format on
175
176 const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
177
178 Invoke(root_library, "main");
179
180 const auto& function = Function::Handle(GetFunction(root_library, "main"));
181 TestPipeline pipeline(function, CompilerPass::kJIT);
182 FlowGraph* flow_graph = pipeline.RunPasses({});
183 ASSERT(flow_graph != nullptr);
184
185 auto entry = flow_graph->graph_entry()->normal_entry();
186 EXPECT(entry != nullptr);
187
188 StaticCallInstr* object = nullptr;
189 ReachabilityFenceInstr* fence1 = nullptr;
190 ReachabilityFenceInstr* fence2 = nullptr;
191 ReachabilityFenceInstr* fence3 = nullptr;
192 ReachabilityFenceInstr* fence4 = nullptr;
193
194 ILMatcher cursor(flow_graph, entry);
195 RELEASE_ASSERT(cursor.TryMatch(
196 {
197 {kMatchAndMoveStaticCall, &object},
198 {kMatchAndMoveReachabilityFence, &fence1},
199 kMatchAndMoveBranchTrue,
200 {kMatchAndMoveReachabilityFence, &fence2},
201 kMatchAndMoveBranchFalse,
202 {kMatchAndMoveReachabilityFence, &fence3},
203 {kMatchAndMoveReachabilityFence, &fence4},
204 },
205 /*insert_before=*/kMoveGlob));
206
207 EXPECT(fence1->value()->definition() == object);
208 EXPECT(fence2->value()->definition() == object);
209 EXPECT(fence3->value()->definition() == object);
210 EXPECT(fence4->value()->definition() == object);
211}
212
213} // namespace dart
#define EXPECT(type, expectedAlignment, expectedSize)
#define RELEASE_ASSERT(cond)
Definition assert.h:327
GraphEntryInstr * graph_entry() const
Definition flow_graph.h:268
FunctionEntryInstr * normal_entry() const
Definition il.h:1986
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
static Object & Handle()
Definition object.h:407
static const char * NullAssertTag()
Definition unit_test.h:422
static const char * NullableTag()
Definition unit_test.h:421
FlowGraph * RunPasses(std::initializer_list< CompilerPass::Id > passes)
std::unique_ptr< char, decltype(std::free) * > CStringUniquePtr
Definition utils.h:644
#define ASSERT(E)
Dart_NativeFunction function
Definition fuchsia.cc:51
LibraryPtr LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri)
ObjectPtr Invoke(const Library &lib, const char *name)
FunctionPtr GetFunction(const Library &lib, const char *name)
#define ISOLATE_UNIT_TEST_CASE(name)
Definition unit_test.h:64