2016-10-15 20:48:46 +00:00
|
|
|
// 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.
|
|
|
|
|
2016-10-26 07:26:03 +00:00
|
|
|
#ifndef RUNTIME_VM_KERNEL_H_
|
|
|
|
#define RUNTIME_VM_KERNEL_H_
|
2016-10-15 20:48:46 +00:00
|
|
|
|
2019-06-21 19:41:08 +00:00
|
|
|
#include <memory>
|
|
|
|
|
2016-10-15 20:48:46 +00:00
|
|
|
#include "platform/assert.h"
|
|
|
|
#include "vm/allocation.h"
|
|
|
|
#include "vm/globals.h"
|
2017-01-31 10:59:06 +00:00
|
|
|
#include "vm/growable_array.h"
|
2017-08-29 08:59:15 +00:00
|
|
|
#include "vm/object.h"
|
2016-11-21 13:13:46 +00:00
|
|
|
#include "vm/token_position.h"
|
2016-10-15 20:48:46 +00:00
|
|
|
|
2018-01-09 13:36:01 +00:00
|
|
|
namespace dart {
|
|
|
|
namespace kernel {
|
|
|
|
class NameIndex {
|
|
|
|
public:
|
2018-04-30 10:57:45 +00:00
|
|
|
static const int kInvalidName = -1;
|
|
|
|
|
|
|
|
NameIndex() : value_(kInvalidName) {}
|
2018-01-09 13:36:01 +00:00
|
|
|
explicit NameIndex(int value) : value_(value) {}
|
|
|
|
|
|
|
|
operator int() const { return value_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
int value_;
|
|
|
|
};
|
2018-02-07 19:35:39 +00:00
|
|
|
} // namespace kernel
|
|
|
|
} // namespace dart
|
2018-01-09 13:36:01 +00:00
|
|
|
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
2016-10-15 20:48:46 +00:00
|
|
|
namespace dart {
|
|
|
|
|
2019-03-12 17:58:46 +00:00
|
|
|
class BitVector;
|
2016-11-21 14:53:00 +00:00
|
|
|
class Field;
|
|
|
|
class ParsedFunction;
|
|
|
|
class Zone;
|
|
|
|
|
2016-10-15 20:48:46 +00:00
|
|
|
namespace kernel {
|
|
|
|
|
|
|
|
class Reader;
|
2018-10-09 17:23:43 +00:00
|
|
|
struct ProcedureAttributesMetadata;
|
2016-10-15 20:48:46 +00:00
|
|
|
|
2017-05-03 22:43:14 +00:00
|
|
|
class StringIndex {
|
|
|
|
public:
|
|
|
|
StringIndex() : value_(-1) {}
|
|
|
|
explicit StringIndex(int value) : value_(value) {}
|
|
|
|
|
|
|
|
operator int() const { return value_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
int value_;
|
|
|
|
};
|
|
|
|
|
2017-08-17 12:34:00 +00:00
|
|
|
const uint8_t kNativeYieldFlags = 0x2;
|
2016-10-15 20:48:46 +00:00
|
|
|
|
2017-08-17 12:34:00 +00:00
|
|
|
enum LogicalOperator { kAnd, kOr };
|
2016-10-15 20:48:46 +00:00
|
|
|
|
2017-06-30 05:55:03 +00:00
|
|
|
class Program {
|
|
|
|
public:
|
2018-06-21 23:27:53 +00:00
|
|
|
// Read a kernel Program from the given Reader. Note the returned Program
|
|
|
|
// can potentially contain several "sub programs", though the library count
|
|
|
|
// etc will reference the last "sub program" only.
|
2019-06-21 19:41:08 +00:00
|
|
|
static std::unique_ptr<Program> ReadFrom(Reader* reader,
|
|
|
|
const char** error = nullptr);
|
|
|
|
|
|
|
|
static std::unique_ptr<Program> ReadFromFile(const char* script_uri,
|
|
|
|
const char** error = nullptr);
|
|
|
|
static std::unique_ptr<Program> ReadFromBuffer(const uint8_t* buffer,
|
|
|
|
intptr_t buffer_length,
|
|
|
|
const char** error = nullptr);
|
|
|
|
static std::unique_ptr<Program> ReadFromTypedData(
|
|
|
|
const ExternalTypedData& typed_data, const char** error = nullptr);
|
2018-03-15 23:24:44 +00:00
|
|
|
|
[kernel] Allow VM to load concatenated dill file
The kernel format has been designed so that one can concatenate several
dill files into one file and then load it. For instance the dart
function BinaryBuilder.readProgram supports this.
Currently a dill file contains one or more programs.
In the VM each of these programs are called either program or subprogram.
Technically a dill "program" isn't necessarily a program at all (e.g. it
could be missing a library).
This naming snafu should probably be cleaned up at some point, but that's
for another CL.
When loading a dill file via BinaryBuilder.readProgram what happens is
this:
- Each program in the dill file ends in 4 bytes that indicates the size
of the program.
- Reading the input from the end one can then read the size, skip back
that amount of bytes, if we have more data (i.e. there's another
program), read another size and so on, and continue until we have
accounted for all bytes in the input.
- We then read each program from the start, and basically overwrite any
library, class, procedure etc. we find.
The first main reference found is the one used though.
(Saying that we overwrite is not completely true, but when the library
is a non-external library that's basically what happens).
This CL introduces (some) support on the C++ side for the same thing.
So far the C++ side could only handle single-program-dills, and trying
to load anything else would probably crash the VM.
The support added is this:
- Assume the SDK (i.e. vm_platform.dill) is not a concatenated file
(error out if it is).
- For user provided input, loop over each contained program one-by-one,
for each individual one behave as normal.
- The way LibraryLoad is implemented (i.e. it skips if the library is
already loaded) this means that it currently would behave differently
than the dart version (i.e. the first one is used, not the last one).
For now it is assumed that that's not a problem.
- There is a possibly snafu if the same script is included several times.
This could probably mostly be remedied by not creating scripts up front,
but only as needed. By the "keep only one" (and fixing the above point,
probably by simply loading in the opposite order, i.e. last program
in the binary first) the (theoretical) problem would probably do away.
Note that we will have separate string tables, canonical name tables etc
per "sub program" and that there might be some duplication.
The implementation was tested as indicated below, but introduces no tests.
$ cat test_lib1.dart
import "test_lib2.dart" as lib2;
String lib1field = "lib #1 field!!";
main() {
foo();
lib2.foo();
print("From lib2: ${lib2.lib2field}");
}
foo() {
print("Hello, Foo, from test_lib1!");
var x = 42;
print(x);
}
$ cat test_lib2.dart
String lib2field = "Lib #2 field!!!!";
foo() {
print("Hello, Foo, from test_lib2!");
var y = 34;
print(y);
}
$ out/ReleaseX64/dart pkg/front_end/tool/_fasta/compile.dart --packages=.packages --platform=out/ReleaseX64/vm_platform.dill test_lib1.dart
$ ls -lha test_lib1.dart.dill
[...] 4.2M Oct 26 14:42 test_lib1.dart.dill
$ dart pkg/kernel/bin/split.dart test_lib1.dart.dill
Wrote test_lib1.dart.dill.part1.dill
Wrote test_lib1.dart.dill.part2.dill
$ ls -lha test_lib1.dart.dill.part{1,2}.dill
[...] 811 Oct 26 14:42 test_lib1.dart.dill.part1.dill
[...] 582 Oct 26 14:42 test_lib1.dart.dill.part2.dill
$ cat test_lib1.dart.dill.part1.dill test_lib1.dart.dill.part2.dill > test_lib1.dart.dill.concat.dill
$ ls -lha test_lib1.dart.dill.concat.dill
[...] 1.4K Oct 26 14:44 test_lib1.dart.dill.concat.dill
$ out/ReleaseX64/dart --kernel-binaries=out/ReleaseX64 --packages=.packages test_lib1.dart.dill.concat.dill
Hello, Foo, from test_lib1!
42
Hello, Foo, from test_lib2!
34
From lib2: Lib #2 field!!!!
Change-Id: I233a033aa3042b202dd4708908a5be3089474588
Reviewed-on: https://dart-review.googlesource.com/16820
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
2017-10-27 12:01:48 +00:00
|
|
|
bool is_single_program() { return single_program_; }
|
2019-03-20 09:39:33 +00:00
|
|
|
uint32_t binary_version() { return binary_version_; }
|
2017-06-30 05:55:03 +00:00
|
|
|
NameIndex main_method() { return main_method_reference_; }
|
2017-10-10 00:50:31 +00:00
|
|
|
intptr_t source_table_offset() const { return source_table_offset_; }
|
|
|
|
intptr_t string_table_offset() const { return string_table_offset_; }
|
|
|
|
intptr_t name_table_offset() const { return name_table_offset_; }
|
2018-05-15 00:41:08 +00:00
|
|
|
intptr_t metadata_payloads_offset() const {
|
|
|
|
return metadata_payloads_offset_;
|
|
|
|
}
|
|
|
|
intptr_t metadata_mappings_offset() const {
|
|
|
|
return metadata_mappings_offset_;
|
|
|
|
}
|
[kernel] Add kernel2kernel constant evaluation, binary format as well as vm support
The introduced "constants" transformation can evaluate constant expressions. The
original use-sites of constant expressions are replaced by a new [ConstantExpression]
node, which points to a subclass of a new [Constant] class hierarchy. Constant
[Field]s and [VariableDeclarations]s will be removed, since all use-sites are
re-written.
The [Constant] class hierarchy is, similarly to the [DartType] class hierarchy, not
part of the AST tree (also has no parent pointer). The constants form a
DAG (directed acyclic graph).
There is no canonicalization requirement of the [Constant] objects referenced by the
AST (via [ConstantExpression]). Although it is beneficial to canonicalize them during
construction, since it reduces time spent in operator==/hashCode.
This CL furthermore adds support for a constant table in the binary format. Similarly
to [String]s, we canonicalize the constants before writing the table to the binary.
The constant table entries in the binary are written in a post-order way, to ensure
easy construction on the backend side.
The text format will be augmented with a "constants { ... }" section at the end,
which lists the constants in the same order as in the binary format.
The transformation can be used by those backends who choose to do so. It is not
enabled by default atm. It should therefore not affect analyzer, fasta or other
components.
Change-Id: I57cd9624fedcf537ab6870db76246149647bed21
Reviewed-on: https://dart-review.googlesource.com/14382
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
2017-11-16 11:08:02 +00:00
|
|
|
intptr_t constant_table_offset() { return constant_table_offset_; }
|
2019-05-31 22:15:51 +00:00
|
|
|
const uint8_t* kernel_data() { return kernel_data_; }
|
|
|
|
intptr_t kernel_data_size() { return kernel_data_size_; }
|
2017-06-30 05:55:03 +00:00
|
|
|
intptr_t library_count() { return library_count_; }
|
2016-10-15 20:48:46 +00:00
|
|
|
|
|
|
|
private:
|
2019-05-31 22:15:51 +00:00
|
|
|
Program() : kernel_data_(NULL), kernel_data_size_(-1) {}
|
2016-10-15 20:48:46 +00:00
|
|
|
|
[kernel] Allow VM to load concatenated dill file
The kernel format has been designed so that one can concatenate several
dill files into one file and then load it. For instance the dart
function BinaryBuilder.readProgram supports this.
Currently a dill file contains one or more programs.
In the VM each of these programs are called either program or subprogram.
Technically a dill "program" isn't necessarily a program at all (e.g. it
could be missing a library).
This naming snafu should probably be cleaned up at some point, but that's
for another CL.
When loading a dill file via BinaryBuilder.readProgram what happens is
this:
- Each program in the dill file ends in 4 bytes that indicates the size
of the program.
- Reading the input from the end one can then read the size, skip back
that amount of bytes, if we have more data (i.e. there's another
program), read another size and so on, and continue until we have
accounted for all bytes in the input.
- We then read each program from the start, and basically overwrite any
library, class, procedure etc. we find.
The first main reference found is the one used though.
(Saying that we overwrite is not completely true, but when the library
is a non-external library that's basically what happens).
This CL introduces (some) support on the C++ side for the same thing.
So far the C++ side could only handle single-program-dills, and trying
to load anything else would probably crash the VM.
The support added is this:
- Assume the SDK (i.e. vm_platform.dill) is not a concatenated file
(error out if it is).
- For user provided input, loop over each contained program one-by-one,
for each individual one behave as normal.
- The way LibraryLoad is implemented (i.e. it skips if the library is
already loaded) this means that it currently would behave differently
than the dart version (i.e. the first one is used, not the last one).
For now it is assumed that that's not a problem.
- There is a possibly snafu if the same script is included several times.
This could probably mostly be remedied by not creating scripts up front,
but only as needed. By the "keep only one" (and fixing the above point,
probably by simply loading in the opposite order, i.e. last program
in the binary first) the (theoretical) problem would probably do away.
Note that we will have separate string tables, canonical name tables etc
per "sub program" and that there might be some duplication.
The implementation was tested as indicated below, but introduces no tests.
$ cat test_lib1.dart
import "test_lib2.dart" as lib2;
String lib1field = "lib #1 field!!";
main() {
foo();
lib2.foo();
print("From lib2: ${lib2.lib2field}");
}
foo() {
print("Hello, Foo, from test_lib1!");
var x = 42;
print(x);
}
$ cat test_lib2.dart
String lib2field = "Lib #2 field!!!!";
foo() {
print("Hello, Foo, from test_lib2!");
var y = 34;
print(y);
}
$ out/ReleaseX64/dart pkg/front_end/tool/_fasta/compile.dart --packages=.packages --platform=out/ReleaseX64/vm_platform.dill test_lib1.dart
$ ls -lha test_lib1.dart.dill
[...] 4.2M Oct 26 14:42 test_lib1.dart.dill
$ dart pkg/kernel/bin/split.dart test_lib1.dart.dill
Wrote test_lib1.dart.dill.part1.dill
Wrote test_lib1.dart.dill.part2.dill
$ ls -lha test_lib1.dart.dill.part{1,2}.dill
[...] 811 Oct 26 14:42 test_lib1.dart.dill.part1.dill
[...] 582 Oct 26 14:42 test_lib1.dart.dill.part2.dill
$ cat test_lib1.dart.dill.part1.dill test_lib1.dart.dill.part2.dill > test_lib1.dart.dill.concat.dill
$ ls -lha test_lib1.dart.dill.concat.dill
[...] 1.4K Oct 26 14:44 test_lib1.dart.dill.concat.dill
$ out/ReleaseX64/dart --kernel-binaries=out/ReleaseX64 --packages=.packages test_lib1.dart.dill.concat.dill
Hello, Foo, from test_lib1!
42
Hello, Foo, from test_lib2!
34
From lib2: Lib #2 field!!!!
Change-Id: I233a033aa3042b202dd4708908a5be3089474588
Reviewed-on: https://dart-review.googlesource.com/16820
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
2017-10-27 12:01:48 +00:00
|
|
|
bool single_program_;
|
2019-03-20 09:39:33 +00:00
|
|
|
uint32_t binary_version_;
|
2017-06-30 05:55:03 +00:00
|
|
|
NameIndex main_method_reference_; // Procedure.
|
|
|
|
intptr_t library_count_;
|
2016-10-15 20:48:46 +00:00
|
|
|
|
2017-09-06 06:38:14 +00:00
|
|
|
// The offset from the start of the binary to the start of the source table.
|
|
|
|
intptr_t source_table_offset_;
|
2017-04-21 08:32:43 +00:00
|
|
|
|
[kernel] Add kernel2kernel constant evaluation, binary format as well as vm support
The introduced "constants" transformation can evaluate constant expressions. The
original use-sites of constant expressions are replaced by a new [ConstantExpression]
node, which points to a subclass of a new [Constant] class hierarchy. Constant
[Field]s and [VariableDeclarations]s will be removed, since all use-sites are
re-written.
The [Constant] class hierarchy is, similarly to the [DartType] class hierarchy, not
part of the AST tree (also has no parent pointer). The constants form a
DAG (directed acyclic graph).
There is no canonicalization requirement of the [Constant] objects referenced by the
AST (via [ConstantExpression]). Although it is beneficial to canonicalize them during
construction, since it reduces time spent in operator==/hashCode.
This CL furthermore adds support for a constant table in the binary format. Similarly
to [String]s, we canonicalize the constants before writing the table to the binary.
The constant table entries in the binary are written in a post-order way, to ensure
easy construction on the backend side.
The text format will be augmented with a "constants { ... }" section at the end,
which lists the constants in the same order as in the binary format.
The transformation can be used by those backends who choose to do so. It is not
enabled by default atm. It should therefore not affect analyzer, fasta or other
components.
Change-Id: I57cd9624fedcf537ab6870db76246149647bed21
Reviewed-on: https://dart-review.googlesource.com/14382
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
2017-11-16 11:08:02 +00:00
|
|
|
// The offset from the start of the binary to the start of the constant table.
|
|
|
|
intptr_t constant_table_offset_;
|
|
|
|
|
2017-05-03 17:27:01 +00:00
|
|
|
// The offset from the start of the binary to the canonical name table.
|
|
|
|
intptr_t name_table_offset_;
|
|
|
|
|
2018-05-15 00:41:08 +00:00
|
|
|
// The offset from the start of the binary to the metadata payloads.
|
|
|
|
intptr_t metadata_payloads_offset_;
|
|
|
|
|
|
|
|
// The offset from the start of the binary to the metadata mappings.
|
|
|
|
intptr_t metadata_mappings_offset_;
|
|
|
|
|
2017-09-06 06:38:14 +00:00
|
|
|
// The offset from the start of the binary to the start of the string table.
|
|
|
|
intptr_t string_table_offset_;
|
|
|
|
|
2019-05-31 22:15:51 +00:00
|
|
|
const uint8_t* kernel_data_;
|
|
|
|
intptr_t kernel_data_size_;
|
2016-10-15 20:48:46 +00:00
|
|
|
|
2017-06-30 05:55:03 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(Program);
|
2016-10-15 20:48:46 +00:00
|
|
|
};
|
|
|
|
|
2017-12-01 05:16:48 +00:00
|
|
|
class KernelLineStartsReader {
|
|
|
|
public:
|
|
|
|
KernelLineStartsReader(const dart::TypedData& line_starts_data,
|
|
|
|
dart::Zone* zone);
|
|
|
|
|
|
|
|
~KernelLineStartsReader() { delete helper_; }
|
|
|
|
|
|
|
|
int32_t DeltaAt(intptr_t index) const {
|
|
|
|
return helper_->At(line_starts_data_, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t LineNumberForPosition(intptr_t position) const;
|
|
|
|
|
|
|
|
void LocationForPosition(intptr_t position,
|
|
|
|
intptr_t* line,
|
|
|
|
intptr_t* col) const;
|
|
|
|
|
|
|
|
void TokenRangeAtLine(intptr_t source_length,
|
|
|
|
intptr_t line_number,
|
|
|
|
dart::TokenPosition* first_token_index,
|
|
|
|
dart::TokenPosition* last_token_index) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
class KernelLineStartsHelper {
|
|
|
|
public:
|
|
|
|
KernelLineStartsHelper() {}
|
|
|
|
virtual ~KernelLineStartsHelper() {}
|
|
|
|
virtual int32_t At(const dart::TypedData& data, intptr_t index) const = 0;
|
|
|
|
|
|
|
|
private:
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(KernelLineStartsHelper);
|
|
|
|
};
|
|
|
|
|
|
|
|
class KernelInt8LineStartsHelper : public KernelLineStartsHelper {
|
|
|
|
public:
|
|
|
|
KernelInt8LineStartsHelper() {}
|
|
|
|
virtual int32_t At(const dart::TypedData& data, intptr_t index) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(KernelInt8LineStartsHelper);
|
|
|
|
};
|
|
|
|
|
|
|
|
class KernelInt16LineStartsHelper : public KernelLineStartsHelper {
|
|
|
|
public:
|
|
|
|
KernelInt16LineStartsHelper() {}
|
|
|
|
virtual int32_t At(const dart::TypedData& data, intptr_t index) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(KernelInt16LineStartsHelper);
|
|
|
|
};
|
|
|
|
|
|
|
|
class KernelInt32LineStartsHelper : public KernelLineStartsHelper {
|
|
|
|
public:
|
|
|
|
KernelInt32LineStartsHelper() {}
|
|
|
|
virtual int32_t At(const dart::TypedData& data, intptr_t index) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(KernelInt32LineStartsHelper);
|
|
|
|
};
|
|
|
|
|
|
|
|
const dart::TypedData& line_starts_data_;
|
|
|
|
KernelLineStartsHelper* helper_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(KernelLineStartsReader);
|
|
|
|
};
|
|
|
|
|
2018-07-17 16:36:50 +00:00
|
|
|
void CollectTokenPositionsFor(const Script& script);
|
|
|
|
|
|
|
|
RawObject* EvaluateMetadata(const Field& metadata_field,
|
|
|
|
bool is_annotations_offset);
|
|
|
|
RawObject* BuildParameterDescriptor(const Function& function);
|
|
|
|
|
2019-03-12 17:58:46 +00:00
|
|
|
// Fills in [is_covariant] and [is_generic_covariant_impl] vectors
|
|
|
|
// according to covariance attributes of [function] parameters.
|
|
|
|
//
|
|
|
|
// [is_covariant] and [is_generic_covariant_impl] should contain bitvectors
|
|
|
|
// of function.NumParameters() length.
|
|
|
|
void ReadParameterCovariance(const Function& function,
|
|
|
|
BitVector* is_covariant,
|
|
|
|
BitVector* is_generic_covariant_impl);
|
|
|
|
|
2018-07-17 16:36:50 +00:00
|
|
|
// Returns true if the given function needs dynamic invocation forwarder:
|
|
|
|
// that is if any of the arguments require checking on the dynamic
|
|
|
|
// call-site: if function has no parameters or has only covariant parameters
|
|
|
|
// as such function already checks all of its parameters.
|
|
|
|
bool NeedsDynamicInvocationForwarder(const Function& function);
|
|
|
|
|
2019-06-12 20:51:44 +00:00
|
|
|
// Returns a list of ParameterTypeChecks needed by a dynamic invocation
|
|
|
|
// forwarder that targets [function]. Indices in these checks correspond to
|
|
|
|
// bytecode frame indices.
|
|
|
|
RawArray* CollectDynamicInvocationChecks(const Function& function);
|
|
|
|
|
2018-10-09 17:23:43 +00:00
|
|
|
ProcedureAttributesMetadata ProcedureAttributesOf(const Function& function,
|
|
|
|
Zone* zone);
|
|
|
|
|
|
|
|
ProcedureAttributesMetadata ProcedureAttributesOf(const Field& field,
|
|
|
|
Zone* zone);
|
2018-09-28 23:49:09 +00:00
|
|
|
|
2016-10-15 20:48:46 +00:00
|
|
|
} // namespace kernel
|
|
|
|
} // namespace dart
|
|
|
|
|
2016-11-16 12:56:20 +00:00
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
2016-10-26 07:26:03 +00:00
|
|
|
#endif // RUNTIME_VM_KERNEL_H_
|