|
5 | 5 | #include "vm/bootstrap.h"
|
6 | 6 |
|
7 | 7 | #include <memory>
|
| 8 | +#include <utility> |
8 | 9 |
|
9 | 10 | #include "include/dart_api.h"
|
10 | 11 |
|
@@ -108,22 +109,10 @@ static void Finish(Thread* thread) {
|
108 | 109 | cls.EnsureIsFinalized(thread);
|
109 | 110 | }
|
110 | 111 |
|
111 |
| -static ErrorPtr BootstrapFromKernel(Thread* thread, |
112 |
| - const uint8_t* kernel_buffer, |
113 |
| - intptr_t kernel_buffer_size) { |
| 112 | +static ErrorPtr BootstrapFromKernelSingleProgram( |
| 113 | + Thread* thread, |
| 114 | + std::unique_ptr<kernel::Program> program) { |
114 | 115 | Zone* zone = thread->zone();
|
115 |
| - const char* error = nullptr; |
116 |
| - std::unique_ptr<kernel::Program> program = kernel::Program::ReadFromBuffer( |
117 |
| - kernel_buffer, kernel_buffer_size, &error); |
118 |
| - if (program == nullptr) { |
119 |
| - const intptr_t kMessageBufferSize = 512; |
120 |
| - char message_buffer[kMessageBufferSize]; |
121 |
| - Utils::SNPrint(message_buffer, kMessageBufferSize, |
122 |
| - "Can't load Kernel binary: %s.", error); |
123 |
| - const String& msg = String::Handle(String::New(message_buffer, Heap::kOld)); |
124 |
| - return ApiError::New(msg, Heap::kOld); |
125 |
| - } |
126 |
| - |
127 | 116 | LongJumpScope jump;
|
128 | 117 | if (setjmp(*jump.Set()) == 0) {
|
129 | 118 | kernel::KernelLoader loader(program.get(), /*uri_to_source_table=*/nullptr);
|
@@ -167,6 +156,66 @@ static ErrorPtr BootstrapFromKernel(Thread* thread,
|
167 | 156 | return Thread::Current()->StealStickyError();
|
168 | 157 | }
|
169 | 158 |
|
| 159 | +static 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 = |
| 196 | + kernel::Program::ReadFrom(&reader, &error); |
| 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 | + |
170 | 219 | ErrorPtr Bootstrap::DoBootstrapping(const uint8_t* kernel_buffer,
|
171 | 220 | intptr_t kernel_buffer_size) {
|
172 | 221 | Thread* thread = Thread::Current();
|
|
0 commit comments