Flutter Engine
The Flutter Engine
bootstrap.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
5#include "vm/bootstrap.h"
6
7#include <memory>
8#include <utility>
9
10#include "include/dart_api.h"
11
12#include "vm/class_finalizer.h"
14#include "vm/dart_api_impl.h"
15#if !defined(DART_PRECOMPILED_RUNTIME)
16#include "vm/kernel.h"
17#include "vm/kernel_loader.h"
18#endif
19#include "vm/longjump.h"
20#include "vm/object.h"
21#include "vm/object_store.h"
22#include "vm/symbols.h"
23
24namespace dart {
25
28 const char* uri;
29};
30
32
33#if !defined(DART_PRECOMPILED_RUNTIME)
34#define MAKE_PROPERTIES(CamelName, name) \
35 {ObjectStore::k##CamelName, "dart:" #name},
36
39
40#undef MAKE_PROPERTIES
41
42static constexpr intptr_t kBootstrapLibraryCount =
44static void Finish(Thread* thread) {
47 FATAL("Error in class finalization during bootstrapping.");
48 }
49
50 // Eagerly compile the _Closure class as it is the class of all closure
51 // instances. This allows us to just finalize function types without going
52 // through the hoops of trying to compile their scope class.
53 ObjectStore* object_store = thread->isolate_group()->object_store();
54 Zone* zone = thread->zone();
55 Class& cls = Class::Handle(zone, object_store->closure_class());
56 cls.EnsureIsFinalized(thread);
57
58 // Make sure _Closure fields are not marked as unboxed as they are accessed
59 // with plain loads.
60 const Array& fields = Array::Handle(zone, cls.fields());
61 Field& field = Field::Handle(zone);
62 for (intptr_t i = 0; i < fields.Length(); ++i) {
63 field ^= fields.At(i);
64 field.set_is_unboxed(false);
65 }
66 // _Closure._hash field should be explicitly marked as nullable because
67 // VM creates instances of _Closure without compiling its constructors,
68 // so it won't get nullability info from a constructor.
69 field ^= fields.At(fields.Length() - 1);
70 // Note that UserVisibleName depends on --show-internal-names.
71 ASSERT(strncmp(field.UserVisibleNameCString(), "_hash", 5) == 0);
72 field.RecordStore(Object::null_object());
73
74#if defined(DEBUG)
75 // Verify that closure field offsets are identical in Dart and C++.
76 ASSERT_EQUAL(fields.Length(), 6);
77 field ^= fields.At(0);
80 field ^= fields.At(1);
82 field ^= fields.At(2);
84 field ^= fields.At(3);
86 field ^= fields.At(4);
88 field ^= fields.At(5);
90#endif // defined(DEBUG)
91
92 // Eagerly compile to avoid repeated checks when loading constants or
93 // serializing.
94 cls = object_store->null_class();
95 cls.EnsureIsFinalized(thread);
96 cls = object_store->bool_class();
97 cls.EnsureIsFinalized(thread);
98 cls = object_store->array_class();
99 cls.EnsureIsFinalized(thread);
100 cls = object_store->immutable_array_class();
101 cls.EnsureIsFinalized(thread);
102 cls = object_store->map_impl_class();
103 cls.EnsureIsFinalized(thread);
104 cls = object_store->const_map_impl_class();
105 cls.EnsureIsFinalized(thread);
106 cls = object_store->set_impl_class();
107 cls.EnsureIsFinalized(thread);
108 cls = object_store->const_set_impl_class();
109 cls.EnsureIsFinalized(thread);
110}
111
113 Thread* thread,
114 std::unique_ptr<kernel::Program> program) {
115 Zone* zone = thread->zone();
116 LongJumpScope jump;
117 if (setjmp(*jump.Set()) == 0) {
118 kernel::KernelLoader loader(program.get(), /*uri_to_source_table=*/nullptr);
119
120 auto isolate_group = thread->isolate_group();
121
122 if (isolate_group->obfuscate()) {
124 }
125
126 // Load the bootstrap libraries in order (see object_store.h).
127 Library& library = Library::Handle(zone);
128 for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
130 library = isolate_group->object_store()->bootstrap_library(id);
131 loader.LoadLibrary(library);
132 }
133
134 // Finish bootstrapping, including class finalization.
135 Finish(thread);
136
137 isolate_group->object_store()->InitKnownObjects();
138
139 // The platform binary may contain other libraries (e.g., dart:_builtin or
140 // dart:io) that will not be bundled with application. Load them now.
141 const Object& result = Object::Handle(zone, loader.LoadProgram());
142 program.reset();
143 if (result.IsError()) {
144 return Error::Cast(result).ptr();
145 }
146
147 if (FLAG_precompiled_mode) {
148 loader.ReadLoadingUnits();
149 }
150
151 return Error::null();
152 }
153
154 // Either class finalization failed or we caught a compile-time error.
155 // In both cases sticky error would be set.
157}
158
159static ErrorPtr BootstrapFromKernel(Thread* thread,
160 const uint8_t* kernel_buffer,
161 intptr_t kernel_buffer_size) {
162 Zone* zone = thread->zone();
163 const char* error = nullptr;
164 std::unique_ptr<kernel::Program> program = kernel::Program::ReadFromBuffer(
165 kernel_buffer, kernel_buffer_size, &error);
166 if (program == nullptr) {
167 const intptr_t kMessageBufferSize = 512;
168 char message_buffer[kMessageBufferSize];
169 Utils::SNPrint(message_buffer, kMessageBufferSize,
170 "Can't load Kernel binary: %s.", error);
171 const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
172 return ApiError::New(msg, Heap::kOld);
173 }
174
175 if (program->is_single_program()) {
176 return BootstrapFromKernelSingleProgram(thread, std::move(program));
177 }
178
179 GrowableArray<intptr_t> subprogram_file_starts;
180 {
181 kernel::Reader reader(program->binary());
182 kernel::KernelLoader::index_programs(&reader, &subprogram_file_starts);
183 }
184 intptr_t subprogram_count = subprogram_file_starts.length() - 1;
185
186 // Create "fake programs" for each sub-program.
187 auto& load_result = Error::Handle(zone);
188 for (intptr_t i = 0; i < subprogram_count; i++) {
189 intptr_t subprogram_start = subprogram_file_starts.At(i);
190 intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
191 const auto& component = TypedDataBase::Handle(
192 program->binary().ViewFromTo(subprogram_start, subprogram_end));
193 kernel::Reader reader(component);
194 const char* error = nullptr;
195 std::unique_ptr<kernel::Program> subprogram =
197 if (subprogram == nullptr) {
198 FATAL("Failed to load kernel file: %s", error);
199 }
200 ASSERT(subprogram->is_single_program());
201 if (i == 0) {
202 // The first subprogram must be the main Dart program.
203 load_result ^=
204 BootstrapFromKernelSingleProgram(thread, std::move(subprogram));
205 } else {
206 // Restrictions on the subsequent programs: Must contain only
207 // contain dummy libraries with VM recognized classes (or classes kept
208 // fully intact by tree-shaking).
209 // Currently only used for concatenating native assets mappings.
210 kernel::KernelLoader loader(subprogram.get(),
211 /*uri_to_source_table=*/nullptr);
212 load_result ^= loader.LoadProgram(false);
213 }
214 if (load_result.IsError()) return load_result.ptr();
215 }
216 return Error::null();
217}
218
219ErrorPtr Bootstrap::DoBootstrapping(const uint8_t* kernel_buffer,
220 intptr_t kernel_buffer_size) {
221 Thread* thread = Thread::Current();
222 auto isolate_group = thread->isolate_group();
223 Zone* zone = thread->zone();
224 String& uri = String::Handle(zone);
225 Library& lib = Library::Handle(zone);
226
227 HANDLESCOPE(thread);
228
229 // Ensure there are library objects for all the bootstrap libraries.
230 for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
232 uri = Symbols::New(thread, bootstrap_libraries[i].uri);
233 lib = isolate_group->object_store()->bootstrap_library(id);
234 ASSERT(lib.ptr() == Library::LookupLibrary(thread, uri));
235 if (lib.IsNull()) {
236 lib = Library::NewLibraryHelper(uri, false);
237 lib.SetLoadRequested();
238 lib.Register(thread);
239 isolate_group->object_store()->set_bootstrap_library(id, lib);
240 }
241 }
242
243 return BootstrapFromKernel(thread, kernel_buffer, kernel_buffer_size);
244}
245#else
246ErrorPtr Bootstrap::DoBootstrapping(const uint8_t* kernel_buffer,
247 intptr_t kernel_buffer_size) {
248 UNREACHABLE();
249 return Error::null();
250}
251#endif
252
253} // namespace dart
#define UNREACHABLE()
Definition: assert.h:248
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309
#define MAKE_PROPERTIES(CamelName, name)
Definition: bootstrap.cc:34
ObjectPtr At(intptr_t index) const
Definition: object.h:10875
intptr_t Length() const
Definition: object.h:10829
const T & At(intptr_t index) const
intptr_t length() const
static ErrorPtr DoBootstrapping(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
Definition: bootstrap.cc:219
static void SetupNativeResolver()
static bool ProcessPendingClasses()
ArrayPtr fields() const
Definition: object.h:1615
ErrorPtr EnsureIsFinalized(Thread *thread) const
Definition: object.cc:4924
static intptr_t delayed_type_arguments_offset()
Definition: object.h:12346
static intptr_t function_offset()
Definition: object.h:12351
static intptr_t instantiator_type_arguments_offset()
Definition: object.h:12326
static intptr_t function_type_arguments_offset()
Definition: object.h:12336
static intptr_t hash_offset()
Definition: object.h:12381
static intptr_t context_offset()
Definition: object.h:12370
const char * UserVisibleNameCString() const
Definition: object.cc:12082
void set_is_unboxed(bool b) const
Definition: object.h:4720
intptr_t HostOffset() const
Definition: object.h:13241
void RecordStore(const Object &value) const
Definition: object.cc:13027
@ kOld
Definition: heap.h:39
ObjectStore * object_store() const
Definition: isolate.h:510
void Register(Thread *thread) const
Definition: object.cc:14731
void SetLoadRequested() const
Definition: object.cc:13628
static LibraryPtr LookupLibrary(Thread *thread, const String &url)
Definition: object.cc:14599
jmp_buf * Set()
Definition: longjump.cc:16
static ObjectPtr null()
Definition: object.h:433
ObjectPtr ptr() const
Definition: object.h:332
bool IsNull() const
Definition: object.h:363
static Object & Handle()
Definition: object.h:407
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition: object.cc:23698
static StringPtr New(Thread *thread, const char *cstr)
Definition: symbols.h:723
Zone * zone() const
Definition: thread_state.h:37
static Thread * Current()
Definition: thread.h:362
DART_WARN_UNUSED_RESULT ErrorPtr StealStickyError()
Definition: thread.cc:245
IsolateGroup * isolate_group() const
Definition: thread.h:541
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
static void index_programs(kernel::Reader *reader, GrowableArray< intptr_t > *subprogram_file_starts)
void LoadLibrary(const Library &library)
ObjectPtr LoadProgram(bool process_pending_classes=true)
static std::unique_ptr< Program > ReadFromBuffer(const uint8_t *buffer, intptr_t buffer_length, const char **error=nullptr)
static std::unique_ptr< Program > ReadFrom(Reader *reader, const char **error=nullptr)
#define ASSERT(E)
#define FATAL(error)
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
#define HANDLESCOPE(thread)
Definition: handles.h:321
Definition: dart_vm.cc:33
static void Finish(Thread *thread)
Definition: bootstrap.cc:44
static const BootstrapLibProps bootstrap_libraries[]
Definition: bootstrap.cc:37
static ErrorPtr BootstrapFromKernel(Thread *thread, const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
Definition: bootstrap.cc:159
static constexpr intptr_t kBootstrapLibraryCount
Definition: bootstrap.cc:42
@ kPathsUriOffset
Definition: bootstrap.cc:31
@ kPathsSourceOffset
Definition: bootstrap.cc:31
@ kPathsEntryLength
Definition: bootstrap.cc:31
static ErrorPtr BootstrapFromKernelSingleProgram(Thread *thread, std::unique_ptr< kernel::Program > program)
Definition: bootstrap.cc:112
#define FOR_EACH_BOOTSTRAP_LIBRARY(M)
Definition: object_store.h:19
ObjectStore::BootstrapLibraryId index
Definition: bootstrap.cc:27
#define ARRAY_SIZE(array)
Definition: globals.h:72