-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathkernel_loader.h
431 lines (344 loc) · 14.6 KB
/
kernel_loader.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_KERNEL_LOADER_H_
#define RUNTIME_VM_KERNEL_LOADER_H_
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/bit_vector.h"
#include "vm/compiler/frontend/constant_reader.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/hash_map.h"
#include "vm/kernel.h"
#include "vm/object.h"
#include "vm/symbols.h"
namespace dart {
namespace kernel {
class KernelLoader;
class BuildingTranslationHelper : public TranslationHelper {
public:
BuildingTranslationHelper(KernelLoader* loader,
Thread* thread,
Heap::Space space)
: TranslationHelper(thread, space),
loader_(loader),
library_lookup_handle_(Library::Handle(thread->zone())) {}
virtual ~BuildingTranslationHelper() {}
virtual LibraryPtr LookupLibraryByKernelLibrary(NameIndex library,
bool required = true);
virtual ClassPtr LookupClassByKernelClass(NameIndex klass,
bool required = true);
private:
KernelLoader* loader_;
#if defined(DEBUG)
class LibraryLookupHandleScope {
public:
explicit LibraryLookupHandleScope(Library& lib) : lib_(lib) {
ASSERT(lib_.IsNull());
}
~LibraryLookupHandleScope() { lib_ = Library::null(); }
private:
Library& lib_;
DISALLOW_COPY_AND_ASSIGN(LibraryLookupHandleScope);
};
#endif // defined(DEBUG)
// Preallocated handle for use in LookupClassByKernelClass().
Library& library_lookup_handle_;
DISALLOW_COPY_AND_ASSIGN(BuildingTranslationHelper);
};
template <typename VmType>
class Mapping {
public:
bool Lookup(intptr_t canonical_name, VmType** handle) {
typename MapType::Pair* pair = map_.LookupPair(canonical_name);
if (pair != nullptr) {
*handle = pair->value;
return true;
}
return false;
}
void Insert(intptr_t canonical_name, VmType* object) {
map_.Insert(canonical_name, object);
}
private:
typedef IntMap<VmType*> MapType;
MapType map_;
};
class LibraryIndex {
public:
explicit LibraryIndex(const TypedDataView& kernel_data);
intptr_t class_count() const { return class_count_; }
intptr_t procedure_count() const { return procedure_count_; }
intptr_t ClassOffset(intptr_t index) const {
return reader_.ReadUInt32At(class_index_offset_ + index * 4);
}
intptr_t ProcedureOffset(intptr_t index) const {
return reader_.ReadUInt32At(procedure_index_offset_ + index * 4);
}
intptr_t SizeOfClassAtOffset(intptr_t class_offset) const {
for (intptr_t i = 0, offset = class_index_offset_; i < class_count_;
++i, offset += 4) {
if (static_cast<intptr_t>(reader_.ReadUInt32At(offset)) == class_offset) {
return reader_.ReadUInt32At(offset + 4) - class_offset;
}
}
UNREACHABLE();
return -1;
}
intptr_t SourceReferencesOffset() { return source_references_offset_; }
private:
Reader reader_;
intptr_t source_references_offset_;
intptr_t class_index_offset_;
intptr_t class_count_;
intptr_t procedure_index_offset_;
intptr_t procedure_count_;
DISALLOW_COPY_AND_ASSIGN(LibraryIndex);
};
class ClassIndex {
public:
// |class_offset| is the offset of class' kernel data in |kernel_data|.
// The size of the class' kernel data is |class_size|.
ClassIndex(const TypedDataBase& kernel_data,
intptr_t class_offset,
intptr_t class_size);
intptr_t procedure_count() const { return procedure_count_; }
intptr_t ProcedureOffset(intptr_t index) const {
return reader_.ReadUInt32At(procedure_index_offset_ + index * 4);
}
private:
void Init(intptr_t class_offset, intptr_t class_size);
Reader reader_;
intptr_t procedure_count_;
intptr_t procedure_index_offset_;
DISALLOW_COPY_AND_ASSIGN(ClassIndex);
};
struct UriToSourceTableEntry : public ZoneAllocated {
UriToSourceTableEntry() {}
const String* uri = nullptr;
const String* sources = nullptr;
const TypedData* line_starts = nullptr;
};
struct UriToSourceTableTrait {
typedef UriToSourceTableEntry* Value;
typedef const UriToSourceTableEntry* Key;
typedef UriToSourceTableEntry* Pair;
static Key KeyOf(Pair kv) { return kv; }
static Value ValueOf(Pair kv) { return kv; }
static inline uword Hash(Key key) { return key->uri->Hash(); }
static inline bool IsKeyEqual(Pair kv, Key key) {
// Only compare uri.
return kv->uri->CompareTo(*key->uri) == 0;
}
};
class KernelLoader : public ValueObject {
public:
explicit KernelLoader(
Program* program,
DirectChainedHashMap<UriToSourceTableTrait>* uri_to_source_table);
static Object& LoadEntireProgram(Program* program,
bool process_pending_classes = true);
// Returns the library containing the main procedure, null if there
// was no main procedure, or a failure object if there was an error.
ObjectPtr LoadProgram(bool process_pending_classes = true);
// Load given library.
void LoadLibrary(const Library& library);
// Returns the function which will evaluate the expression, or a failure
// object if there was an error.
ObjectPtr LoadExpressionEvaluationFunction(const String& library_url,
const String& klass);
// Finds all libraries that have been modified in this incremental
// version of the kernel program file.
//
// When [force_reload] is false and if [p_num_classes], [p_num_procedures] are
// not nullptr, then they are populated with number of classes and top-level
// procedures in [program].
static void FindModifiedLibraries(Program* program,
IsolateGroup* isolate_group,
BitVector* modified_libs,
bool force_reload,
bool* is_empty_program,
intptr_t* p_num_classes,
intptr_t* p_num_procedures);
static StringPtr FindSourceForScript(const uint8_t* kernel_buffer,
intptr_t kernel_buffer_length,
const String& url);
static void FinishLoading(const Class& klass);
void ReadObfuscationProhibitions();
void ReadLoadingUnits();
// Get closure Function from cache or create it if it is not created yet.
// [func_decl_offset] is an offset FunctionExpression or FunctionDeclaration.
static FunctionPtr GetClosureFunction(Thread* thread,
intptr_t func_decl_offset,
const Function& member_function,
const Function& parent_function,
const Object& closure_owner);
static void index_programs(kernel::Reader* reader,
GrowableArray<intptr_t>* subprogram_file_starts);
private:
// Pragma bits
using HasPragma = BitField<uint32_t, bool>;
using ExternalNamePragma = BitField<uint32_t, bool, HasPragma::kNextBit>;
using InvisibleFunctionPragma =
BitField<uint32_t, bool, ExternalNamePragma::kNextBit>;
using IsolateUnsendablePragma =
BitField<uint32_t, bool, InvisibleFunctionPragma::kNextBit>;
using DeeplyImmutablePragma =
BitField<uint32_t, bool, IsolateUnsendablePragma::kNextBit>;
using FfiNativePragma =
BitField<uint32_t, bool, DeeplyImmutablePragma::kNextBit>;
using SharedPragma = BitField<uint32_t, bool, FfiNativePragma::kNextBit>;
using DynModuleExtendablePragma =
BitField<uint32_t, bool, SharedPragma::kNextBit>;
using DynModuleImplicitlyExtendablePragma =
BitField<uint32_t, bool, DynModuleExtendablePragma::kNextBit>;
using DynModuleCanBeOverriddenPragma =
BitField<uint32_t, bool, DynModuleImplicitlyExtendablePragma::kNextBit>;
using DynModuleCanBeOverriddenImplicitlyPragma =
BitField<uint32_t, bool, DynModuleCanBeOverriddenPragma::kNextBit>;
void FinishTopLevelClassLoading(const Class& toplevel_class,
const Library& library,
const LibraryIndex& library_index);
bool IsClassName(NameIndex name, const String& library, const String& klass);
void ReadVMAnnotations(intptr_t annotation_count,
uint32_t* pragma_bits,
String* native_name = nullptr);
KernelLoader(const KernelProgramInfo& kernel_program_info,
const TypedDataBase& kernel_data,
intptr_t data_program_offset);
void InitializeFields(
DirectChainedHashMap<UriToSourceTableTrait>* uri_to_source_table);
LibraryPtr LoadLibrary(intptr_t index);
const String& LibraryUri(intptr_t library_index) {
return translation_helper_.DartSymbolPlain(
translation_helper_.CanonicalNameString(
library_canonical_name(library_index)));
}
intptr_t library_offset(intptr_t index) {
kernel::Reader reader(program_->binary());
return reader.ReadFromIndexNoReset(reader.size(),
KernelFixedFieldsAfterLibraries,
program_->library_count() + 1, index);
}
NameIndex library_canonical_name(intptr_t index) {
kernel::Reader reader(program_->binary());
reader.set_offset(library_offset(index));
// Start reading library.
// Note that this needs to be keep in sync with LibraryHelper.
reader.ReadFlags();
reader.ReadUInt(); // Read major language version.
reader.ReadUInt(); // Read minor language version.
return reader.ReadCanonicalNameReference();
}
uint8_t CharacterAt(StringIndex string_index, intptr_t index);
void walk_incremental_kernel(BitVector* modified_libs,
bool* is_empty_program,
intptr_t* p_num_classes,
intptr_t* p_num_procedures);
void LoadPreliminaryClass(ClassHelper* class_helper,
intptr_t type_parameter_count);
void ReadInferredType(const Field& field, intptr_t kernel_offset);
void CheckForInitializer(const Field& field);
void LoadClass(const Library& library,
const Class& toplevel_class,
intptr_t class_end,
Class* out_class);
void FinishClassLoading(const Class& klass,
const Library& library,
const Class& toplevel_class,
intptr_t class_offset,
const ClassIndex& class_index,
ClassHelper* class_helper);
void LoadProcedure(const Library& library,
const Class& owner,
bool in_class,
intptr_t procedure_end);
ArrayPtr MakeFieldsArray();
ArrayPtr MakeFunctionsArray();
ScriptPtr LoadScriptAt(
intptr_t index,
DirectChainedHashMap<UriToSourceTableTrait>* uri_to_source_table);
// If klass's script is not the script at the uri index, return a PatchClass
// for klass whose script corresponds to the uri index.
// Otherwise return klass.
const Object& ClassForScriptAt(const Class& klass, intptr_t source_uri_index);
ScriptPtr ScriptAt(intptr_t source_uri_index) {
return kernel_program_info_.ScriptAt(source_uri_index);
}
// Reads field initializer and returns the initial field value.
ObjectPtr ReadInitialFieldValue(const Field& field,
FieldHelper* field_helper);
// Generates field getter and setter functions.
void GenerateFieldAccessors(const Class& klass,
const Field& field,
FieldHelper* field_helper);
void LoadLibraryImportsAndExports(Library* library,
const Class& toplevel_class);
LibraryPtr LookupLibraryOrNull(NameIndex library);
LibraryPtr LookupLibrary(NameIndex library);
LibraryPtr LookupLibraryFromClass(NameIndex klass);
ClassPtr LookupClass(const Library& library, NameIndex klass);
UntaggedFunction::Kind GetFunctionType(ProcedureHelper::Kind procedure_kind);
// Read local function (either FunctionExpression or FunctionDeclaration)
// and create corresponding Function object.
// If [closure_owner] is not null, it overrides closure function owner.
FunctionPtr LoadClosureFunction(const Function& parent_function,
const Object& closure_owner);
Program* program_;
Thread* thread_;
Zone* zone_;
NoActiveIsolateScope no_active_isolate_scope_;
Array& patch_classes_;
ActiveClass active_class_;
// This is the offset of the current library within
// the whole kernel program.
intptr_t library_kernel_offset_;
// This is the offset by which offsets, which are set relative
// to their library's kernel data, have to be corrected.
intptr_t correction_offset_;
bool loading_native_wrappers_library_;
NameIndex skip_vmservice_library_;
TypedDataView& library_kernel_data_;
KernelProgramInfo& kernel_program_info_;
BuildingTranslationHelper translation_helper_;
KernelReaderHelper helper_;
ConstantReader constant_reader_;
TypeTranslator type_translator_;
InferredTypeMetadataHelper inferred_type_metadata_helper_;
Object& static_field_value_;
Smi& name_index_handle_;
// We "re-use" the normal .dill file format for encoding compiled evaluation
// expressions from the debugger. This allows us to also reuse the normal
// a) kernel loader b) flow graph building code. The encoding is either one
// of the following two options:
//
// * Option a) The expression is evaluated inside an instance method call
// context:
//
// Program:
// |> library "evaluate:source"
// |> class "#DebugClass"
// |> procedure ":Eval"
//
// * Option b) The expression is evaluated outside an instance method call
// context:
//
// Program:
// |> library "evaluate:source"
// |> procedure ":Eval"
//
// See
// * pkg/front_end/lib/src/fasta/incremental_compiler.dart,
// compileExpression
// * pkg/front_end/lib/src/fasta/kernel/utils.dart,
// createExpressionEvaluationComponent
//
Library& expression_evaluation_library_;
GrowableArray<const Function*> functions_;
GrowableArray<const Field*> fields_;
friend class BuildingTranslationHelper;
DISALLOW_COPY_AND_ASSIGN(KernelLoader);
};
} // namespace kernel
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // RUNTIME_VM_KERNEL_LOADER_H_