237 {
239
241
242 if (program->is_single_program()) {
244 return Object::Handle(loader.LoadProgram(process_pending_classes));
245 }
246
247 GrowableArray<intptr_t> subprogram_file_starts;
248 {
249 kernel::Reader reader(program->binary());
251 }
252
253 Zone* zone = thread->zone();
255 intptr_t subprogram_count = subprogram_file_starts.length() - 1;
256
257
259 UriToSourceTableEntry wrapper;
261 Zone* zone_ = thread_->zone();
262 for (intptr_t i = subprogram_count - 1; i >= 0; --i) {
263 intptr_t subprogram_start = subprogram_file_starts.At(i);
264 intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
266 program->binary().ViewFromTo(subprogram_start, subprogram_end));
267 TranslationHelper translation_helper(thread);
268 KernelReaderHelper helper_(zone_, &translation_helper, component, 0);
270 for (intptr_t index = 0; index < source_table_size; ++index) {
272 wrapper.uri = &uri_string;
273 TypedData& line_starts =
275 if (line_starts.Length() == 0) continue;
276 const String& script_source = helper_.
GetSourceFor(index);
277 wrapper.uri = &uri_string;
278 UriToSourceTableEntry* pair = uri_to_source_table.LookupValue(&wrapper);
279 if (pair != nullptr) {
280
281
282 const bool src_differ = pair->sources->
CompareTo(script_source) != 0;
283 const bool line_starts_differ =
284 !pair->line_starts->CanonicalizeEquals(line_starts);
285 if (src_differ || line_starts_differ) {
287 "Invalid kernel binary: Contains at least two source entries "
288 "that do not agree. URI '%s', difference: %s. Subprogram count: "
290 uri_string.ToCString(),
291 src_differ && line_starts_differ
292 ? "src and line starts"
293 : (src_differ ? "src" : "line starts"),
294 subprogram_count);
295 }
296 } else {
297 UriToSourceTableEntry* tmp = new UriToSourceTableEntry();
298 tmp->uri = &uri_string;
299 tmp->sources = &script_source;
300 tmp->line_starts = &line_starts;
301 uri_to_source_table.Insert(tmp);
302 }
303 }
304 }
305
306
307 for (intptr_t i = subprogram_count - 1; i >= 0; --i) {
308 intptr_t subprogram_start = subprogram_file_starts.At(i);
309 intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
311 program->binary().ViewFromTo(subprogram_start, subprogram_end));
312 Reader reader(component);
313 const char*
error =
nullptr;
314 std::unique_ptr<Program> subprogram = Program::ReadFrom(&reader, &
error);
315 if (subprogram == nullptr) {
316 FATAL(
"Failed to load kernel file: %s",
error);
317 }
318 ASSERT(subprogram->is_single_program());
319 KernelLoader loader(subprogram.get(), &uri_to_source_table);
321 if (load_result.IsError()) return load_result;
322
323 if (load_result.IsLibrary()) {
324 library ^= load_result.ptr();
325 }
326 }
327
329
331 }
332
333 return library;
334}
static bool ProcessPendingClasses()
intptr_t CompareTo(const String &other) const
const String & GetSourceFor(intptr_t index)
String & SourceTableUriFor(intptr_t index)
intptr_t SourceTableSize()
TypedDataPtr GetLineStartsFor(intptr_t index)
DirectChainedHashMap< UriToSourceTableTrait > UriToSourceTable
#define TIMELINE_DURATION(thread, stream, name)