dart-sdk/runtime/vm/kernel.h

261 lines
8.4 KiB
C
Raw Normal View History

// 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_H_
#define RUNTIME_VM_KERNEL_H_
#include <memory>
#include "platform/assert.h"
#include "vm/allocation.h"
#include "vm/globals.h"
#include "vm/growable_array.h"
#include "vm/object.h"
#include "vm/token_position.h"
namespace dart {
namespace kernel {
class NameIndex {
public:
static const int kInvalidName = -1;
NameIndex() : value_(kInvalidName) {}
explicit NameIndex(int value) : value_(value) {}
operator int() const { return value_; }
private:
int value_;
};
} // namespace kernel
} // namespace dart
#if !defined(DART_PRECOMPILED_RUNTIME)
namespace dart {
class BitVector;
class Field;
class ParsedFunction;
class Zone;
namespace kernel {
class Reader;
struct ProcedureAttributesMetadata;
class TableSelectorMetadata;
class StringIndex {
public:
StringIndex() : value_(-1) {}
explicit StringIndex(int value) : value_(value) {}
operator int() const { return value_; }
private:
int value_;
};
const uint8_t kNativeYieldFlags = 0x2;
enum LogicalOperator { kAnd, kOr };
struct ProgramBinary {
ProgramBinary SubView(intptr_t start, intptr_t end) const {
return {typed_data, kernel_data + start, end - start};
}
const ExternalTypedData* typed_data;
const uint8_t* kernel_data;
intptr_t kernel_data_size;
};
class Program {
public:
// 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.
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);
[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_; }
uint32_t binary_version() { return binary_version_; }
NameIndex main_method() { return main_method_reference_; }
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_; }
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_; }
[kernel] Change constant references; remove need for map Previously constants were referenced via there relative binary offset, i.e. a constant reference saying 42 meant at byte offset 42 relative to the start of the constant table in the binary. This was done to be able to (on the VM side) read the needed constants lazily. It meant, though, that constants had to be stored in a map, mapping from the byte position to the constant. This change adds a level of indirection when needing the lazy reading, but lets the constant references reference the constant number instead so that a constant reference saying 42 means constant number 42, i.e. constants can be stored in a list instead of in a map. This is done on the dart side, but the VM still stores it in a map. The level of indirection is a tabel next to the constant table where each entry has constant size (4 bytes) from which one can read the relative byte offset into the constant table from the constant number, thus still being able to read needed constants lazily. This CL also cleans up a leftover where for instance double constants had their textual representation saved as a string in the string indexer (and thus the output dill) even though they were never referenced. File size changes: * Platform: increses 7,816 bytes. * Compile of dart2js (including platform): decreases 71,424 bytes. Speed changes: * Adding `UserTag`s to the code and looking at observatories cpu profile on a `pkg/kernel/test/binary_bench.dart --golem AstFromBinaryLazy` run of a compile of dart2js reading the constant table has gone from ~10% to ~5%. * Doing statistics on `pkg/kernel/test/binary_bench.dart --raw AstFromBinaryLazy` run of a compile of dart2js says -6.28169% +/- 4.97269%. * Golem runs has nothing above the noise level. It does say "AstFromBinaryLazy (Intel Xeon) -4.006% (0.4 noise)" and "AstFromBinaryEagerP50 (Intel Core i5) -8.929% (0.6 noise)" though. TEST=All tests running the VM tests this. Change-Id: I07ead457527a4477de803ee55ba742f5557413d3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196925 Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
2021-05-04 11:08:31 +00:00
intptr_t component_index_offset() { return component_index_offset_; }
intptr_t library_count() { return library_count_; }
NNBDCompiledMode compilation_mode() const { return compilation_mode_; }
const ProgramBinary& binary() const { return binary_; }
const ExternalTypedData* typed_data() { return binary().typed_data; }
const uint8_t* kernel_data() { return binary().kernel_data; }
intptr_t kernel_data_size() { return binary().kernel_data_size; }
private:
Program() : binary_() {}
[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_;
uint32_t binary_version_;
NameIndex main_method_reference_; // Procedure.
NNBDCompiledMode compilation_mode_;
intptr_t library_count_;
[kernel] Don't scan strings up front when serializing. Currently serializing the ast for kernel is done in two passe: 1) Scan the program to find and index all strings. These are then sorted based on frequency and assigned an id. All string- references are refering to that id. As small numbers use less space in the binary than big numbers, sorting the numbers by frequency saves a certain amount of space. In addition the string indexing is "hijacked" for the "LimitedBinaryPrinter" to also perform some CanonicalName re-indexing. 2) We then serialize the entire thing. This CL gets rid of a pass by not indexing the strings up-front. Whenever it is asked to serialize a string it adds it to the index (if not already there). The serialization is otherwise the same. This means that: 1) Strings are not sorted by frequency, i.e. the binary output size can by bigger (numbers below). 2) The stringindex and canonical names are moved to the end of the binary instead of the front. As we still need it up front for deserialization some additional data is added to the ProgramIndex. 3) The "hijacking" done in "LimitedBinaryPrinter" is replaced by an alternative. 4) We don't spend time on walking the tree twice. The cost is the binary size. Compiling helloworld with fasta, as well as looking at outline.dill, platform.dill and vmservice_io.dill reveals these numbers: * helloworld.dill is 0.657248732% bigger (26573 bytes) * outline.dill is 1.686911399% bigger (9395 bytes) * platform.dill is 0.657062238% bigger (26565 bytes) * vmservice_io.dill is 0.44991899% bigger (19147 bytes) The cost does thus not appear to be very big. The gain is the serialization time. From 20 runs of an instrumented VM/serialization, running numbers through calculations stolens from ministat (https://www.freebsd.org/cgi/man.cgi?query=ministat) reveals the following: * Serialization time: -21.69% +/- 1.44% * Total time spend in relevant parts of bootstrap_nocore.cc, dart_api_impl.cc (Dart_LoadKernel), bootstrap_nocore.cc, dart_api_impl.cc (LoadKernelProgram) as well as serialization: -14.01% +/- 1.58% From 5 runs of "time python tools/test.py -m release -cdartk language -j6" (again run through ministat calculations): * real: -4.18% +/- 0.5% * user: -4.2% +/- 0.29% * sys: No difference at 95% * user+sys: -3.3% +/- 0.36% Change-Id: I1c220eac083496994f0a9f1e2a2445b3707c9a93 Reviewed-on: https://dart-review.googlesource.com/2880 Reviewed-by: Samir Jindel <sjindel@google.com>
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_;
[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_;
[kernel] Change constant references; remove need for map Previously constants were referenced via there relative binary offset, i.e. a constant reference saying 42 meant at byte offset 42 relative to the start of the constant table in the binary. This was done to be able to (on the VM side) read the needed constants lazily. It meant, though, that constants had to be stored in a map, mapping from the byte position to the constant. This change adds a level of indirection when needing the lazy reading, but lets the constant references reference the constant number instead so that a constant reference saying 42 means constant number 42, i.e. constants can be stored in a list instead of in a map. This is done on the dart side, but the VM still stores it in a map. The level of indirection is a tabel next to the constant table where each entry has constant size (4 bytes) from which one can read the relative byte offset into the constant table from the constant number, thus still being able to read needed constants lazily. This CL also cleans up a leftover where for instance double constants had their textual representation saved as a string in the string indexer (and thus the output dill) even though they were never referenced. File size changes: * Platform: increses 7,816 bytes. * Compile of dart2js (including platform): decreases 71,424 bytes. Speed changes: * Adding `UserTag`s to the code and looking at observatories cpu profile on a `pkg/kernel/test/binary_bench.dart --golem AstFromBinaryLazy` run of a compile of dart2js reading the constant table has gone from ~10% to ~5%. * Doing statistics on `pkg/kernel/test/binary_bench.dart --raw AstFromBinaryLazy` run of a compile of dart2js says -6.28169% +/- 4.97269%. * Golem runs has nothing above the noise level. It does say "AstFromBinaryLazy (Intel Xeon) -4.006% (0.4 noise)" and "AstFromBinaryEagerP50 (Intel Core i5) -8.929% (0.6 noise)" though. TEST=All tests running the VM tests this. Change-Id: I07ead457527a4477de803ee55ba742f5557413d3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196925 Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
2021-05-04 11:08:31 +00:00
// The offset from the start of the binary to the start of the ending-index.
intptr_t component_index_offset_;
// The offset from the start of the binary to the canonical name table.
intptr_t name_table_offset_;
// 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_;
[kernel] Don't scan strings up front when serializing. Currently serializing the ast for kernel is done in two passe: 1) Scan the program to find and index all strings. These are then sorted based on frequency and assigned an id. All string- references are refering to that id. As small numbers use less space in the binary than big numbers, sorting the numbers by frequency saves a certain amount of space. In addition the string indexing is "hijacked" for the "LimitedBinaryPrinter" to also perform some CanonicalName re-indexing. 2) We then serialize the entire thing. This CL gets rid of a pass by not indexing the strings up-front. Whenever it is asked to serialize a string it adds it to the index (if not already there). The serialization is otherwise the same. This means that: 1) Strings are not sorted by frequency, i.e. the binary output size can by bigger (numbers below). 2) The stringindex and canonical names are moved to the end of the binary instead of the front. As we still need it up front for deserialization some additional data is added to the ProgramIndex. 3) The "hijacking" done in "LimitedBinaryPrinter" is replaced by an alternative. 4) We don't spend time on walking the tree twice. The cost is the binary size. Compiling helloworld with fasta, as well as looking at outline.dill, platform.dill and vmservice_io.dill reveals these numbers: * helloworld.dill is 0.657248732% bigger (26573 bytes) * outline.dill is 1.686911399% bigger (9395 bytes) * platform.dill is 0.657062238% bigger (26565 bytes) * vmservice_io.dill is 0.44991899% bigger (19147 bytes) The cost does thus not appear to be very big. The gain is the serialization time. From 20 runs of an instrumented VM/serialization, running numbers through calculations stolens from ministat (https://www.freebsd.org/cgi/man.cgi?query=ministat) reveals the following: * Serialization time: -21.69% +/- 1.44% * Total time spend in relevant parts of bootstrap_nocore.cc, dart_api_impl.cc (Dart_LoadKernel), bootstrap_nocore.cc, dart_api_impl.cc (LoadKernelProgram) as well as serialization: -14.01% +/- 1.58% From 5 runs of "time python tools/test.py -m release -cdartk language -j6" (again run through ministat calculations): * real: -4.18% +/- 0.5% * user: -4.2% +/- 0.29% * sys: No difference at 95% * user+sys: -3.3% +/- 0.36% Change-Id: I1c220eac083496994f0a9f1e2a2445b3707c9a93 Reviewed-on: https://dart-review.googlesource.com/2880 Reviewed-by: Samir Jindel <sjindel@google.com>
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_;
ProgramBinary binary_;
DISALLOW_COPY_AND_ASSIGN(Program);
};
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);
}
[vm/compiler] Copy inlined IDs with token positions. When creating new instructions that inherit a token position that represents a source location from another instruction, the inheriting instruction must also have the same inlining ID in order for the source position represented by the token position to be looked up in the correct script. Force this by wrapping both in a single InstructionSource struct which is taken by instructions which take token positions instead of just a token position. That way, it's more work to manually transfer the token position separately from the inlining ID of the instruction than doing the right thing of transfering both at once. To ensure this information is kept consistent, we pass InstructionSource structs through the FlowGraphCompiler all the way down to the CodeSourceMapBuilder. This CL also makes the following changes: * Cache the upper bound of source positions in scripts and use it to add a check for if a given real token position is valid for the script without iterating over the line starts data for each token position. * Start inlining intervals appropriately when adding descriptor and null check information to the code source map. Code size changes are minimal on Flutter gallery in release mode (<0.05% decrease). TEST=Existing tests on trybots, with manual checking with --check-token-positions that previous errors are now removed. Bug: https://github.com/dart-lang/sdk/issues/44436 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-linux-debug-x64-try,vm-kernel-linux-release-x64-try,vm-kernel-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-nnbd-linux-release-x64-try,vm-kernel-linux-product-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-linux-release-simarm64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-ia32-try Change-Id: I23ced262cb4e9fe9d81356f409e7e8d220d63ee0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/173967 Reviewed-by: Régis Crelier <regis@google.com>
2020-12-18 00:42:14 +00:00
int32_t MaxPosition() const;
[vm] Signal bad token positions and lines in KernelLineStartsReader. First, change LocationForPosition and TokenRangeAtLine to return whether they successfully located the offset/line. Also change the wrappers in Script (GetTokenLocation and TokenRangeAtLine) to return whether or not any information was successfully located. These methods now only change the out parameters in the case that appropriate information was found, so any unconditional uses of the out parameters need the out parameters to be appropriately initialized. We now allow negative lines to be requested in TokenRangeAtLine (with the failure behavior described above) so the line returned by LocationAtPosition can be fed into TokenRangeAtLine without intermediate checking. The calculation of the token length, which uses the script source and not the line starts array, has been moved to a new method, Script::GetTokenLength. The new method returns the length (or a negative value if the token length could not be determined) instead of using an out parameter. TEST=Existing tests on trybots, to ensure tests using current line/number info aren't affected. Bug: https://github.com/dart-lang/sdk/issues/44436 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-product-x64-try,vm-kernel-linux-product-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm-try Change-Id: Ibc048a226d11ff9a340a8d249654d07720fdf115 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175365 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Clement Skau <cskau@google.com>
2020-12-16 11:14:12 +00:00
// Returns whether the given offset corresponds to a valid source offset
// If it does, then *line and *column (if column is not nullptr) are set
// to the line and column the token starts at.
DART_WARN_UNUSED_RESULT bool LocationForPosition(
intptr_t position,
intptr_t* line,
intptr_t* col = nullptr) const;
// Returns whether any tokens were found for the given line. When found,
// *first_token_index and *last_token_index are set to the first and
// last token on the line, respectively.
DART_WARN_UNUSED_RESULT bool TokenRangeAtLine(
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);
};
void CollectTokenPositionsFor(const Script& script);
[VM] Read and report constant constructor coverage from dill (2nd try) This CL makes use of the now included constant constructor coverage in the dill file. It works like this: * When the CFE evaluates constants, every constant constructor invocation evaluated saves the reference to the constructor in the `Source` (from the Components uri to source table) for the callers Library. * This data is loaded into the VM in a "raw" format. * When a request for coverage comes in, the VM - on top of the normal coverage processing - goes through all scripts to find constant constructor coverage for the requested script and offset. Note that all scripts must be checked because library A can have evaluated a constructor from library B - so even if only coverage for library B was requested, library A has to be checked. For all constructors found the start and end position is reported as covered. Note that this does not mark any initializes and there are (at least currently) no good way of marking which initializes were evaluated (because it has to be stable across edits even when the `advanced invalidation feature` is enabled). * Note that the reason for the coverage to work on references - as hinted above - is because we want it to be stable across hot reloads even if/when advanced invalidation is enabled. This means, that library A cannot record "positional coverage" for library B because library B might get (for instance) new comments that will make any old offsets invalid. By using references we always lookup in the current world and use the correct offsets. https://github.com/dart-lang/sdk/issues/38934 TEST=Existing test suite, new tests for the new coverage added. Change-Id: I29531247a4b91a99d9a459cfdefbb9798e9c948f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175246 Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Commit-Queue: Jens Johansen <jensj@google.com>
2020-12-08 10:47:43 +00:00
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
ArrayPtr CollectConstConstructorCoverageFrom(const Script& interesting_script);
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
ObjectPtr EvaluateStaticConstFieldInitializer(const Field& field);
ObjectPtr EvaluateMetadata(const Library& library,
intptr_t kernel_offset,
bool is_annotations_offset);
ObjectPtr BuildParameterDescriptor(const Function& function);
// 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);
// 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);
ProcedureAttributesMetadata ProcedureAttributesOf(const Function& function,
Zone* zone);
ProcedureAttributesMetadata ProcedureAttributesOf(const Field& field,
Zone* zone);
TableSelectorMetadata* TableSelectorMetadataForProgram(
const KernelProgramInfo& info,
Zone* zone);
} // namespace kernel
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // RUNTIME_VM_KERNEL_H_