OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // Generate a snapshot file after loading all the scripts specified on the | 5 // Generate a snapshot file after loading all the scripts specified on the |
6 // command line. | 6 // command line. |
7 | 7 |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <string.h> | 9 #include <string.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
11 | 11 |
| 12 #include <cstdarg> |
| 13 |
12 #include "include/dart_api.h" | 14 #include "include/dart_api.h" |
13 | 15 |
14 #include "bin/builtin.h" | 16 #include "bin/builtin.h" |
15 #include "bin/dartutils.h" | 17 #include "bin/dartutils.h" |
16 #include "bin/eventhandler.h" | 18 #include "bin/eventhandler.h" |
17 #include "bin/file.h" | 19 #include "bin/file.h" |
18 #include "bin/log.h" | 20 #include "bin/log.h" |
19 #include "bin/thread.h" | 21 #include "bin/thread.h" |
20 #include "bin/vmservice_impl.h" | 22 #include "bin/vmservice_impl.h" |
21 | 23 |
22 #include "platform/globals.h" | 24 #include "platform/globals.h" |
23 | 25 |
24 | 26 |
25 namespace dart { | 27 namespace dart { |
26 namespace bin { | 28 namespace bin { |
27 | 29 |
28 #define CHECK_RESULT(result) \ | 30 #define CHECK_RESULT(result) \ |
29 if (Dart_IsError(result)) { \ | 31 if (Dart_IsError(result)) { \ |
30 Log::PrintErr("Error: %s", Dart_GetError(result)); \ | 32 Log::PrintErr("Error: %s", Dart_GetError(result)); \ |
31 Dart_ExitScope(); \ | 33 Dart_ExitScope(); \ |
32 Dart_ShutdownIsolate(); \ | 34 Dart_ShutdownIsolate(); \ |
33 exit(255); \ | 35 exit(255); \ |
34 } \ | 36 } \ |
35 | 37 |
36 | 38 |
37 // Global state that indicates whether a snapshot is to be created and | 39 // Global state that indicates whether a snapshot is to be created and |
38 // if so which file to write the snapshot into. | 40 // if so which file to write the snapshot into. |
39 static const char* vm_isolate_snapshot_filename = NULL; | 41 static const char* vm_isolate_snapshot_filename = NULL; |
40 static const char* isolate_snapshot_filename = NULL; | 42 static const char* isolate_snapshot_filename = NULL; |
| 43 static const char* instructions_snapshot_filename = NULL; |
| 44 static const char* embedder_entry_points_manifest = NULL; |
41 static const char* package_root = NULL; | 45 static const char* package_root = NULL; |
42 | 46 |
43 | 47 |
44 // Global state which contains a pointer to the script name for which | 48 // Global state which contains a pointer to the script name for which |
45 // a snapshot needs to be created (NULL would result in the creation | 49 // a snapshot needs to be created (NULL would result in the creation |
46 // of a generic snapshot that contains only the corelibs). | 50 // of a generic snapshot that contains only the corelibs). |
47 static char* app_script_name = NULL; | 51 static char* app_script_name = NULL; |
48 | 52 |
49 | 53 |
50 // Global state that captures the URL mappings specified on the command line. | 54 // Global state that captures the URL mappings specified on the command line. |
(...skipping 30 matching lines...) Expand all Loading... |
81 static bool ProcessIsolateSnapshotOption(const char* option) { | 85 static bool ProcessIsolateSnapshotOption(const char* option) { |
82 const char* name = ProcessOption(option, "--isolate_snapshot="); | 86 const char* name = ProcessOption(option, "--isolate_snapshot="); |
83 if (name != NULL) { | 87 if (name != NULL) { |
84 isolate_snapshot_filename = name; | 88 isolate_snapshot_filename = name; |
85 return true; | 89 return true; |
86 } | 90 } |
87 return false; | 91 return false; |
88 } | 92 } |
89 | 93 |
90 | 94 |
| 95 static bool ProcessInstructionsSnapshotOption(const char* option) { |
| 96 const char* name = ProcessOption(option, "--instructions_snapshot="); |
| 97 if (name != NULL) { |
| 98 instructions_snapshot_filename = name; |
| 99 return true; |
| 100 } |
| 101 return false; |
| 102 } |
| 103 |
| 104 |
| 105 static bool ProcessEmbedderEntryPointsManifestOption(const char* option) { |
| 106 const char* name = ProcessOption(option, "--embedder_entry_points_manifest="); |
| 107 if (name != NULL) { |
| 108 embedder_entry_points_manifest = name; |
| 109 return true; |
| 110 } |
| 111 return false; |
| 112 } |
| 113 |
| 114 |
91 static bool ProcessPackageRootOption(const char* option) { | 115 static bool ProcessPackageRootOption(const char* option) { |
92 const char* name = ProcessOption(option, "--package_root="); | 116 const char* name = ProcessOption(option, "--package_root="); |
93 if (name != NULL) { | 117 if (name != NULL) { |
94 package_root = name; | 118 package_root = name; |
95 return true; | 119 return true; |
96 } | 120 } |
97 return false; | 121 return false; |
98 } | 122 } |
99 | 123 |
100 | 124 |
(...skipping 19 matching lines...) Expand all Loading... |
120 const char* kPrefix = "--"; | 144 const char* kPrefix = "--"; |
121 const intptr_t kPrefixLen = strlen(kPrefix); | 145 const intptr_t kPrefixLen = strlen(kPrefix); |
122 | 146 |
123 // Skip the binary name. | 147 // Skip the binary name. |
124 int i = 1; | 148 int i = 1; |
125 | 149 |
126 // Parse out the vm options. | 150 // Parse out the vm options. |
127 while ((i < argc) && IsValidFlag(argv[i], kPrefix, kPrefixLen)) { | 151 while ((i < argc) && IsValidFlag(argv[i], kPrefix, kPrefixLen)) { |
128 if (ProcessVmIsolateSnapshotOption(argv[i]) || | 152 if (ProcessVmIsolateSnapshotOption(argv[i]) || |
129 ProcessIsolateSnapshotOption(argv[i]) || | 153 ProcessIsolateSnapshotOption(argv[i]) || |
| 154 ProcessInstructionsSnapshotOption(argv[i]) || |
| 155 ProcessEmbedderEntryPointsManifestOption(argv[i]) || |
130 ProcessURLmappingOption(argv[i]) || | 156 ProcessURLmappingOption(argv[i]) || |
131 ProcessPackageRootOption(argv[i])) { | 157 ProcessPackageRootOption(argv[i])) { |
132 i += 1; | 158 i += 1; |
133 continue; | 159 continue; |
134 } | 160 } |
135 vm_options->AddArgument(argv[i]); | 161 vm_options->AddArgument(argv[i]); |
136 i += 1; | 162 i += 1; |
137 } | 163 } |
138 | 164 |
139 // Get the script name. | 165 // Get the script name. |
140 if (i < argc) { | 166 if (i < argc) { |
141 *script_name = argv[i]; | 167 *script_name = argv[i]; |
142 i += 1; | 168 i += 1; |
143 } else { | 169 } else { |
144 *script_name = NULL; | 170 *script_name = NULL; |
145 } | 171 } |
146 | 172 |
147 if (vm_isolate_snapshot_filename == NULL) { | 173 if (vm_isolate_snapshot_filename == NULL) { |
148 Log::PrintErr("No vm isolate snapshot output file specified.\n\n"); | 174 Log::PrintErr("No vm isolate snapshot output file specified.\n\n"); |
149 return -1; | 175 return -1; |
150 } | 176 } |
151 | 177 |
152 if (isolate_snapshot_filename == NULL) { | 178 if (isolate_snapshot_filename == NULL) { |
153 Log::PrintErr("No isolate snapshot output file specified.\n\n"); | 179 Log::PrintErr("No isolate snapshot output file specified.\n\n"); |
154 return -1; | 180 return -1; |
155 } | 181 } |
156 | 182 |
| 183 if (instructions_snapshot_filename != NULL && |
| 184 embedder_entry_points_manifest == NULL) { |
| 185 Log::PrintErr( |
| 186 "Specifying an instructions snapshot filename indicates precompilation" |
| 187 ". But no embedder entry points manifest was specified.\n\n"); |
| 188 return -1; |
| 189 } |
| 190 |
| 191 if (embedder_entry_points_manifest != NULL && |
| 192 instructions_snapshot_filename == NULL) { |
| 193 Log::PrintErr( |
| 194 "Specifying the embedder entry points manifest indicates " |
| 195 "precompilation. But no instuctions snapshot was specified.\n\n"); |
| 196 return -1; |
| 197 } |
| 198 |
157 return 0; | 199 return 0; |
158 } | 200 } |
159 | 201 |
160 | 202 |
| 203 static bool IsSnapshottingForPrecompilation(void) { |
| 204 return embedder_entry_points_manifest != NULL && |
| 205 instructions_snapshot_filename != NULL; |
| 206 } |
| 207 |
| 208 |
161 static void WriteSnapshotFile(const char* filename, | 209 static void WriteSnapshotFile(const char* filename, |
162 const uint8_t* buffer, | 210 const uint8_t* buffer, |
163 const intptr_t size) { | 211 const intptr_t size) { |
164 File* file = File::Open(filename, File::kWriteTruncate); | 212 File* file = File::Open(filename, File::kWriteTruncate); |
165 ASSERT(file != NULL); | 213 ASSERT(file != NULL); |
166 if (!file->WriteFully(buffer, size)) { | 214 if (!file->WriteFully(buffer, size)) { |
167 Log::PrintErr("Error: Failed to write snapshot file.\n\n"); | 215 Log::PrintErr("Error: Failed to write snapshot file.\n\n"); |
168 } | 216 } |
169 delete file; | 217 delete file; |
170 } | 218 } |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 Dart_Handle lib; | 461 Dart_Handle lib; |
414 // Load the builtin library to make it available in the snapshot | 462 // Load the builtin library to make it available in the snapshot |
415 // for importing. | 463 // for importing. |
416 lib = Builtin::LoadAndCheckLibrary(id); | 464 lib = Builtin::LoadAndCheckLibrary(id); |
417 ASSERT(!Dart_IsError(lib)); | 465 ASSERT(!Dart_IsError(lib)); |
418 return lib; | 466 return lib; |
419 } | 467 } |
420 | 468 |
421 | 469 |
422 static void PrintUsage() { | 470 static void PrintUsage() { |
423 Log::PrintErr( | 471 #define STRINGERIZE(...) #__VA_ARGS__ |
424 "Usage:\n" | 472 // clang-format off |
425 "\n" | 473 Log::PrintErr(STRINGERIZE( |
426 " gen_snapshot [<vm-flags>] [<options>] \\\n" | 474 Usage: \n |
427 " --snapshot=<out-file> [<dart-script-file>]\n" | 475 gen_snapshot [<vm-flags>] [<options>] [<dart-script-file>] \n |
428 "\n" | 476 \n |
429 " Writes a snapshot of <dart-script-file> to <out-file>. If no\n" | 477 Writes a snapshot of <dart-script-file> to the specified snapshot files. If \n |
430 " <dart-script-file> is passed, a generic snapshot of all the corelibs is\n" | 478 no <dart-script-file> is passed, a generic snapshot of all the corelibs is \n |
431 " created. It is required to specify an output file name:\n" | 479 created. It is required to specify the VM isolate snapshot and the isolate \n |
432 "\n" | 480 snapshot. The other flags are related to precompilation and are optional. \n |
433 " --snapshot=<file> Generates a complete snapshot. Uses the url\n" | 481 \n |
434 " mapping specified on the command line to load\n" | 482 Precompilation: \n |
435 " the libraries.\n" | 483 In order to configure the snapshotter for precompilation, both the \n |
436 "Supported options:\n" | 484 instructions snapshot and embedder entry points manifest must be specified. \n |
437 "\n" | 485 Machine code for the target architecture will be dumped into the \n |
438 "--package_root=<path>\n" | 486 instructions snapshot. This must be linked into the target binary in a \n |
439 " Where to find packages, that is, \"package:...\" imports.\n" | 487 separate step. The embedder entry points manifest lists the standalone entry\n |
440 "\n" | 488 points into the VM. Not specifying these will cause the tree shaker to \n |
441 "--url_mapping=<mapping>\n" | 489 disregard the same as being used. The format of this manifest is as follows.\n |
442 " Uses the URL mapping(s) specified on the command line to load the\n" | 490 Each line in the manifest is a comma separated list of three elements. The \n |
443 " libraries. For use only with --snapshot=.\n"); | 491 first entry is the library URI, the second entry is the class name and the \n |
| 492 final entry the function name. The file must be terminated with a newline \n |
| 493 charater. \n |
| 494 \n |
| 495 Example: \n |
| 496 dart:something,SomeClass,doSomething \n |
| 497 \n |
| 498 Supported options: \n |
| 499 --vm_isolate_snapshot=<file> A full snapshot is a compact \n |
| 500 --isolate_snapshot=<file> representation of the dart vm isolate \n |
| 501 heap and dart isolate heap states. \n |
| 502 Both these options are required \n |
| 503 \n |
| 504 --package_root=<path> Where to find packages, that is, \n |
| 505 package:... imports. \n |
| 506 \n |
| 507 --url_mapping=<mapping> Uses the URL mapping(s) specified on the\n |
| 508 command line to load the libraries. \n |
| 509 \n |
| 510 --instructions_snapshot=<file> (Precompilation only) Contains the \n |
| 511 assembly that must be linked into \n |
| 512 the target binary \n |
| 513 \n |
| 514 --embedder_entry_points_manifest=<file> (Precompilation only) Contains the\n |
| 515 stanalone embedder entry points \n |
| 516 )); |
| 517 // clang-format on |
| 518 #undef STRINGERIZE |
444 } | 519 } |
445 | 520 |
446 | 521 |
447 static void VerifyLoaded(Dart_Handle library) { | 522 static void VerifyLoaded(Dart_Handle library) { |
448 if (Dart_IsError(library)) { | 523 if (Dart_IsError(library)) { |
449 const char* err_msg = Dart_GetError(library); | 524 const char* err_msg = Dart_GetError(library); |
450 Log::PrintErr("Errors encountered while loading: %s\n", err_msg); | 525 Log::PrintErr("Errors encountered while loading: %s\n", err_msg); |
451 Dart_ExitScope(); | 526 Dart_ExitScope(); |
452 Dart_ShutdownIsolate(); | 527 Dart_ShutdownIsolate(); |
453 exit(255); | 528 exit(255); |
454 } | 529 } |
455 ASSERT(Dart_IsLibrary(library)); | 530 ASSERT(Dart_IsLibrary(library)); |
456 } | 531 } |
457 | 532 |
458 | 533 |
| 534 static const char StubNativeFunctionName[] = "StubNativeFunction"; |
| 535 |
| 536 |
| 537 void StubNativeFunction(Dart_NativeArguments arguments) { |
| 538 // This is a stub function for the resolver |
| 539 UNREACHABLE(); |
| 540 } |
| 541 |
| 542 |
| 543 static Dart_NativeFunction StubNativeLookup(Dart_Handle name, |
| 544 int argument_count, |
| 545 bool* auto_setup_scope) { |
| 546 return &StubNativeFunction; |
| 547 } |
| 548 |
| 549 |
| 550 static const uint8_t* StubNativeSymbol(Dart_NativeFunction nf) { |
| 551 return reinterpret_cast<const uint8_t *>(StubNativeFunctionName); |
| 552 } |
| 553 |
| 554 |
| 555 static void SetupStubNativeResolver(size_t lib_index, |
| 556 const Dart_QualifiedFunctionName* entry) { |
| 557 // TODO(24686): Remove this. |
| 558 Dart_Handle library_string = Dart_NewStringFromCString(entry->library_uri); |
| 559 DART_CHECK_VALID(library_string); |
| 560 Dart_Handle library = Dart_LookupLibrary(library_string); |
| 561 // Embedder entry points may be setup in libraries that have not been |
| 562 // explicitly loaded by the application script. In such cases, library lookup |
| 563 // will fail. Manually load those libraries. |
| 564 if (Dart_IsError(library)) { |
| 565 static const uint32_t kLoadBufferMaxSize = 128; |
| 566 char* load_buffer = |
| 567 reinterpret_cast<char*>(calloc(kLoadBufferMaxSize, sizeof(char))); |
| 568 snprintf(load_buffer, |
| 569 kLoadBufferMaxSize, |
| 570 "import '%s';", |
| 571 DartUtils::GetStringValue(library_string)); |
| 572 Dart_Handle script_handle = Dart_NewStringFromCString(load_buffer); |
| 573 memset(load_buffer, 0, kLoadBufferMaxSize); |
| 574 snprintf(load_buffer, |
| 575 kLoadBufferMaxSize, |
| 576 "dart:_snapshot_%zu", |
| 577 lib_index); |
| 578 Dart_Handle script_url = Dart_NewStringFromCString(load_buffer); |
| 579 free(load_buffer); |
| 580 Dart_Handle loaded = Dart_LoadLibrary(script_url, script_handle, 0, 0); |
| 581 DART_CHECK_VALID(loaded); |
| 582 |
| 583 // Do a fresh lookup |
| 584 library = Dart_LookupLibrary(library_string); |
| 585 } |
| 586 |
| 587 DART_CHECK_VALID(library); |
| 588 Dart_Handle result = Dart_SetNativeResolver(library, |
| 589 &StubNativeLookup, |
| 590 &StubNativeSymbol); |
| 591 DART_CHECK_VALID(result); |
| 592 } |
| 593 |
| 594 |
| 595 static void ImportNativeEntryPointLibrariesIntoRoot( |
| 596 const Dart_QualifiedFunctionName* entries) { |
| 597 if (entries == NULL) { |
| 598 return; |
| 599 } |
| 600 |
| 601 size_t index = 0; |
| 602 while (true) { |
| 603 Dart_QualifiedFunctionName entry = entries[index++]; |
| 604 if (entry.library_uri == NULL) { |
| 605 // The termination sentinel has null members. |
| 606 break; |
| 607 } |
| 608 Dart_Handle entry_library = |
| 609 Dart_LookupLibrary(Dart_NewStringFromCString(entry.library_uri)); |
| 610 DART_CHECK_VALID(entry_library); |
| 611 Dart_Handle import_result = Dart_LibraryImportLibrary( |
| 612 entry_library, Dart_RootLibrary(), Dart_EmptyString()); |
| 613 DART_CHECK_VALID(import_result); |
| 614 } |
| 615 } |
| 616 |
| 617 |
| 618 static void SetupStubNativeResolversForPrecompilation( |
| 619 const Dart_QualifiedFunctionName* entries) { |
| 620 |
| 621 if (entries == NULL) { |
| 622 return; |
| 623 } |
| 624 |
| 625 // Setup native resolvers for all libraries found in the manifest. |
| 626 size_t index = 0; |
| 627 while (true) { |
| 628 Dart_QualifiedFunctionName entry = entries[index++]; |
| 629 if (entry.library_uri == NULL) { |
| 630 // The termination sentinel has null members. |
| 631 break; |
| 632 } |
| 633 // Setup stub resolvers on loaded libraries |
| 634 SetupStubNativeResolver(index, &entry); |
| 635 } |
| 636 } |
| 637 |
| 638 |
| 639 static void CleanupEntryPointItem(const Dart_QualifiedFunctionName *entry) { |
| 640 if (entry == NULL) { |
| 641 return; |
| 642 } |
| 643 // The allocation used for these entries is zero'ed. So even in error cases, |
| 644 // references to some entries will be null. Calling this on an already cleaned |
| 645 // up entry is programmer error. |
| 646 free(const_cast<char*>(entry->library_uri)); |
| 647 free(const_cast<char*>(entry->class_name)); |
| 648 free(const_cast<char*>(entry->function_name)); |
| 649 } |
| 650 |
| 651 |
| 652 static void CleanupEntryPointsCollection(Dart_QualifiedFunctionName* entries) { |
| 653 if (entries == NULL) { |
| 654 return; |
| 655 } |
| 656 |
| 657 size_t index = 0; |
| 658 while (true) { |
| 659 Dart_QualifiedFunctionName entry = entries[index++]; |
| 660 if (entry.library_uri == NULL) { |
| 661 break; |
| 662 } |
| 663 CleanupEntryPointItem(&entry); |
| 664 } |
| 665 free(entries); |
| 666 } |
| 667 |
| 668 |
| 669 char* ParserErrorStringCreate(const char* format, ...) { |
| 670 static const size_t kErrorBufferSize = 256; |
| 671 |
| 672 char* error_buffer = |
| 673 reinterpret_cast<char*>(calloc(kErrorBufferSize, sizeof(char))); |
| 674 va_list args; |
| 675 va_start(args, format); |
| 676 vsnprintf(error_buffer, kErrorBufferSize, format, args); |
| 677 va_end(args); |
| 678 |
| 679 // In case of error, the buffer is released by the caller |
| 680 return error_buffer; |
| 681 } |
| 682 |
| 683 |
| 684 const char* ParseEntryNameForIndex(uint8_t index) { |
| 685 switch (index) { |
| 686 case 0: |
| 687 return "Library"; |
| 688 case 1: |
| 689 return "Class"; |
| 690 case 2: |
| 691 return "Function"; |
| 692 default: |
| 693 return "Unknown"; |
| 694 } |
| 695 return NULL; |
| 696 } |
| 697 |
| 698 |
| 699 static bool ParseEntryPointsManifestSingleLine( |
| 700 const char* line, Dart_QualifiedFunctionName* entry, char** error) { |
| 701 bool success = true; |
| 702 size_t offset = 0; |
| 703 for (uint8_t i = 0; i < 3; i++) { |
| 704 const char* component = strchr(line + offset, i == 2 ? '\n' : ','); |
| 705 if (component == NULL) { |
| 706 success = false; |
| 707 *error = ParserErrorStringCreate( |
| 708 "Manifest entries must be comma separated and newline terminated. " |
| 709 "Could not parse '%s' on line '%s'", |
| 710 ParseEntryNameForIndex(i), line); |
| 711 break; |
| 712 } |
| 713 |
| 714 int64_t chars_read = component - (line + offset); |
| 715 if (chars_read <= 0) { |
| 716 success = false; |
| 717 *error = |
| 718 ParserErrorStringCreate("There is no '%s' specified on line '%s'", |
| 719 ParseEntryNameForIndex(i), line); |
| 720 break; |
| 721 } |
| 722 |
| 723 if (entry != NULL) { |
| 724 // These allocations are collected in |CleanupEntryPointsCollection|. |
| 725 char* entry_item = |
| 726 reinterpret_cast<char*>(calloc(chars_read + 1, sizeof(char))); |
| 727 memcpy(entry_item, line + offset, chars_read); |
| 728 |
| 729 switch (i) { |
| 730 case 0: // library |
| 731 entry->library_uri = entry_item; |
| 732 break; |
| 733 case 1: // class |
| 734 entry->class_name = entry_item; |
| 735 break; |
| 736 case 2: // function |
| 737 entry->function_name = entry_item; |
| 738 break; |
| 739 default: |
| 740 free(entry_item); |
| 741 success = false; |
| 742 *error = ParserErrorStringCreate("Internal parser error\n"); |
| 743 break; |
| 744 } |
| 745 } |
| 746 |
| 747 offset += chars_read + 1; |
| 748 } |
| 749 return success; |
| 750 } |
| 751 |
| 752 |
| 753 int64_t ParseEntryPointsManifestLines(FILE* file, |
| 754 Dart_QualifiedFunctionName* collection) { |
| 755 int64_t entries = 0; |
| 756 |
| 757 static const int kManifestMaxLineLength = 1024; |
| 758 char* line = reinterpret_cast<char*>(malloc(kManifestMaxLineLength)); |
| 759 size_t line_number = 0; |
| 760 while (true) { |
| 761 line_number++; |
| 762 char* read_line = fgets(line, kManifestMaxLineLength, file); |
| 763 |
| 764 if (read_line == NULL) { |
| 765 if ((feof(file) != 0) && (ferror(file) != 0)) { |
| 766 Log::PrintErr( |
| 767 "Error while reading line number %zu. The manifest must be " |
| 768 "terminated by a newline\n", |
| 769 line_number); |
| 770 entries = -1; |
| 771 } |
| 772 break; |
| 773 } |
| 774 |
| 775 Dart_QualifiedFunctionName* entry = |
| 776 collection != NULL ? collection + entries : NULL; |
| 777 |
| 778 char* error_buffer = NULL; |
| 779 if (!ParseEntryPointsManifestSingleLine(read_line, entry, &error_buffer)) { |
| 780 CleanupEntryPointItem(entry); |
| 781 Log::PrintErr("Parser error on line %zu: %s\n", line_number, |
| 782 error_buffer); |
| 783 free(error_buffer); |
| 784 entries = -1; |
| 785 break; |
| 786 } |
| 787 |
| 788 entries++; |
| 789 } |
| 790 |
| 791 free(line); |
| 792 |
| 793 return entries; |
| 794 } |
| 795 |
| 796 |
| 797 static Dart_QualifiedFunctionName* ParseEntryPointsManifestFile( |
| 798 const char* path) { |
| 799 if (path == NULL) { |
| 800 return NULL; |
| 801 } |
| 802 |
| 803 FILE* file = fopen(path, "r"); |
| 804 |
| 805 if (file == NULL) { |
| 806 Log::PrintErr("Could not open entry points manifest file\n"); |
| 807 return NULL; |
| 808 } |
| 809 |
| 810 // Parse the file once but don't store the results. This is done to first |
| 811 // determine the number of entries in the manifest |
| 812 int64_t entry_count = ParseEntryPointsManifestLines(file, NULL); |
| 813 |
| 814 if (entry_count <= 0) { |
| 815 Log::PrintErr( |
| 816 "Manifest file specified is invalid or contained no entries\n"); |
| 817 fclose(file); |
| 818 return NULL; |
| 819 } |
| 820 |
| 821 rewind(file); |
| 822 |
| 823 // Allocate enough storage for the entries in the file plus a termination |
| 824 // sentinel and parse it again to populate the allocation |
| 825 Dart_QualifiedFunctionName* entries = |
| 826 reinterpret_cast<Dart_QualifiedFunctionName*>( |
| 827 calloc(entry_count + 1, sizeof(Dart_QualifiedFunctionName))); |
| 828 |
| 829 int64_t parsed_entry_count = ParseEntryPointsManifestLines(file, entries); |
| 830 ASSERT(parsed_entry_count == entry_count); |
| 831 |
| 832 fclose(file); |
| 833 |
| 834 // The entries allocation must be explicitly cleaned up via |
| 835 // |CleanupEntryPointsCollection| |
| 836 return entries; |
| 837 } |
| 838 |
| 839 |
| 840 static Dart_QualifiedFunctionName* ParseEntryPointsManifestIfPresent() { |
| 841 Dart_QualifiedFunctionName* entries = |
| 842 ParseEntryPointsManifestFile(embedder_entry_points_manifest); |
| 843 if (entries == NULL && IsSnapshottingForPrecompilation()) { |
| 844 Log::PrintErr( |
| 845 "Could not find native embedder entry points during precompilation\n"); |
| 846 exit(255); |
| 847 } |
| 848 return entries; |
| 849 } |
| 850 |
| 851 |
459 static void CreateAndWriteSnapshot() { | 852 static void CreateAndWriteSnapshot() { |
| 853 ASSERT(!IsSnapshottingForPrecompilation()); |
460 Dart_Handle result; | 854 Dart_Handle result; |
461 uint8_t* vm_isolate_buffer = NULL; | 855 uint8_t* vm_isolate_buffer = NULL; |
462 intptr_t vm_isolate_size = 0; | 856 intptr_t vm_isolate_size = 0; |
463 uint8_t* isolate_buffer = NULL; | 857 uint8_t* isolate_buffer = NULL; |
464 intptr_t isolate_size = 0; | 858 intptr_t isolate_size = 0; |
465 | 859 |
466 // First create a snapshot. | 860 // First create a snapshot. |
467 result = Dart_CreateSnapshot(&vm_isolate_buffer, | 861 result = Dart_CreateSnapshot(&vm_isolate_buffer, |
468 &vm_isolate_size, | 862 &vm_isolate_size, |
469 &isolate_buffer, | 863 &isolate_buffer, |
470 &isolate_size); | 864 &isolate_size); |
471 CHECK_RESULT(result); | 865 CHECK_RESULT(result); |
472 | 866 |
473 // Now write the vm isolate and isolate snapshots out to the | 867 // Now write the vm isolate and isolate snapshots out to the |
474 // specified file and exit. | 868 // specified file and exit. |
475 WriteSnapshotFile(vm_isolate_snapshot_filename, | 869 WriteSnapshotFile(vm_isolate_snapshot_filename, |
476 vm_isolate_buffer, | 870 vm_isolate_buffer, |
477 vm_isolate_size); | 871 vm_isolate_size); |
478 WriteSnapshotFile(isolate_snapshot_filename, | 872 WriteSnapshotFile(isolate_snapshot_filename, |
479 isolate_buffer, | 873 isolate_buffer, |
480 isolate_size); | 874 isolate_size); |
481 Dart_ExitScope(); | 875 Dart_ExitScope(); |
482 | 876 |
483 // Shutdown the isolate. | 877 // Shutdown the isolate. |
484 Dart_ShutdownIsolate(); | 878 Dart_ShutdownIsolate(); |
485 } | 879 } |
486 | 880 |
487 | 881 |
| 882 static void CreateAndWritePrecompiledSnapshot( |
| 883 Dart_QualifiedFunctionName* standalone_entry_points) { |
| 884 ASSERT(IsSnapshottingForPrecompilation()); |
| 885 Dart_Handle result; |
| 886 uint8_t* vm_isolate_buffer = NULL; |
| 887 intptr_t vm_isolate_size = 0; |
| 888 uint8_t* isolate_buffer = NULL; |
| 889 intptr_t isolate_size = 0; |
| 890 uint8_t* instructions_buffer = NULL; |
| 891 intptr_t instructions_size = 0; |
| 892 |
| 893 // Precompile with specified embedder entry points |
| 894 result = Dart_Precompile(standalone_entry_points, true); |
| 895 CHECK_RESULT(result); |
| 896 |
| 897 // Create a precompiled snapshot. This gives us an instruction buffer with |
| 898 // machine code |
| 899 result = Dart_CreatePrecompiledSnapshot(&vm_isolate_buffer, |
| 900 &vm_isolate_size, |
| 901 &isolate_buffer, |
| 902 &isolate_size, |
| 903 &instructions_buffer, |
| 904 &instructions_size); |
| 905 CHECK_RESULT(result); |
| 906 |
| 907 // Now write the vm isolate, isolate and instructions snapshots out to the |
| 908 // specified files and exit. |
| 909 WriteSnapshotFile(vm_isolate_snapshot_filename, |
| 910 vm_isolate_buffer, |
| 911 vm_isolate_size); |
| 912 WriteSnapshotFile(isolate_snapshot_filename, |
| 913 isolate_buffer, |
| 914 isolate_size); |
| 915 WriteSnapshotFile(instructions_snapshot_filename, |
| 916 instructions_buffer, |
| 917 instructions_size); |
| 918 Dart_ExitScope(); |
| 919 |
| 920 // Shutdown the isolate. |
| 921 Dart_ShutdownIsolate(); |
| 922 } |
| 923 |
| 924 |
488 static void SetupForUriResolution() { | 925 static void SetupForUriResolution() { |
489 // Set up the library tag handler for this isolate. | 926 // Set up the library tag handler for this isolate. |
490 Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler); | 927 Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler); |
491 if (Dart_IsError(result)) { | 928 if (Dart_IsError(result)) { |
492 Log::PrintErr("%s", Dart_GetError(result)); | 929 Log::PrintErr("%s", Dart_GetError(result)); |
493 Dart_ExitScope(); | 930 Dart_ExitScope(); |
494 Dart_ShutdownIsolate(); | 931 Dart_ShutdownIsolate(); |
495 exit(255); | 932 exit(255); |
496 } | 933 } |
497 // This is a generic dart snapshot which needs builtin library setup. | 934 // This is a generic dart snapshot which needs builtin library setup. |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 | 1019 |
583 Thread::InitOnce(); | 1020 Thread::InitOnce(); |
584 DartUtils::SetOriginalWorkingDirectory(); | 1021 DartUtils::SetOriginalWorkingDirectory(); |
585 // Start event handler. | 1022 // Start event handler. |
586 EventHandler::Start(); | 1023 EventHandler::Start(); |
587 | 1024 |
588 vm_options.AddArgument("--load_deferred_eagerly"); | 1025 vm_options.AddArgument("--load_deferred_eagerly"); |
589 // Workaround until issue 21620 is fixed. | 1026 // Workaround until issue 21620 is fixed. |
590 // (https://github.com/dart-lang/sdk/issues/21620) | 1027 // (https://github.com/dart-lang/sdk/issues/21620) |
591 vm_options.AddArgument("--no-concurrent_sweep"); | 1028 vm_options.AddArgument("--no-concurrent_sweep"); |
| 1029 |
| 1030 if (IsSnapshottingForPrecompilation()) { |
| 1031 vm_options.AddArgument("--precompilation"); |
| 1032 } |
| 1033 |
592 Dart_SetVMFlags(vm_options.count(), vm_options.arguments()); | 1034 Dart_SetVMFlags(vm_options.count(), vm_options.arguments()); |
593 | 1035 |
594 // Initialize the Dart VM. | 1036 // Initialize the Dart VM. |
595 // Note: We don't expect isolates to be created from dart code during | 1037 // Note: We don't expect isolates to be created from dart code during |
596 // snapshot generation. | 1038 // snapshot generation. |
597 char* error = Dart_Initialize( | 1039 char* error = Dart_Initialize( |
598 NULL, | 1040 NULL, |
599 NULL, | 1041 NULL, |
600 CreateServiceIsolate, | 1042 CreateServiceIsolate, |
601 NULL, | 1043 NULL, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 fprintf(stderr, "%s", error); | 1107 fprintf(stderr, "%s", error); |
666 free(error); | 1108 free(error); |
667 exit(255); | 1109 exit(255); |
668 } | 1110 } |
669 Dart_EnterScope(); | 1111 Dart_EnterScope(); |
670 | 1112 |
671 // Set up the library tag handler in such a manner that it will use the | 1113 // Set up the library tag handler in such a manner that it will use the |
672 // URL mapping specified on the command line to load the libraries. | 1114 // URL mapping specified on the command line to load the libraries. |
673 result = Dart_SetLibraryTagHandler(CreateSnapshotLibraryTagHandler); | 1115 result = Dart_SetLibraryTagHandler(CreateSnapshotLibraryTagHandler); |
674 CHECK_RESULT(result); | 1116 CHECK_RESULT(result); |
| 1117 |
| 1118 Dart_QualifiedFunctionName* entry_points = |
| 1119 ParseEntryPointsManifestIfPresent(); |
| 1120 |
| 1121 SetupStubNativeResolversForPrecompilation(entry_points); |
| 1122 |
675 // Load the specified script. | 1123 // Load the specified script. |
676 library = LoadSnapshotCreationScript(app_script_name); | 1124 library = LoadSnapshotCreationScript(app_script_name); |
677 VerifyLoaded(library); | 1125 VerifyLoaded(library); |
| 1126 |
| 1127 ImportNativeEntryPointLibrariesIntoRoot(entry_points); |
| 1128 |
678 // Ensure that we mark all libraries as loaded. | 1129 // Ensure that we mark all libraries as loaded. |
679 result = Dart_FinalizeLoading(false); | 1130 result = Dart_FinalizeLoading(false); |
680 CHECK_RESULT(result); | 1131 CHECK_RESULT(result); |
681 CreateAndWriteSnapshot(); | 1132 |
| 1133 if (entry_points == NULL) { |
| 1134 ASSERT(!IsSnapshottingForPrecompilation()); |
| 1135 CreateAndWriteSnapshot(); |
| 1136 } else { |
| 1137 CreateAndWritePrecompiledSnapshot(entry_points); |
| 1138 } |
| 1139 |
| 1140 CleanupEntryPointsCollection(entry_points); |
682 | 1141 |
683 Dart_EnterIsolate(UriResolverIsolateScope::isolate); | 1142 Dart_EnterIsolate(UriResolverIsolateScope::isolate); |
684 Dart_ShutdownIsolate(); | 1143 Dart_ShutdownIsolate(); |
685 } else { | 1144 } else { |
686 SetupForGenericSnapshotCreation(); | 1145 SetupForGenericSnapshotCreation(); |
687 CreateAndWriteSnapshot(); | 1146 CreateAndWriteSnapshot(); |
688 } | 1147 } |
689 EventHandler::Stop(); | 1148 EventHandler::Stop(); |
690 return 0; | 1149 return 0; |
691 } | 1150 } |
692 | 1151 |
693 } // namespace bin | 1152 } // namespace bin |
694 } // namespace dart | 1153 } // namespace dart |
695 | 1154 |
696 int main(int argc, char** argv) { | 1155 int main(int argc, char** argv) { |
697 return dart::bin::main(argc, argv); | 1156 return dart::bin::main(argc, argv); |
698 } | 1157 } |
OLD | NEW |