Flutter Engine
The Flutter Engine
compiler_test.cc
Go to the documentation of this file.
1// Copyright (c) 2012, 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
6#include "platform/assert.h"
8#include "vm/code_patcher.h"
9#include "vm/dart_api_impl.h"
10#include "vm/heap/safepoint.h"
11#include "vm/kernel_isolate.h"
12#include "vm/object.h"
13#include "vm/symbols.h"
14#include "vm/thread_pool.h"
15#include "vm/unit_test.h"
16
17namespace dart {
18
19ISOLATE_UNIT_TEST_CASE(CompileFunction) {
20 const char* kScriptChars =
21 "class A {\n"
22 " static foo() { return 42; }\n"
23 " static moo() {\n"
24 " // A.foo();\n"
25 " }\n"
26 "}\n";
27 Dart_Handle library;
28 {
29 TransitionVMToNative transition(thread);
30 library = TestCase::LoadTestScript(kScriptChars, nullptr);
31 }
32 const Library& lib =
35 Class& cls =
37 EXPECT(!cls.IsNull());
38 const auto& error = cls.EnsureIsFinalized(thread);
40 String& function_foo_name = String::Handle(String::New("foo"));
41 Function& function_foo =
42 Function::Handle(cls.LookupStaticFunction(function_foo_name));
43 EXPECT(!function_foo.IsNull());
44 String& function_source = String::Handle(function_foo.GetSource());
45 EXPECT_STREQ("static foo() { return 42; }", function_source.ToCString());
47 EXPECT(function_foo.HasCode());
48
49 String& function_moo_name = String::Handle(String::New("moo"));
50 Function& function_moo =
51 Function::Handle(cls.LookupStaticFunction(function_moo_name));
52 EXPECT(!function_moo.IsNull());
53
55 EXPECT(function_moo.HasCode());
56 function_source = function_moo.GetSource();
57 EXPECT_STREQ("static moo() {\n // A.foo();\n }",
58 function_source.ToCString());
59}
60
61ISOLATE_UNIT_TEST_CASE(OptimizeCompileFunctionOnHelperThread) {
62 // Create a simple function and compile it without optimization.
63 const char* kScriptChars =
64 "class A {\n"
65 " static foo() { return 42; }\n"
66 "}\n";
67 Dart_Handle library;
68 {
69 TransitionVMToNative transition(thread);
70 library = TestCase::LoadTestScript(kScriptChars, nullptr);
71 }
72 const Library& lib =
75 Class& cls =
77 EXPECT(!cls.IsNull());
78 String& function_foo_name = String::Handle(String::New("foo"));
79 const auto& error = cls.EnsureIsFinalized(thread);
81 Function& func =
82 Function::Handle(cls.LookupStaticFunction(function_foo_name));
83 EXPECT(!func.HasCode());
85 EXPECT(func.HasCode());
86 EXPECT(!func.HasOptimizedCode());
87#if !defined(PRODUCT)
88 // Constant in product mode.
89 FLAG_background_compilation = true;
90#endif
91 auto isolate_group = thread->isolate_group();
92 isolate_group->background_compiler()->EnqueueCompilation(func);
93 Monitor* m = new Monitor();
94 {
96 while (!func.HasOptimizedCode()) {
97 ml.Wait(1);
98 }
99 }
100 delete m;
101}
102
103ISOLATE_UNIT_TEST_CASE(CompileFunctionOnHelperThread) {
104 // Create a simple function and compile it without optimization.
105 const char* kScriptChars =
106 "class A {\n"
107 " static foo() { return 42; }\n"
108 "}\n";
109 Dart_Handle library;
110 {
111 TransitionVMToNative transition(thread);
112 library = TestCase::LoadTestScript(kScriptChars, nullptr);
113 }
114 const Library& lib =
117 Class& cls =
119 EXPECT(!cls.IsNull());
120 const auto& error = cls.EnsureIsFinalized(thread);
122 String& function_foo_name = String::Handle(String::New("foo"));
123 Function& func =
124 Function::Handle(cls.LookupStaticFunction(function_foo_name));
125 EXPECT(!func.HasCode());
127 EXPECT(func.HasCode());
128}
129
130ISOLATE_UNIT_TEST_CASE(RegenerateAllocStubs) {
131 const char* kScriptChars =
132 "class A {\n"
133 "}\n"
134 "unOpt() => new A(); \n"
135 "optIt() => new A(); \n"
136 "A main() {\n"
137 " return unOpt();\n"
138 "}\n";
139
140 Class& cls = Class::Handle();
141 TransitionVMToNative transition(thread);
142
143 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
144 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
146
147 {
148 TransitionNativeToVM transition(thread);
149 Library& lib_handle =
151 cls = lib_handle.LookupClass(String::Handle(Symbols::New(thread, "A")));
152 EXPECT(!cls.IsNull());
153 }
154
155 {
156 TransitionNativeToVM transition(thread);
158 }
159 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
161
162 {
163 TransitionNativeToVM transition(thread);
165 }
166 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
168
169 {
170 TransitionNativeToVM transition(thread);
172 }
173 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
175}
176
177TEST_CASE(EvalExpression) {
178 const char* kScriptChars =
179 "int ten = 2 * 5; \n"
180 "get dot => '.'; \n"
181 "class A { \n"
182 " var apa = 'Herr Nilsson'; \n"
183 " calc(x) => '${x*ten}'; \n"
184 "} \n"
185 "makeObj() => new A(); \n";
186
187 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
188 Dart_Handle obj_handle =
189 Dart_Invoke(lib, Dart_NewStringFromCString("makeObj"), 0, nullptr);
190 EXPECT_VALID(obj_handle);
191 TransitionNativeToVM transition(thread);
192 const Object& obj = Object::Handle(Api::UnwrapHandle(obj_handle));
193 EXPECT(!obj.IsNull());
194 EXPECT(obj.IsInstance());
195
196 String& expr_text = String::Handle();
197 expr_text = String::New("apa + ' ${calc(10)}' + dot");
198 Object& val = Object::Handle();
199 const Class& receiver_cls = Class::Handle(obj.clazz());
200
202 UNREACHABLE();
203 } else {
204 LibraryPtr raw_library = Library::RawCast(Api::UnwrapHandle(lib));
205 Library& lib_handle = Library::ZoneHandle(raw_library);
206
207 Dart_KernelCompilationResult compilation_result =
209 /*platform_kernel=*/nullptr, /*platform_kernel_size=*/0,
210 expr_text.ToCString(), Array::empty_array(), Array::empty_array(),
211 Array::empty_array(), Array::empty_array(), Array::empty_array(),
212 String::Handle(lib_handle.url()).ToCString(), "A",
213 /* method= */ nullptr,
214 /* token_pos= */ TokenPosition::kNoSource,
215 /* script_uri= */ String::Handle(lib_handle.url()).ToCString(),
216 /* is_static= */ false);
217 EXPECT_EQ(Dart_KernelCompilationStatus_Ok, compilation_result.status);
218
219 const ExternalTypedData& kernel_buffer =
221 const_cast<uint8_t*>(compilation_result.kernel),
222 compilation_result.kernel_size));
223
224 val = Instance::Cast(obj).EvaluateCompiledExpression(
225 receiver_cls, kernel_buffer, Array::empty_array(), Array::empty_array(),
226 TypeArguments::null_type_arguments());
227 }
228 EXPECT(!val.IsNull());
229 EXPECT(!val.IsError());
230 EXPECT(val.IsString());
231 EXPECT_STREQ("Herr Nilsson 100.", val.ToCString());
232}
233
234ISOLATE_UNIT_TEST_CASE(EvalExpressionWithLazyCompile) {
235 { // Initialize an incremental compiler in DFE mode.
236 TransitionVMToNative transition(thread);
237 TestCase::LoadTestScript("", nullptr);
238 }
240 const String& expression = String::Handle(
241 String::New("(){ return (){ return (){ return 3 + 4; }(); }(); }()"));
242 Object& val = Object::Handle();
243 val = Api::UnwrapHandle(
244 TestCase::EvaluateExpression(lib, expression,
245 /* param_names= */ Array::empty_array(),
246 /* param_values= */ Array::empty_array()));
247
248 EXPECT(!val.IsNull());
249 EXPECT(!val.IsError());
250 EXPECT(val.IsInteger());
251 EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
252}
253
254ISOLATE_UNIT_TEST_CASE(EvalExpressionExhaustCIDs) {
255 { // Initialize an incremental compiler in DFE mode.
256 TransitionVMToNative transition(thread);
257 TestCase::LoadTestScript("", nullptr);
258 }
260 const String& expression = String::Handle(String::New("3 + 4"));
261 Object& val = Object::Handle();
262 val = Api::UnwrapHandle(
263 TestCase::EvaluateExpression(lib, expression,
264 /* param_names= */ Array::empty_array(),
265 /* param_values= */ Array::empty_array()));
266
267 EXPECT(!val.IsNull());
268 EXPECT(!val.IsError());
269 EXPECT(val.IsInteger());
270 EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
271
272 auto class_table = IsolateGroup::Current()->class_table();
273
274 intptr_t initial_class_table_size = class_table->NumCids();
275
276 val = Api::UnwrapHandle(
277 TestCase::EvaluateExpression(lib, expression,
278 /* param_names= */ Array::empty_array(),
279 /* param_values= */ Array::empty_array()));
280 EXPECT(!val.IsNull());
281 EXPECT(!val.IsError());
282 EXPECT(val.IsInteger());
283 EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
284
285 intptr_t final_class_table_size = class_table->NumCids();
286 // Eval should not eat into this non-renewable resource.
287 EXPECT_EQ(initial_class_table_size, final_class_table_size);
288}
289
290// Too slow in debug mode.
291#if !defined(DEBUG) && !defined(USING_THREAD_SANITIZER)
292TEST_CASE(ManyClasses) {
293 // Limit is 20 bits. Check only more than 16 bits so test completes in
294 // reasonable time.
295 const intptr_t kNumClasses = (1 << 16) + 1;
296
298 for (intptr_t i = 0; i < kNumClasses; i++) {
299 buffer.Printf("class C%" Pd " { String toString() => 'C%" Pd "'; }\n", i,
300 i);
301 }
302 buffer.Printf("main() {\n");
303 for (intptr_t i = 0; i < kNumClasses; i++) {
304 buffer.Printf(" new C%" Pd "().toString();\n", i);
305 }
306 buffer.Printf("}\n");
307
308 Dart_Handle lib = TestCase::LoadTestScript(buffer.buffer(), nullptr);
309 EXPECT_VALID(lib);
310 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
312
313 EXPECT(IsolateGroup::Current()->class_table()->NumCids() >= kNumClasses);
314}
315#endif // !defined(DEBUG) && !defined(USING_THREAD_SANITIZER)
316
317} // namespace dart
#define EXPECT(type, expectedAlignment, expectedSize)
#define UNREACHABLE()
Definition: assert.h:248
static ObjectPtr UnwrapHandle(Dart_Handle object)
static bool ProcessPendingClasses()
intptr_t NumCids() const
Definition: class_table.h:447
FunctionPtr LookupStaticFunction(const String &name) const
Definition: object.cc:6137
void DisableAllocationStub() const
Definition: object.cc:5879
ErrorPtr EnsureIsFinalized(Thread *thread) const
Definition: object.cc:4924
static bool TestCompileFunction(const Function &function)
Definition: unit_test.cc:781
static ExternalTypedDataPtr NewFinalizeWithFree(uint8_t *data, intptr_t len)
Definition: object.cc:25649
StringPtr GetSource() const
Definition: object.cc:11119
bool HasCode() const
Definition: object.cc:7936
bool HasOptimizedCode() const
Definition: object.cc:10974
static IsolateGroup * Current()
Definition: isolate.h:539
ClassTable * class_table() const
Definition: isolate.h:496
static bool IsRunning()
static Dart_KernelCompilationResult CompileExpressionToKernel(const uint8_t *platform_kernel, intptr_t platform_kernel_size, const char *expression, const Array &definitions, const Array &definition_types, const Array &type_definitions, const Array &type_bounds, const Array &type_defaults, const char *library_url, const char *klass, const char *method, TokenPosition token_pos, char const *script_uri, bool is_static)
static LibraryPtr CoreLibrary()
Definition: object.cc:14787
ClassPtr LookupClass(const String &name) const
Definition: object.cc:14105
StringPtr url() const
Definition: object.h:5097
static ObjectPtr null()
Definition: object.h:433
virtual const char * ToCString() const
Definition: object.h:366
bool IsNull() const
Definition: object.h:363
static Object & Handle()
Definition: object.h:407
static ObjectPtr RawCast(ObjectPtr obj)
Definition: object.h:325
static Object & ZoneHandle()
Definition: object.h:419
ClassPtr clazz() const
Definition: object.h:13218
Monitor::WaitResult Wait(int64_t millis=Monitor::kNoTimeout)
Definition: lockers.cc:77
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition: object.cc:23698
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition: object.cc:24126
static StringPtr New(Thread *thread, const char *cstr)
Definition: symbols.h:723
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
Definition: unit_test.cc:436
static Dart_Handle EvaluateExpression(const Library &lib, const String &expr, const Array &param_names, const Array &param_values)
Definition: unit_test.cc:660
@ Dart_KernelCompilationStatus_Ok
Definition: dart_api.h:3785
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
Definition: dart_vm.cc:33
constexpr intptr_t MB
Definition: globals.h:530
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction)
TEST_CASE(DirectoryCurrent)
Dart_Handle NewString(const char *str)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
#define Pd
Definition: globals.h:408
Dart_KernelCompilationStatus status
Definition: dart_api.h:3792
#define EXPECT_VALID(handle)
Definition: unit_test.h:643