mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 14:32:24 +00:00
991f1aa248
Expressions missing offsets were: - LogicalExpression - ConditionalExpression - Not - BlockExpression - Instantiation - TypedefTearOff* * I'm not sure how TypedefTearOff is actually being used, I don't see reference to it in the VM runtime. Unless the CFE lowers it before the VM gets it. I also added a test on `binary.md` that ensures all expressions include a file offset in their serialized format. This can be expanded to statements if offsets are added to the remaining statement nodes without offsets. TEST=Added binary_md_git_test.dart to ensure all expressions contain offset data going forward. Change-Id: Ieaf80545f388b209f76be44db86ef07e80c8ad66 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/331540 Reviewed-by: Jens Johansen <jensj@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Nate Biggs <natebiggs@google.com>
613 lines
26 KiB
C++
613 lines
26 KiB
C++
// Copyright (c) 2017, 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_BINARY_H_
|
|
#define RUNTIME_VM_KERNEL_BINARY_H_
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
#include "platform/unaligned.h"
|
|
#include "vm/kernel.h"
|
|
#include "vm/object.h"
|
|
|
|
namespace dart {
|
|
namespace kernel {
|
|
|
|
// Keep in sync with package:kernel/lib/binary/tag.dart,
|
|
// package:kernel/binary.md.
|
|
|
|
static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
|
|
static const uint32_t kSupportedKernelFormatVersion = 113;
|
|
|
|
// Keep in sync with package:kernel/lib/binary/tag.dart
|
|
#define KERNEL_TAG_LIST(V) \
|
|
V(Nothing, 0) \
|
|
V(Something, 1) \
|
|
V(Class, 2) \
|
|
V(Extension, 115) \
|
|
V(ExtensionTypeDeclaration, 85) \
|
|
V(FunctionNode, 3) \
|
|
V(Field, 4) \
|
|
V(Constructor, 5) \
|
|
V(Procedure, 6) \
|
|
V(InvalidInitializer, 7) \
|
|
V(FieldInitializer, 8) \
|
|
V(SuperInitializer, 9) \
|
|
V(RedirectingInitializer, 10) \
|
|
V(LocalInitializer, 11) \
|
|
V(AssertInitializer, 12) \
|
|
V(CheckLibraryIsLoaded, 13) \
|
|
V(LoadLibrary, 14) \
|
|
V(EqualsNull, 15) \
|
|
V(EqualsCall, 16) \
|
|
V(StaticTearOff, 17) \
|
|
V(ConstStaticInvocation, 18) \
|
|
V(InvalidExpression, 19) \
|
|
V(VariableGet, 20) \
|
|
V(VariableSet, 21) \
|
|
V(AbstractSuperPropertyGet, 22) \
|
|
V(AbstractSuperPropertySet, 23) \
|
|
V(SuperPropertyGet, 24) \
|
|
V(SuperPropertySet, 25) \
|
|
V(StaticGet, 26) \
|
|
V(StaticSet, 27) \
|
|
V(AbstractSuperMethodInvocation, 28) \
|
|
V(SuperMethodInvocation, 29) \
|
|
V(StaticInvocation, 30) \
|
|
V(ConstructorInvocation, 31) \
|
|
V(ConstConstructorInvocation, 32) \
|
|
V(Not, 33) \
|
|
V(NullCheck, 117) \
|
|
V(LogicalExpression, 34) \
|
|
V(ConditionalExpression, 35) \
|
|
V(StringConcatenation, 36) \
|
|
V(ListConcatenation, 111) \
|
|
V(SetConcatenation, 112) \
|
|
V(MapConcatenation, 113) \
|
|
V(InstanceCreation, 114) \
|
|
V(FileUriExpression, 116) \
|
|
V(IsExpression, 37) \
|
|
V(AsExpression, 38) \
|
|
V(StringLiteral, 39) \
|
|
V(DoubleLiteral, 40) \
|
|
V(TrueLiteral, 41) \
|
|
V(FalseLiteral, 42) \
|
|
V(NullLiteral, 43) \
|
|
V(SymbolLiteral, 44) \
|
|
V(TypeLiteral, 45) \
|
|
V(ThisExpression, 46) \
|
|
V(Rethrow, 47) \
|
|
V(Throw, 48) \
|
|
V(ListLiteral, 49) \
|
|
V(SetLiteral, 109) \
|
|
V(MapLiteral, 50) \
|
|
V(AwaitExpression, 51) \
|
|
V(FunctionExpression, 52) \
|
|
V(Let, 53) \
|
|
V(BlockExpression, 82) \
|
|
V(Instantiation, 54) \
|
|
V(PositiveIntLiteral, 55) \
|
|
V(NegativeIntLiteral, 56) \
|
|
V(BigIntLiteral, 57) \
|
|
V(ConstListLiteral, 58) \
|
|
V(ConstSetLiteral, 110) \
|
|
V(ConstMapLiteral, 59) \
|
|
V(ConstructorTearOff, 60) \
|
|
V(TypedefTearOff, 83) \
|
|
V(RedirectingFactoryTearOff, 84) \
|
|
V(RecordIndexGet, 101) \
|
|
V(RecordNameGet, 102) \
|
|
V(RecordLiteral, 104) \
|
|
V(ConstRecordLiteral, 105) \
|
|
V(ExpressionStatement, 61) \
|
|
V(Block, 62) \
|
|
V(EmptyStatement, 63) \
|
|
V(AssertStatement, 64) \
|
|
V(LabeledStatement, 65) \
|
|
V(BreakStatement, 66) \
|
|
V(WhileStatement, 67) \
|
|
V(DoStatement, 68) \
|
|
V(ForStatement, 69) \
|
|
V(ForInStatement, 70) \
|
|
V(SwitchStatement, 71) \
|
|
V(ContinueSwitchStatement, 72) \
|
|
V(IfStatement, 73) \
|
|
V(ReturnStatement, 74) \
|
|
V(TryCatch, 75) \
|
|
V(TryFinally, 76) \
|
|
V(YieldStatement, 77) \
|
|
V(VariableDeclaration, 78) \
|
|
V(FunctionDeclaration, 79) \
|
|
V(AsyncForInStatement, 80) \
|
|
V(AssertBlock, 81) \
|
|
V(TypedefType, 87) \
|
|
V(InvalidType, 90) \
|
|
V(DynamicType, 91) \
|
|
V(VoidType, 92) \
|
|
V(InterfaceType, 93) \
|
|
V(FunctionType, 94) \
|
|
V(TypeParameterType, 95) \
|
|
V(SimpleInterfaceType, 96) \
|
|
V(SimpleFunctionType, 97) \
|
|
V(NeverType, 98) \
|
|
V(IntersectionType, 99) \
|
|
V(RecordType, 100) \
|
|
V(ExtensionType, 103) \
|
|
V(ConstantExpression, 106) \
|
|
V(FutureOrType, 107) \
|
|
V(FileUriConstantExpression, 108) \
|
|
V(InstanceGet, 118) \
|
|
V(InstanceSet, 119) \
|
|
V(InstanceInvocation, 120) \
|
|
V(InstanceGetterInvocation, 89) \
|
|
V(InstanceTearOff, 121) \
|
|
V(DynamicGet, 122) \
|
|
V(DynamicSet, 123) \
|
|
V(DynamicInvocation, 124) \
|
|
V(FunctionInvocation, 125) \
|
|
V(FunctionTearOff, 126) \
|
|
V(LocalFunctionInvocation, 127) \
|
|
V(AndPattern, 128) \
|
|
V(AssignedVariablePattern, 129) \
|
|
V(CastPattern, 130) \
|
|
V(ConstantPattern, 131) \
|
|
V(InvalidPattern, 132) \
|
|
V(ListPattern, 133) \
|
|
V(MapPattern, 134) \
|
|
V(NamedPattern, 135) \
|
|
V(NullAssertPattern, 136) \
|
|
V(NullCheckPattern, 137) \
|
|
V(ObjectPattern, 138) \
|
|
V(OrPattern, 139) \
|
|
V(RecordPattern, 140) \
|
|
V(RelationalPattern, 141) \
|
|
V(RestPattern, 142) \
|
|
V(VariablePattern, 143) \
|
|
V(WildcardPattern, 144) \
|
|
V(MapPatternEntry, 145) \
|
|
V(MapPatternRestEntry, 146) \
|
|
V(PatternSwitchStatement, 147) \
|
|
V(SwitchExpression, 148) \
|
|
V(IfCaseStatement, 149) \
|
|
V(PatternAssignment, 150) \
|
|
V(PatternVariableDeclaration, 151) \
|
|
V(NullType, 152) \
|
|
V(SpecializedVariableGet, 224) \
|
|
V(SpecializedVariableSet, 232) \
|
|
V(SpecializedIntLiteral, 240)
|
|
|
|
static constexpr intptr_t kSpecializedTagHighBits = 0xe0;
|
|
static constexpr intptr_t kSpecializedTagMask = 0xf8;
|
|
static constexpr intptr_t kSpecializedPayloadMask = 0x7;
|
|
|
|
enum Tag {
|
|
#define DECLARE(Name, value) k##Name = value,
|
|
KERNEL_TAG_LIST(DECLARE)
|
|
#undef DECLARE
|
|
};
|
|
|
|
// Keep in sync with package:kernel/lib/binary/tag.dart
|
|
enum ConstantTag {
|
|
kNullConstant = 0,
|
|
kBoolConstant = 1,
|
|
kIntConstant = 2,
|
|
kDoubleConstant = 3,
|
|
kStringConstant = 4,
|
|
kSymbolConstant = 5,
|
|
kMapConstant = 6,
|
|
kListConstant = 7,
|
|
kSetConstant = 13,
|
|
kInstanceConstant = 8,
|
|
kInstantiationConstant = 9,
|
|
kStaticTearOffConstant = 10,
|
|
kTypeLiteralConstant = 11,
|
|
// These constants are not expected to be seen by the VM, because all
|
|
// constants are fully evaluated.
|
|
kUnevaluatedConstant = 12,
|
|
kTypedefTearOffConstant = 14,
|
|
kConstructorTearOffConstant = 15,
|
|
kRedirectingFactoryTearOffConstant = 16,
|
|
kRecordConstant = 17,
|
|
};
|
|
|
|
// Keep in sync with package:kernel/lib/ast.dart
|
|
enum class KernelNullability : int8_t {
|
|
kUndetermined = 0,
|
|
kNullable = 1,
|
|
kNonNullable = 2,
|
|
kLegacy = 3,
|
|
};
|
|
|
|
// Keep in sync with package:kernel/lib/ast.dart
|
|
enum Variance {
|
|
kUnrelated = 0,
|
|
kCovariant = 1,
|
|
kContravariant = 2,
|
|
kInvariant = 3,
|
|
kLegacyCovariant = 4,
|
|
};
|
|
|
|
// Keep in sync with package:kernel/lib/ast.dart
|
|
enum AsExpressionFlags {
|
|
kAsExpressionFlagTypeError = 1 << 0,
|
|
kAsExpressionFlagCovarianceCheck = 1 << 1,
|
|
kAsExpressionFlagForDynamic = 1 << 2,
|
|
kAsExpressionFlagForNonNullableByDefault = 1 << 3,
|
|
kAsExpressionFlagUnchecked = 1 << 4,
|
|
};
|
|
|
|
// Keep in sync with package:kernel/lib/ast.dart
|
|
enum IsExpressionFlags {
|
|
kIsExpressionFlagForNonNullableByDefault = 1 << 0,
|
|
};
|
|
|
|
// Keep in sync with package:kernel/lib/ast.dart
|
|
enum InstanceInvocationFlags {
|
|
kInstanceInvocationFlagInvariant = 1 << 0,
|
|
kInstanceInvocationFlagBoundsSafe = 1 << 1,
|
|
};
|
|
|
|
// Keep in sync with package:kernel/lib/ast.dart
|
|
enum YieldStatementFlags {
|
|
kYieldStatementFlagYieldStar = 1 << 0,
|
|
};
|
|
|
|
// Keep in sync with package:kernel/lib/ast.dart
|
|
enum class NamedTypeFlags : uint8_t {
|
|
kIsRequired = 1 << 0,
|
|
};
|
|
|
|
// Keep in sync with package:kernel/lib/ast.dart
|
|
enum class FunctionAccessKind {
|
|
kFunction,
|
|
kFunctionType,
|
|
kInapplicable,
|
|
kNullable,
|
|
};
|
|
|
|
static constexpr int SpecializedIntLiteralBias = 3;
|
|
static constexpr int LibraryCountFieldCountFromEnd = 1;
|
|
static constexpr int KernelFormatVersionOffset = 4;
|
|
static constexpr int SourceTableFieldCountFromFirstLibraryOffset = 9;
|
|
|
|
static constexpr int HeaderSize = 8; // 'magic', 'formatVersion'.
|
|
|
|
class Reader : public ValueObject {
|
|
public:
|
|
explicit Reader(const TypedDataBase& typed_data)
|
|
: thread_(Thread::Current()), typed_data_(&typed_data) {
|
|
Init();
|
|
}
|
|
|
|
uint32_t ReadFromIndex(intptr_t end_offset,
|
|
intptr_t fields_before,
|
|
intptr_t list_size,
|
|
intptr_t list_index) {
|
|
intptr_t org_offset = offset();
|
|
uint32_t result =
|
|
ReadFromIndexNoReset(end_offset, fields_before, list_size, list_index);
|
|
offset_ = org_offset;
|
|
return result;
|
|
}
|
|
|
|
uint32_t ReadUInt32At(intptr_t offset) const {
|
|
ASSERT((size_ >= 4) && (offset >= 0) && (offset <= size_ - 4));
|
|
uint32_t value =
|
|
LoadUnaligned(reinterpret_cast<const uint32_t*>(raw_buffer_ + offset));
|
|
return Utils::BigEndianToHost32(value);
|
|
}
|
|
|
|
uint32_t ReadFromIndexNoReset(intptr_t end_offset,
|
|
intptr_t fields_before,
|
|
intptr_t list_size,
|
|
intptr_t list_index) {
|
|
offset_ = end_offset - (fields_before + list_size - list_index) * 4;
|
|
return ReadUInt32();
|
|
}
|
|
|
|
uint32_t ReadUInt32() {
|
|
uint32_t value = ReadUInt32At(offset_);
|
|
offset_ += 4;
|
|
return value;
|
|
}
|
|
|
|
double ReadDouble() {
|
|
ASSERT((size_ >= 8) && (offset_ >= 0) && (offset_ <= size_ - 8));
|
|
double value =
|
|
LoadUnaligned(reinterpret_cast<const double*>(&raw_buffer_[offset_]));
|
|
offset_ += 8;
|
|
return value;
|
|
}
|
|
|
|
uint32_t ReadUInt() {
|
|
ASSERT((size_ >= 1) && (offset_ >= 0) && (offset_ <= size_ - 1));
|
|
|
|
const uint8_t* buffer = raw_buffer_;
|
|
uword byte0 = buffer[offset_];
|
|
if ((byte0 & 0x80) == 0) {
|
|
// 0...
|
|
offset_++;
|
|
return byte0;
|
|
} else if ((byte0 & 0xc0) == 0x80) {
|
|
// 10...
|
|
ASSERT((size_ >= 2) && (offset_ >= 0) && (offset_ <= size_ - 2));
|
|
uint32_t value =
|
|
((byte0 & ~static_cast<uword>(0x80)) << 8) | (buffer[offset_ + 1]);
|
|
offset_ += 2;
|
|
return value;
|
|
} else {
|
|
// 11...
|
|
ASSERT((size_ >= 4) && (offset_ >= 0) && (offset_ <= size_ - 4));
|
|
uint32_t value = ((byte0 & ~static_cast<uword>(0xc0)) << 24) |
|
|
(buffer[offset_ + 1] << 16) |
|
|
(buffer[offset_ + 2] << 8) | (buffer[offset_ + 3] << 0);
|
|
offset_ += 4;
|
|
return value;
|
|
}
|
|
}
|
|
|
|
intptr_t ReadSLEB128() {
|
|
ReadStream stream(raw_buffer_, size_, offset_);
|
|
const intptr_t result = stream.ReadSLEB128();
|
|
offset_ = stream.Position();
|
|
return result;
|
|
}
|
|
|
|
int64_t ReadSLEB128AsInt64() {
|
|
ReadStream stream(raw_buffer_, size_, offset_);
|
|
const int64_t result = stream.ReadSLEB128<int64_t>();
|
|
offset_ = stream.Position();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Read and return a TokenPosition from this reader.
|
|
*/
|
|
TokenPosition ReadPosition() {
|
|
// Position is saved as unsigned,
|
|
// but actually ranges from -1 and up (thus the -1)
|
|
intptr_t value = ReadUInt() - 1;
|
|
TokenPosition result = TokenPosition::Deserialize(value);
|
|
max_position_ = TokenPosition::Max(max_position_, result);
|
|
min_position_ = TokenPosition::Min(min_position_, result);
|
|
return result;
|
|
}
|
|
|
|
intptr_t ReadListLength() { return ReadUInt(); }
|
|
|
|
uint8_t ReadByte() { return raw_buffer_[offset_++]; }
|
|
|
|
uint8_t PeekByte() { return raw_buffer_[offset_]; }
|
|
|
|
void ReadBytes(uint8_t* buffer, uint8_t size) {
|
|
for (int i = 0; i < size; i++) {
|
|
buffer[i] = ReadByte();
|
|
}
|
|
}
|
|
|
|
bool ReadBool() { return (ReadByte() & 1) == 1; }
|
|
|
|
uint8_t ReadFlags() { return ReadByte(); }
|
|
|
|
static const char* TagName(Tag tag);
|
|
|
|
Tag ReadTag(uint8_t* payload = nullptr) {
|
|
uint8_t byte = ReadByte();
|
|
bool has_payload =
|
|
(byte & kSpecializedTagHighBits) == kSpecializedTagHighBits;
|
|
if (has_payload) {
|
|
if (payload != nullptr) {
|
|
*payload = byte & kSpecializedPayloadMask;
|
|
}
|
|
return static_cast<Tag>(byte & kSpecializedTagMask);
|
|
} else {
|
|
return static_cast<Tag>(byte);
|
|
}
|
|
}
|
|
|
|
Tag PeekTag(uint8_t* payload = nullptr) {
|
|
uint8_t byte = PeekByte();
|
|
bool has_payload =
|
|
(byte & kSpecializedTagHighBits) == kSpecializedTagHighBits;
|
|
if (has_payload) {
|
|
if (payload != nullptr) {
|
|
*payload = byte & kSpecializedPayloadMask;
|
|
}
|
|
return static_cast<Tag>(byte & kSpecializedTagMask);
|
|
} else {
|
|
return static_cast<Tag>(byte);
|
|
}
|
|
}
|
|
|
|
static Nullability ConvertNullability(KernelNullability kernel_nullability) {
|
|
switch (kernel_nullability) {
|
|
case KernelNullability::kNullable:
|
|
return Nullability::kNullable;
|
|
case KernelNullability::kLegacy:
|
|
return Nullability::kLegacy;
|
|
case KernelNullability::kNonNullable:
|
|
case KernelNullability::kUndetermined:
|
|
return Nullability::kNonNullable;
|
|
}
|
|
UNREACHABLE();
|
|
}
|
|
|
|
Nullability ReadNullability() {
|
|
const uint8_t byte = ReadByte();
|
|
return ConvertNullability(static_cast<KernelNullability>(byte));
|
|
}
|
|
|
|
Variance ReadVariance() {
|
|
uint8_t byte = ReadByte();
|
|
return static_cast<Variance>(byte);
|
|
}
|
|
|
|
void EnsureEnd() {
|
|
if (offset_ != size_) {
|
|
FATAL(
|
|
"Reading Kernel file: Expected to be at EOF "
|
|
"(offset: %" Pd ", size: %" Pd ")",
|
|
offset_, size_);
|
|
}
|
|
}
|
|
|
|
// The largest position read yet (since last reset).
|
|
// This is automatically updated when calling ReadPosition,
|
|
// but can be overwritten (e.g. via the PositionScope class).
|
|
TokenPosition max_position() { return max_position_; }
|
|
// The smallest position read yet (since last reset).
|
|
// This is automatically updated when calling ReadPosition,
|
|
// but can be overwritten (e.g. via the PositionScope class).
|
|
TokenPosition min_position() { return min_position_; }
|
|
|
|
// A canonical name reference of -1 indicates none (for optional names), not
|
|
// the root name as in the canonical name table.
|
|
NameIndex ReadCanonicalNameReference() { return NameIndex(ReadUInt() - 1); }
|
|
|
|
const TypedDataBase* typed_data() { return typed_data_; }
|
|
|
|
intptr_t offset() const { return offset_; }
|
|
void set_offset(intptr_t offset) {
|
|
ASSERT(offset < size_);
|
|
offset_ = offset;
|
|
}
|
|
intptr_t size() const { return size_; }
|
|
|
|
TypedDataViewPtr ViewFromTo(intptr_t start, intptr_t end) {
|
|
return typed_data_->ViewFromTo(start, end, Heap::kOld);
|
|
}
|
|
|
|
const uint8_t* BufferAt(intptr_t offset) {
|
|
ASSERT((offset >= 0) && (offset < size_));
|
|
return &raw_buffer_[offset];
|
|
}
|
|
|
|
TypedDataPtr ReadLineStartsData(intptr_t line_start_count);
|
|
|
|
private:
|
|
friend class Program;
|
|
friend class AlternativeReadingScopeWithNewData;
|
|
friend class AlternativeReadingScope;
|
|
|
|
Reader(const uint8_t* buffer, intptr_t size)
|
|
: thread_(nullptr),
|
|
raw_buffer_(buffer),
|
|
size_(size) {}
|
|
|
|
void Init() {
|
|
ASSERT(typed_data_->IsExternalOrExternalView());
|
|
raw_buffer_ = reinterpret_cast<uint8_t*>(typed_data_->DataAddr(0));
|
|
size_ = typed_data_->LengthInBytes();
|
|
offset_ = 0;
|
|
}
|
|
|
|
Thread* thread_ = nullptr;
|
|
|
|
// A external typed data or a view on an external typed data.
|
|
const TypedDataBase* typed_data_ = nullptr;
|
|
|
|
// The raw data size/length of [typed_data_].
|
|
const uint8_t* raw_buffer_ = nullptr;
|
|
intptr_t size_ = 0;
|
|
|
|
intptr_t offset_ = 0;
|
|
TokenPosition max_position_ = TokenPosition::kNoSource;
|
|
TokenPosition min_position_ = TokenPosition::kNoSource;
|
|
intptr_t current_script_id_ = -1;
|
|
|
|
friend class PositionScope;
|
|
friend class Program;
|
|
};
|
|
|
|
// A helper class that saves the current reader position, goes to another reader
|
|
// position, and upon destruction, resets to the original reader position.
|
|
class AlternativeReadingScope {
|
|
public:
|
|
AlternativeReadingScope(Reader* reader, intptr_t new_position)
|
|
: reader_(reader), saved_offset_(reader_->offset_) {
|
|
reader_->offset_ = new_position;
|
|
}
|
|
|
|
explicit AlternativeReadingScope(Reader* reader)
|
|
: reader_(reader), saved_offset_(reader_->offset_) {}
|
|
|
|
~AlternativeReadingScope() { reader_->offset_ = saved_offset_; }
|
|
|
|
intptr_t saved_offset() { return saved_offset_; }
|
|
|
|
private:
|
|
Reader* const reader_;
|
|
const intptr_t saved_offset_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(AlternativeReadingScope);
|
|
};
|
|
|
|
// Similar to AlternativeReadingScope, but also switches reading to another
|
|
// typed data array.
|
|
class AlternativeReadingScopeWithNewData {
|
|
public:
|
|
AlternativeReadingScopeWithNewData(Reader* reader,
|
|
const TypedDataBase* new_typed_data,
|
|
intptr_t new_position)
|
|
: reader_(reader),
|
|
saved_size_(reader_->size_),
|
|
saved_raw_buffer_(reader_->raw_buffer_),
|
|
saved_typed_data_(reader_->typed_data_),
|
|
saved_offset_(reader_->offset_) {
|
|
reader_->typed_data_ = new_typed_data;
|
|
reader_->Init();
|
|
reader_->offset_ = new_position;
|
|
}
|
|
|
|
~AlternativeReadingScopeWithNewData() {
|
|
reader_->raw_buffer_ = saved_raw_buffer_;
|
|
reader_->typed_data_ = saved_typed_data_;
|
|
reader_->size_ = saved_size_;
|
|
reader_->offset_ = saved_offset_;
|
|
}
|
|
|
|
intptr_t saved_offset() { return saved_offset_; }
|
|
|
|
private:
|
|
Reader* reader_;
|
|
intptr_t saved_size_;
|
|
const uint8_t* saved_raw_buffer_;
|
|
const TypedDataBase* saved_typed_data_;
|
|
intptr_t saved_offset_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(AlternativeReadingScopeWithNewData);
|
|
};
|
|
|
|
// A helper class that resets the readers min and max positions both upon
|
|
// initialization and upon destruction, i.e. when created the min an max
|
|
// positions will be reset to "noSource", when destructing the min and max will
|
|
// be reset to have they value they would have had, if they hadn't been reset in
|
|
// the first place.
|
|
class PositionScope {
|
|
public:
|
|
explicit PositionScope(Reader* reader)
|
|
: reader_(reader),
|
|
min_(reader->min_position_),
|
|
max_(reader->max_position_) {
|
|
reader->min_position_ = reader->max_position_ = TokenPosition::kNoSource;
|
|
}
|
|
|
|
~PositionScope() {
|
|
reader_->min_position_ = TokenPosition::Min(reader_->min_position_, min_);
|
|
reader_->max_position_ = TokenPosition::Max(reader_->max_position_, max_);
|
|
}
|
|
|
|
private:
|
|
Reader* reader_;
|
|
TokenPosition min_;
|
|
TokenPosition max_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(PositionScope);
|
|
};
|
|
|
|
} // namespace kernel
|
|
} // namespace dart
|
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
|
#endif // RUNTIME_VM_KERNEL_BINARY_H_
|