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
5#include "vm/unit_test.h"
6
7#include <stdio.h>
8
9#include "bin/builtin.h"
10#include "bin/dartutils.h"
11#include "bin/isolate_data.h"
12
13#include "platform/globals.h"
14
15#include "vm/compiler/assembler/assembler.h"
16#include "vm/compiler/assembler/disassembler.h"
17#include "vm/compiler/jit/compiler.h"
18#include "vm/dart_api_impl.h"
19#include "vm/isolate_reload.h"
20#include "vm/kernel_isolate.h"
21#include "vm/parser.h"
22#include "vm/symbols.h"
23#include "vm/thread.h"
24#include "vm/virtual_memory.h"
25
26using dart::bin::Builtin;
27using dart::bin::DartUtils;
28
29extern "C" {
30extern const uint8_t kPlatformStrongDill[];
31extern intptr_t kPlatformStrongDillSize;
32}
33
34namespace dart {
35
36DECLARE_FLAG(bool, gc_during_reload);
37DECLARE_FLAG(bool, force_evacuation);
38
39const uint8_t* platform_strong_dill = kPlatformStrongDill;
40const intptr_t platform_strong_dill_size = kPlatformStrongDillSize;
41
42const uint8_t* TesterState::vm_snapshot_data = NULL;
43Dart_IsolateGroupCreateCallback TesterState::create_callback = NULL;
44Dart_IsolateShutdownCallback TesterState::shutdown_callback = NULL;
45Dart_IsolateGroupCleanupCallback TesterState::group_cleanup_callback = nullptr;
46const char** TesterState::argv = NULL;
47int TesterState::argc = 0;
48
49void KernelBufferList::AddBufferToList(const uint8_t* kernel_buffer) {
50 next_ = new KernelBufferList(kernel_buffer_, next_);
51 kernel_buffer_ = kernel_buffer;
52}
53
54TestCaseBase* TestCaseBase::first_ = NULL;
55TestCaseBase* TestCaseBase::tail_ = NULL;
56KernelBufferList* TestCaseBase::current_kernel_buffers_ = NULL;
57
58TestCaseBase::TestCaseBase(const char* name, const char* expectation)
59 : raw_test_(false),
60 next_(NULL),
61 name_(name),
62 expectation_(strlen(expectation) > 0 ? expectation : "Pass") {
63 if (first_ == NULL) {
64 first_ = this;
65 } else {
66 tail_->next_ = this;
67 }
68 tail_ = this;
69}
70
71void TestCaseBase::RunAllRaw() {
72 TestCaseBase* test = first_;
73 while (test != NULL) {
74 if (test->raw_test_) {
75 test->RunTest();
76 CleanupState();
77 }
78 test = test->next_;
79 }
80}
81
82void TestCaseBase::RunAll() {
83 TestCaseBase* test = first_;
84 while (test != NULL) {
85 if (!test->raw_test_) {
86 test->RunTest();
87 CleanupState();
88 }
89 test = test->next_;
90 }
91}
92
93void TestCaseBase::CleanupState() {
94 if (current_kernel_buffers_ != NULL) {
95 delete current_kernel_buffers_;
96 current_kernel_buffers_ = NULL;
97 }
98}
99
100void TestCaseBase::AddToKernelBuffers(const uint8_t* kernel_buffer) {
101 ASSERT(kernel_buffer != NULL);
102 if (current_kernel_buffers_ == NULL) {
103 current_kernel_buffers_ = new KernelBufferList(kernel_buffer);
104 } else {
105 current_kernel_buffers_->AddBufferToList(kernel_buffer);
106 }
107}
108
109Dart_Isolate TestCase::CreateIsolate(const uint8_t* data_buffer,
110 intptr_t len,
111 const uint8_t* instr_buffer,
112 const char* name,
113 void* group_data,
114 void* isolate_data) {
115 char* err;
116 Dart_IsolateFlags api_flags;
117 Isolate::FlagsInitialize(&api_flags);
118 api_flags.null_safety = (FLAG_sound_null_safety == kNullSafetyOptionStrong);
119 Dart_Isolate isolate = NULL;
120 if (len == 0) {
121 isolate = Dart_CreateIsolateGroup(
122 /*script_uri=*/name, /*name=*/name, data_buffer, instr_buffer,
123 &api_flags, group_data, isolate_data, &err);
124 } else {
125 isolate = Dart_CreateIsolateGroupFromKernel(/*script_uri=*/name,
126 /*name=*/name, data_buffer, len,
127 &api_flags, group_data,
128 isolate_data, &err);
129 }
130 if (isolate == NULL) {
131 OS::PrintErr("Creation of isolate failed '%s'\n", err);
132 free(err);
133 }
134
135 EXPECT(isolate != NULL);
136 return isolate;
137}
138
139Dart_Isolate TestCase::CreateTestIsolate(const char* name,
140 void* group_data,
141 void* isolate_data) {
142 return CreateIsolate(bin::core_isolate_snapshot_data,
143 0 /* Snapshots have length encoded within them. */,
144 bin::core_isolate_snapshot_instructions, name,
145 group_data, isolate_data);
146}
147
148void SetupCoreLibrariesForUnitTest() {
149 TransitionVMToNative transition(Thread::Current());
150
151 Dart_EnterScope();
152 bool ok = bin::DartUtils::SetOriginalWorkingDirectory();
153 RELEASE_ASSERT(ok);
154 Dart_Handle result = bin::DartUtils::PrepareForScriptLoading(
155 /*is_service_isolate=*/false,
156 /*trace_loading=*/false);
157 Dart_ExitScope();
158
159 RELEASE_ASSERT(!Dart_IsError(result));
160}
161
162Dart_Isolate TestCase::CreateTestIsolateInGroup(const char* name,
163 Dart_Isolate parent,
164 void* group_data,
165 void* isolate_data) {
166 char* error;
167#if defined(DART_PRECOMPILED_RUNTIME)
168 Isolate* result = CreateWithinExistingIsolateGroupAOT(
169 reinterpret_cast<Isolate*>(parent)->group(), name, &error);
170#else
171 Isolate* result = CreateWithinExistingIsolateGroup(
172 reinterpret_cast<Isolate*>(parent)->group(), name, &error);
173#endif
174 if (error != nullptr) {
175 OS::PrintErr("CreateTestIsolateInGroup failed: %s\n", error);
176 free(error);
177 }
178 EXPECT(result != nullptr);
179 return Api::CastIsolate(result);
180}
181
182struct TestLibEntry {
183 const char* url;
184 const char* source;
185};
186
187static MallocGrowableArray<TestLibEntry>* test_libs_ = NULL;
188
189const char* TestCase::url() {
190 return RESOLVED_USER_TEST_URI;
191}
192
193void TestCase::AddTestLib(const char* url, const char* source) {
194 if (test_libs_ == NULL) {
195 test_libs_ = new MallocGrowableArray<TestLibEntry>();
196 }
197 // If the test lib is already added, replace the source.
198 for (intptr_t i = 0; i < test_libs_->length(); i++) {
199 if (strcmp(url, (*test_libs_)[i].url) == 0) {
200 (*test_libs_)[i].source = source;
201 return;
202 }
203 }
204 TestLibEntry entry;
205 entry.url = url;
206 entry.source = source;
207 test_libs_->Add(entry);
208}
209
210const char* TestCase::GetTestLib(const char* url) {
211 if (test_libs_ == NULL) {
212 return NULL;
213 }
214 for (intptr_t i = 0; i < test_libs_->length(); i++) {
215 if (strcmp(url, (*test_libs_)[i].url) == 0) {
216 return (*test_libs_)[i].source;
217 }
218 }
219 return NULL;
220}
221
222bool TestCase::IsNNBD() {
223 return KernelIsolate::GetExperimentalFlag("non-nullable");
224}
225
226#ifndef PRODUCT
227static const char* kIsolateReloadTestLibSource =
228 "void reloadTest() native 'Test_Reload';\n"
229 "void collectNewSpace() native 'Test_CollectNewSpace';\n"
230 "void collectOldSpace() native 'Test_CollectOldSpace';\n";
231
232static const char* IsolateReloadTestLibUri() {
233 return "test:isolate_reload_helper";
234}
235
236#define RELOAD_NATIVE_LIST(V) \
237 V(Test_Reload, 0) \
238 V(Test_CollectNewSpace, 0) \
239 V(Test_CollectOldSpace, 0)
240
241RELOAD_NATIVE_LIST(DECLARE_FUNCTION);
242
243static struct NativeEntries {
244 const char* name_;
245 Dart_NativeFunction function_;
246 int argument_count_;
247} ReloadEntries[] = {RELOAD_NATIVE_LIST(REGISTER_FUNCTION)};
248
249static Dart_NativeFunction IsolateReloadTestNativeResolver(
250 Dart_Handle name,
251 int argument_count,
252 bool* auto_setup_scope) {
253 const char* function_name = NULL;
254 Dart_Handle result = Dart_StringToCString(name, &function_name);
255 ASSERT(!Dart_IsError(result));
256 ASSERT(function_name != NULL);
257 ASSERT(auto_setup_scope != NULL);
258 *auto_setup_scope = true;
259 int num_entries = sizeof(ReloadEntries) / sizeof(struct NativeEntries);
260 for (int i = 0; i < num_entries; i++) {
261 struct NativeEntries* entry = &(ReloadEntries[i]);
262 if ((strcmp(function_name, entry->name_) == 0) &&
263 (entry->argument_count_ == argument_count)) {
264 return reinterpret_cast<Dart_NativeFunction>(entry->function_);
265 }
266 }
267 return NULL;
268}
269
270void FUNCTION_NAME(Test_Reload)(Dart_NativeArguments native_args) {
271 Dart_Handle result = TestCase::TriggerReload(/* kernel_buffer= */ NULL,
272 /* kernel_buffer_size= */ 0);
273 if (Dart_IsError(result)) {
274 Dart_PropagateError(result);
275 }
276}
277
278void FUNCTION_NAME(Test_CollectNewSpace)(Dart_NativeArguments native_args) {
279 TransitionNativeToVM transition(Thread::Current());
280 GCTestHelper::CollectNewSpace();
281}
282
283void FUNCTION_NAME(Test_CollectOldSpace)(Dart_NativeArguments native_args) {
284 TransitionNativeToVM transition(Thread::Current());
285 GCTestHelper::CollectOldSpace();
286}
287
288static Dart_Handle LoadIsolateReloadTestLib() {
289 return TestCase::LoadTestLibrary(IsolateReloadTestLibUri(),
290 kIsolateReloadTestLibSource,
291 IsolateReloadTestNativeResolver);
292}
293#endif // !PRODUCT
294
295char* TestCase::CompileTestScriptWithDFE(const char* url,
296 const char* source,
297 const uint8_t** kernel_buffer,
298 intptr_t* kernel_buffer_size,
299 bool incrementally,
300 bool allow_compile_errors,
301 const char* multiroot_filepaths,
302 const char* multiroot_scheme) {
303 // clang-format off
304 Dart_SourceFile sourcefiles[] = {
305 {
306 url, source,
307 },
308 {
309 "file:///.packages", ""
310 }};
311 // clang-format on
312 return CompileTestScriptWithDFE(
313 url, sizeof(sourcefiles) / sizeof(Dart_SourceFile), sourcefiles,
314 kernel_buffer, kernel_buffer_size, incrementally, allow_compile_errors,
315 multiroot_filepaths, multiroot_scheme);
316}
317
318char* TestCase::CompileTestScriptWithDFE(const char* url,
319 int sourcefiles_count,
320 Dart_SourceFile sourcefiles[],
321 const uint8_t** kernel_buffer,
322 intptr_t* kernel_buffer_size,
323 bool incrementally,
324 bool allow_compile_errors,
325 const char* multiroot_filepaths,
326 const char* multiroot_scheme) {
327 Zone* zone = Thread::Current()->zone();
328 Dart_KernelCompilationResult result = KernelIsolate::CompileToKernel(
329 url, platform_strong_dill, platform_strong_dill_size, sourcefiles_count,
330 sourcefiles, incrementally, NULL, multiroot_filepaths, multiroot_scheme);
331 if (result.status == Dart_KernelCompilationStatus_Ok) {
332 if (KernelIsolate::AcceptCompilation().status !=
333 Dart_KernelCompilationStatus_Ok) {
334 FATAL(
335 "An error occurred in the CFE while accepting the most recent"
336 " compilation results.");
337 }
338 }
339 return ValidateCompilationResult(zone, result, kernel_buffer,
340 kernel_buffer_size, allow_compile_errors);
341}
342
343char* TestCase::ValidateCompilationResult(
344 Zone* zone,
345 Dart_KernelCompilationResult compilation_result,
346 const uint8_t** kernel_buffer,
347 intptr_t* kernel_buffer_size,
348 bool allow_compile_errors) {
349 if (!allow_compile_errors &&
350 (compilation_result.status != Dart_KernelCompilationStatus_Ok)) {
351 char* result =
352 OS::SCreate(zone, "Compilation failed %s", compilation_result.error);
353 free(compilation_result.error);
354 if (compilation_result.kernel != NULL) {
355 free(const_cast<uint8_t*>(compilation_result.kernel));
356 }
357 *kernel_buffer = NULL;
358 *kernel_buffer_size = 0;
359 return result;
360 }
361 *kernel_buffer = compilation_result.kernel;
362 *kernel_buffer_size = compilation_result.kernel_size;
363 if (compilation_result.error != NULL) {
364 free(compilation_result.error);
365 }
366 if (kernel_buffer == NULL) {
367 return OS::SCreate(zone, "front end generated a NULL kernel file");
368 }
369 return NULL;
370}
371
372static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
373 Dart_Handle library,
374 Dart_Handle url) {
375 if (tag == Dart_kCanonicalizeUrl) {
376 Dart_Handle library_url = Dart_LibraryUrl(library);
377 if (Dart_IsError(library_url)) {
378 return library_url;
379 }
380 return Dart_DefaultCanonicalizeUrl(library_url, url);
381 }
382 UNREACHABLE();
383 return Dart_Null();
384}
385
386static intptr_t BuildSourceFilesArray(
387 Dart_SourceFile** sourcefiles,
388 const char* script,
389 const char* script_url = RESOLVED_USER_TEST_URI) {
390 ASSERT(sourcefiles != NULL);
391 ASSERT(script != NULL);
392
393 intptr_t num_test_libs = 0;
394 if (test_libs_ != NULL) {
395 num_test_libs = test_libs_->length();
396 }
397
398 *sourcefiles = new Dart_SourceFile[num_test_libs + 1];
399 (*sourcefiles)[0].uri = script_url;
400 (*sourcefiles)[0].source = script;
401 for (intptr_t i = 0; i < num_test_libs; ++i) {
402 (*sourcefiles)[i + 1].uri = test_libs_->At(i).url;
403 (*sourcefiles)[i + 1].source = test_libs_->At(i).source;
404 }
405 return num_test_libs + 1;
406}
407
408Dart_Handle TestCase::LoadTestScriptWithErrors(
409 const char* script,
410 Dart_NativeEntryResolver resolver,
411 const char* lib_url,
412 bool finalize_classes) {
413 return LoadTestScript(script, resolver, lib_url, finalize_classes, true);
414}
415
416Dart_Handle TestCase::LoadTestScript(const char* script,
417 Dart_NativeEntryResolver resolver,
418 const char* lib_url,
419 bool finalize_classes,
420 bool allow_compile_errors) {
421#ifndef PRODUCT
422 if (strstr(script, IsolateReloadTestLibUri()) != NULL) {
423 Dart_Handle result = LoadIsolateReloadTestLib();
424 EXPECT_VALID(result);
425 }
426#endif // ifndef PRODUCT
427 Dart_SourceFile* sourcefiles = NULL;
428 intptr_t num_sources = BuildSourceFilesArray(&sourcefiles, script, lib_url);
429 Dart_Handle result =
430 LoadTestScriptWithDFE(num_sources, sourcefiles, resolver,
431 finalize_classes, true, allow_compile_errors);
432 delete[] sourcefiles;
433 return result;
434}
435
436Dart_Handle TestCase::LoadTestLibrary(const char* lib_uri,
437 const char* script,
438 Dart_NativeEntryResolver resolver) {
439 const char* prefixed_lib_uri =
440 OS::SCreate(Thread::Current()->zone(), "file:///%s", lib_uri);
441 Dart_SourceFile sourcefiles[] = {{prefixed_lib_uri, script}};
442 const uint8_t* kernel_buffer = NULL;
443 intptr_t kernel_buffer_size = 0;
444 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
445 char* error = TestCase::CompileTestScriptWithDFE(
446 sourcefiles[0].uri, sourcefiles_count, sourcefiles, &kernel_buffer,
447 &kernel_buffer_size, true);
448 if ((kernel_buffer == NULL) && (error != NULL)) {
449 return Dart_NewApiError(error);
450 }
451 Dart_Handle lib =
452 Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
453 EXPECT_VALID(lib);
454
455 // Ensure kernel buffer isn't leaked after test is run.
456 AddToKernelBuffers(kernel_buffer);
457
458 // TODO(32618): Kernel doesn't correctly represent the root library.
459 lib = Dart_LookupLibrary(Dart_NewStringFromCString(sourcefiles[0].uri));
460 EXPECT_VALID(lib);
461 Dart_Handle result = Dart_SetRootLibrary(lib);
462 EXPECT_VALID(result);
463
464 Dart_SetNativeResolver(lib, resolver, NULL);
465 return lib;
466}
467
468Dart_Handle TestCase::LoadTestScriptWithDFE(int sourcefiles_count,
469 Dart_SourceFile sourcefiles[],
470 Dart_NativeEntryResolver resolver,
471 bool finalize,
472 bool incrementally,
473 bool allow_compile_errors,
474 const char* entry_script_uri,
475 const char* multiroot_filepaths,
476 const char* multiroot_scheme) {
477 // First script is the main script.
478 Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler);
479 EXPECT_VALID(result);
480 const uint8_t* kernel_buffer = NULL;
481 intptr_t kernel_buffer_size = 0;
482 char* error = TestCase::CompileTestScriptWithDFE(
483 entry_script_uri != NULL ? entry_script_uri : sourcefiles[0].uri,
484 sourcefiles_count, sourcefiles, &kernel_buffer, &kernel_buffer_size,
485 incrementally, allow_compile_errors, multiroot_filepaths,
486 multiroot_scheme);
487 if ((kernel_buffer == NULL) && error != NULL) {
488 return Dart_NewApiError(error);
489 }
490
491 Dart_Handle lib =
492 Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
493 EXPECT_VALID(lib);
494
495 // Ensure kernel buffer isn't leaked after test is run.
496 AddToKernelBuffers(kernel_buffer);
497
498 // BOGUS: Kernel doesn't correctly represent the root library.
499 lib = Dart_LookupLibrary(Dart_NewStringFromCString(
500 entry_script_uri != NULL ? entry_script_uri : sourcefiles[0].uri));
501 EXPECT_VALID(lib);
502 result = Dart_SetRootLibrary(lib);
503 EXPECT_VALID(result);
504
505 result = Dart_SetNativeResolver(lib, resolver, NULL);
506 EXPECT_VALID(result);
507 if (finalize) {
508 result = Dart_FinalizeLoading(false);
509 EXPECT_VALID(result);
510 }
511 return lib;
512}
513
514#ifndef PRODUCT
515
516Dart_Handle TestCase::SetReloadTestScript(const char* script) {
517 // For our vm/cc/IsolateReload_* tests we flip the GC flag on, which will
518 // cause the isolate reload to do GCs before/after morphing, etc.
519 FLAG_gc_during_reload = true;
520 FLAG_force_evacuation = true;
521
522 Dart_SourceFile* sourcefiles = NULL;
523 intptr_t num_files = BuildSourceFilesArray(&sourcefiles, script);
524 Dart_KernelCompilationResult compilation_result =
525 KernelIsolate::UpdateInMemorySources(num_files, sourcefiles);
526 delete[] sourcefiles;
527 if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
528 Dart_Handle result = Dart_NewApiError(compilation_result.error);
529 free(compilation_result.error);
530 return result;
531 }
532 return Api::Success();
533}
534
535Dart_Handle TestCase::TriggerReload(const uint8_t* kernel_buffer,
536 intptr_t kernel_buffer_size) {
537 Thread* thread = Thread::Current();
538 Isolate* isolate = thread->isolate();
539 JSONStream js;
540 bool success = false;
541 {
542 TransitionNativeToVM transition(thread);
543 success =
544 isolate->group()->ReloadKernel(&js,
545 false, // force_reload
546 kernel_buffer, kernel_buffer_size,
547 true); // dont_delete_reload_context
548 OS::PrintErr("RELOAD REPORT:\n%s\n", js.ToCString());
549 }
550
551 Dart_Handle result = Dart_Null();
552 if (success) {
553 result = Dart_FinalizeLoading(false);
554 }
555
556 if (Dart_IsError(result)) {
557 // Keep load error.
558 } else if (isolate->group()->reload_context()->reload_aborted()) {
559 TransitionNativeToVM transition(thread);
560 result = Api::NewHandle(
561 thread, isolate->reload_context()->group_reload_context()->error());
562 } else {
563 result = Dart_RootLibrary();
564 }
565
566 TransitionNativeToVM transition(thread);
567 if (isolate->reload_context() != NULL) {
568 isolate->DeleteReloadContext();
569 isolate->group()->DeleteReloadContext();
570 }
571
572 return result;
573}
574
575Dart_Handle TestCase::ReloadTestScript(const char* script) {
576 Dart_SourceFile* sourcefiles = NULL;
577 intptr_t num_files = BuildSourceFilesArray(&sourcefiles, script);
578 Dart_KernelCompilationResult compilation_result =
579 KernelIsolate::UpdateInMemorySources(num_files, sourcefiles);
580 delete[] sourcefiles;
581 if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
582 Dart_Handle result = Dart_NewApiError(compilation_result.error);
583 free(compilation_result.error);
584 if (compilation_result.kernel != NULL) {
585 free(const_cast<uint8_t*>(compilation_result.kernel));
586 }
587 return result;
588 }
589
590 return TriggerReload(/* kernel_buffer= */ NULL, /* kernel_buffer_size= */ 0);
591}
592
593Dart_Handle TestCase::ReloadTestKernel(const uint8_t* kernel_buffer,
594 intptr_t kernel_buffer_size) {
595 return TriggerReload(kernel_buffer, kernel_buffer_size);
596}
597
598#endif // !PRODUCT
599
600Dart_Handle TestCase::LoadCoreTestScript(const char* script,
601 Dart_NativeEntryResolver resolver) {
602 return LoadTestScript(script, resolver, CORELIB_TEST_URI);
603}
604
605Dart_Handle TestCase::lib() {
606 Dart_Handle url = NewString(TestCase::url());
607 Dart_Handle lib = Dart_LookupLibrary(url);
608 EXPECT_VALID(lib);
609 ASSERT(Dart_IsLibrary(lib));
610 return lib;
611}
612
613Dart_Handle TestCase::library_handler(Dart_LibraryTag tag,
614 Dart_Handle library,
615 Dart_Handle url) {
616 if (tag == Dart_kCanonicalizeUrl) {
617 return url;
618 }
619 return Api::Success();
620}
621
622Dart_Handle TestCase::EvaluateExpression(const Library& lib,
623 const String& expr,
624 const Array& param_names,
625 const Array& param_values) {
626 Thread* thread = Thread::Current();
627
628 Object& val = Object::Handle();
629 if (!KernelIsolate::IsRunning()) {
630 UNREACHABLE();
631 } else {
632 Dart_KernelCompilationResult compilation_result =
633 KernelIsolate::CompileExpressionToKernel(
634 /* platform_kernel= */ nullptr, /* platform_kernel_size= */ 0,
635 expr.ToCString(), param_names, Array::empty_array(),
636 String::Handle(lib.url()).ToCString(), /* klass=*/nullptr,
637 /* is_static= */ true);
638 if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
639 return Api::NewError("%s", compilation_result.error);
640 }
641
642 const ExternalTypedData& kernel_buffer =
643 ExternalTypedData::Handle(ExternalTypedData::NewFinalizeWithFree(
644 const_cast<uint8_t*>(compilation_result.kernel),
645 compilation_result.kernel_size));
646
647 val = lib.EvaluateCompiledExpression(kernel_buffer, Array::empty_array(),
648 param_values,
649 TypeArguments::null_type_arguments());
650 }
651 return Api::NewHandle(thread, val.raw());
652}
653
654#if !defined(PRODUCT)
655static bool IsHex(int c) {
656 return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f');
657}
658#endif
659
660void AssemblerTest::Assemble() {
661 const String& function_name =
662 String::ZoneHandle(Symbols::New(Thread::Current(), name_));
663
664 // We make a dummy script so that exception objects can be composed for
665 // assembler instructions that do runtime calls.
666 const char* kDummyScript = "assembler_test_dummy_function() {}";
667 const Script& script = Script::Handle(
668 Script::New(function_name, String::Handle(String::New(kDummyScript))));
669 const Library& lib = Library::Handle(Library::CoreLibrary());
670 const Class& cls = Class::ZoneHandle(
671 Class::New(lib, function_name, script, TokenPosition::kMinSource));
672 Function& function = Function::ZoneHandle(Function::New(
673 function_name, FunctionLayout::kRegularFunction, true, false, false,
674 false, false, cls, TokenPosition::kMinSource));
675 code_ = Code::FinalizeCodeAndNotify(function, nullptr, assembler_,
676 Code::PoolAttachment::kAttachPool);
677 code_.set_owner(function);
678 code_.set_exception_handlers(Object::empty_exception_handlers());
679#ifndef PRODUCT
680 uword start = code_.PayloadStart();
681 if (FLAG_disassemble) {
682 OS::PrintErr("Code for test '%s' {\n", name_);
683 Disassembler::Disassemble(start, start + assembler_->CodeSize());
684 OS::PrintErr("}\n");
685 }
686 Disassembler::Disassemble(start, start + assembler_->CodeSize(), disassembly_,
687 DISASSEMBLY_SIZE);
688 // Blank out big hex constants, since they are not stable from run to run.
689 bool in_hex_constant = false;
690 for (char* p = disassembly_; *p != '\0'; p++) {
691 if (in_hex_constant) {
692 if (IsHex(*p)) {
693 *p = '.';
694 } else {
695 in_hex_constant = false;
696 }
697 } else {
698 if (*p == '0' && *(p + 1) == 'x' && IsHex(*(p + 2)) && IsHex(*(p + 3)) &&
699 IsHex(*(p + 4))) {
700 p++;
701 in_hex_constant = true;
702 }
703 }
704 }
705#endif // !PRODUCT
706}
707
708bool CompilerTest::TestCompileFunction(const Function& function) {
709 Thread* thread = Thread::Current();
710 ASSERT(thread != NULL);
711 ASSERT(ClassFinalizer::AllClassesFinalized());
712 const Object& result =
713 Object::Handle(Compiler::CompileFunction(thread, function));
714 return result.IsCode();
715}
716
717void ElideJSONSubstring(const char* prefix, const char* in, char* out) {
718 const char* pos = strstr(in, prefix);
719 while (pos != NULL) {
720 // Copy up to pos into the output buffer.
721 while (in < pos) {
722 *out++ = *in++;
723 }
724
725 // Skip to the close quote.
726 in += strcspn(in, "\"");
727 pos = strstr(in, prefix);
728 }
729 // Copy the remainder of in to out.
730 while (*in != '\0') {
731 *out++ = *in++;
732 }
733 *out = '\0';
734}
735
736} // namespace dart
737