9f49b47823
This is a major revamp of bytecode metadata format. Now bytecode has its own serialization mechanisms. This CL adds 'bytecode component' metadata, which contains bytecode object table and string table. All references from bytecode (constant pools) to libraries, classes, members, types and strings now have a new format. References to frequently used objects are represented as indices in object table, while rarely used objects are written inline. This allows VM to cache frequently used objects while reading bytecode. Representation of strings is aligned with VM - string characters are stored in separate pools of one-byte and two-byte strings. This allows VM to avoid UTF-8 decoding and extra copying. Closure declarations are now explicit. Type parameters no longer require enslosing scopes when reading/writing them. Benchmarks: GenKernelKernelReadAllBytecode (Intel Core i5) +29.84% GenKernelKernelReadAllBytecode (Intel Xeon) +28.74% Change-Id: I4b80009733a8f8c038264af74f97c4e094b9e311 Reviewed-on: https://dart-review.googlesource.com/c/85469 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Régis Crelier <regis@google.com> Reviewed-by: Zach Anderson <zra@google.com>
179 lines
5.9 KiB
C++
179 lines
5.9 KiB
C++
// Copyright (c) 2018, 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_COMPILER_FRONTEND_BYTECODE_READER_H_
|
|
#define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
|
|
|
|
#include "vm/compiler/frontend/kernel_translation_helper.h"
|
|
#include "vm/constants_kbc.h"
|
|
#include "vm/object.h"
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
namespace dart {
|
|
namespace kernel {
|
|
|
|
class BytecodeComponentData;
|
|
|
|
// Helper class which provides access to bytecode metadata.
|
|
class BytecodeMetadataHelper : public MetadataHelper {
|
|
public:
|
|
static const char* tag() { return "vm.bytecode"; }
|
|
|
|
explicit BytecodeMetadataHelper(KernelReaderHelper* helper,
|
|
TypeTranslator* type_translator,
|
|
ActiveClass* active_class);
|
|
|
|
bool HasBytecode(intptr_t node_offset);
|
|
|
|
void ReadMetadata(const Function& function);
|
|
|
|
RawArray* ReadBytecodeComponent();
|
|
|
|
private:
|
|
// These constants should match corresponding constants in class ObjectHandle
|
|
// (pkg/vm/lib/bytecode/object_table.dart).
|
|
static const int kReferenceBit = 1 << 0;
|
|
static const int kIndexShift = 1;
|
|
static const int kKindShift = 1;
|
|
static const int kKindMask = 0x0f;
|
|
static const int kFlagBit0 = 1 << 5;
|
|
static const int kFlagBit1 = 1 << 6;
|
|
static const int kFlagBit2 = 1 << 7;
|
|
static const int kFlagsMask = (kFlagBit0 | kFlagBit1 | kFlagBit2);
|
|
|
|
class FunctionTypeScope : public ValueObject {
|
|
public:
|
|
explicit FunctionTypeScope(BytecodeMetadataHelper* bytecode_reader)
|
|
: bytecode_reader_(bytecode_reader),
|
|
saved_type_parameters_(
|
|
bytecode_reader->function_type_type_parameters_) {}
|
|
|
|
~FunctionTypeScope() {
|
|
bytecode_reader_->function_type_type_parameters_ = saved_type_parameters_;
|
|
}
|
|
|
|
private:
|
|
BytecodeMetadataHelper* bytecode_reader_;
|
|
TypeArguments* const saved_type_parameters_;
|
|
};
|
|
|
|
void ReadClosureDeclaration(const Function& function, intptr_t closureIndex);
|
|
RawType* ReadFunctionSignature(const Function& func,
|
|
bool has_optional_positional_params,
|
|
bool has_optional_named_params,
|
|
bool has_type_params,
|
|
bool has_positional_param_names);
|
|
void ReadTypeParametersDeclaration(const Class& parameterized_class,
|
|
const Function& parameterized_function,
|
|
intptr_t num_type_params);
|
|
|
|
void ReadConstantPool(const Function& function, const ObjectPool& pool);
|
|
RawBytecode* ReadBytecode(const ObjectPool& pool);
|
|
void ReadExceptionsTable(const Bytecode& bytecode, bool has_exceptions_table);
|
|
void ReadSourcePositions(const Bytecode& bytecode, bool has_source_positions);
|
|
RawTypedData* NativeEntry(const Function& function,
|
|
const String& external_name);
|
|
|
|
RawObject* ReadObject();
|
|
RawObject* ReadObjectContents(uint32_t header);
|
|
RawString* ReadString(bool is_canonical = true);
|
|
RawTypeArguments* ReadTypeArguments(const Class& instantiator);
|
|
|
|
TypeTranslator& type_translator_;
|
|
ActiveClass* const active_class_;
|
|
BytecodeComponentData* bytecode_component_;
|
|
Array* closures_;
|
|
TypeArguments* function_type_type_parameters_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(BytecodeMetadataHelper);
|
|
};
|
|
|
|
class BytecodeComponentData : ValueObject {
|
|
public:
|
|
enum {
|
|
kVersion,
|
|
kStringsHeaderOffset,
|
|
kStringsContentsOffset,
|
|
kObjectsContentsOffset,
|
|
kNumFields
|
|
};
|
|
|
|
explicit BytecodeComponentData(const Array& data) : data_(data) {}
|
|
|
|
intptr_t GetVersion() const;
|
|
intptr_t GetStringsHeaderOffset() const;
|
|
intptr_t GetStringsContentsOffset() const;
|
|
intptr_t GetObjectsContentsOffset() const;
|
|
void SetObject(intptr_t index, const Object& obj) const;
|
|
RawObject* GetObject(intptr_t index) const;
|
|
|
|
bool IsNull() const { return data_.IsNull(); }
|
|
|
|
static RawArray* New(Zone* zone,
|
|
intptr_t version,
|
|
intptr_t num_objects,
|
|
intptr_t strings_header_offset,
|
|
intptr_t strings_contents_offset,
|
|
intptr_t objects_contents_offset,
|
|
Heap::Space space);
|
|
|
|
private:
|
|
const Array& data_;
|
|
};
|
|
|
|
class BytecodeReader : public AllStatic {
|
|
public:
|
|
// Reads bytecode for the given function and sets its bytecode field.
|
|
// Returns error (if any), or null.
|
|
static RawError* ReadFunctionBytecode(Thread* thread,
|
|
const Function& function);
|
|
};
|
|
|
|
class BytecodeSourcePositionsIterator : ValueObject {
|
|
public:
|
|
BytecodeSourcePositionsIterator(Zone* zone, const Bytecode& bytecode)
|
|
: reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
|
|
pairs_remaining_(0),
|
|
cur_bci_(0),
|
|
cur_token_pos_(TokenPosition::kNoSource.value()) {
|
|
if (bytecode.HasSourcePositions()) {
|
|
reader_.set_offset(bytecode.source_positions_binary_offset());
|
|
pairs_remaining_ = reader_.ReadUInt();
|
|
}
|
|
}
|
|
|
|
bool MoveNext() {
|
|
if (pairs_remaining_ == 0) {
|
|
return false;
|
|
}
|
|
ASSERT(pairs_remaining_ > 0);
|
|
--pairs_remaining_;
|
|
cur_bci_ += reader_.ReadUInt();
|
|
cur_token_pos_ += reader_.ReadSLEB128();
|
|
return true;
|
|
}
|
|
|
|
intptr_t BytecodeInstructionIndex() const { return cur_bci_; }
|
|
|
|
uword PcOffset() const {
|
|
return KernelBytecode::BytecodePcToOffset(BytecodeInstructionIndex(),
|
|
/* is_return_address = */ true);
|
|
}
|
|
|
|
TokenPosition TokenPos() const { return TokenPosition(cur_token_pos_); }
|
|
|
|
private:
|
|
Reader reader_;
|
|
intptr_t pairs_remaining_;
|
|
intptr_t cur_bci_;
|
|
intptr_t cur_token_pos_;
|
|
};
|
|
|
|
} // namespace kernel
|
|
} // namespace dart
|
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
|
#endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
|