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 errors 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, ...) { | |
rmacnak
2015/10/22 16:46:15
char* Parser
const char* format
Chinmay
2015/10/22 19:01:29
ack
| |
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; | |
rmacnak
2015/10/22 16:46:15
char* error_buffer
Chinmay
2015/10/22 19:01:29
ack
| |
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"); | |
rmacnak
2015/10/22 16:46:15
Are these IO functions portable? gen_snapshot need
Chinmay
2015/10/22 19:01:29
I am quite certain I have used portable functions.
| |
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 |