mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 03:07:49 +00:00
[vm] Remove obsolete kernel constant expression evaluator.
Change-Id: I16c515135468e526263db180f7252e7fdebe6414 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/111643 Commit-Queue: Aske Simon Christensen <askesc@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
parent
0e9eadcb71
commit
e8de03915b
|
@ -107,8 +107,8 @@ compiler_sources = [
|
|||
"frontend/bytecode_reader.h",
|
||||
"frontend/bytecode_scope_builder.cc",
|
||||
"frontend/bytecode_scope_builder.h",
|
||||
"frontend/constant_evaluator.cc",
|
||||
"frontend/constant_evaluator.h",
|
||||
"frontend/constant_reader.cc",
|
||||
"frontend/constant_reader.h",
|
||||
"frontend/flow_graph_builder.cc",
|
||||
"frontend/flow_graph_builder.h",
|
||||
"frontend/kernel_binary_flowgraph.cc",
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,188 +0,0 @@
|
|||
// 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_CONSTANT_EVALUATOR_H_
|
||||
#define RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_EVALUATOR_H_
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
#include "vm/compiler/frontend/kernel_translation_helper.h"
|
||||
#include "vm/hash_table.h"
|
||||
#include "vm/object.h"
|
||||
|
||||
namespace dart {
|
||||
namespace kernel {
|
||||
|
||||
class FlowGraphBuilder;
|
||||
|
||||
// There are several cases when we are compiling constant expressions:
|
||||
//
|
||||
// * constant field initializers:
|
||||
// const FieldName = <expr>;
|
||||
//
|
||||
// * constant expressions:
|
||||
// const [<expr>, ...]
|
||||
// const {<expr> : <expr>, ...}
|
||||
// const Constructor(<expr>, ...)
|
||||
//
|
||||
// * constant default parameters:
|
||||
// f(a, [b = <expr>])
|
||||
// f(a, {b: <expr>})
|
||||
//
|
||||
// * constant values to compare in a [SwitchCase]
|
||||
// case <expr>:
|
||||
//
|
||||
// In all cases `<expr>` must be recursively evaluated and canonicalized at
|
||||
// compile-time.
|
||||
class ConstantEvaluator {
|
||||
public:
|
||||
ConstantEvaluator(KernelReaderHelper* helper,
|
||||
TypeTranslator* type_translator,
|
||||
ActiveClass* active_class,
|
||||
FlowGraphBuilder* flow_graph_builder = nullptr);
|
||||
|
||||
virtual ~ConstantEvaluator() {}
|
||||
|
||||
bool IsCached(intptr_t offset);
|
||||
|
||||
RawInstance* EvaluateExpression(intptr_t offset, bool reset_position = true);
|
||||
Instance& EvaluateListLiteral(intptr_t offset, bool reset_position = true);
|
||||
Instance& EvaluateMapLiteral(intptr_t offset, bool reset_position = true);
|
||||
Instance& EvaluateConstructorInvocation(intptr_t offset,
|
||||
bool reset_position = true);
|
||||
Instance& EvaluateStaticInvocation(intptr_t offset,
|
||||
bool reset_position = true);
|
||||
RawObject* EvaluateExpressionSafe(intptr_t offset);
|
||||
RawObject* EvaluateAnnotations();
|
||||
|
||||
// Peeks to see if constant at the given offset will evaluate to
|
||||
// instance of the given clazz.
|
||||
bool IsInstanceConstant(intptr_t constant_offset, const Class& clazz);
|
||||
|
||||
// Evaluates a constant at the given offset (possibly by recursing
|
||||
// into sub-constants).
|
||||
RawInstance* EvaluateConstantExpression(intptr_t constant_offset);
|
||||
|
||||
private:
|
||||
RawInstance* EvaluateConstant(intptr_t constant_offset);
|
||||
|
||||
void BailoutIfBackgroundCompilation();
|
||||
|
||||
bool IsBuildingFlowGraph() const;
|
||||
bool IsAllowedToEvaluate() const;
|
||||
void EvaluateAsExpression();
|
||||
void EvaluateVariableGet(bool is_specialized);
|
||||
void EvaluatePropertyGet();
|
||||
void EvaluateDirectPropertyGet();
|
||||
void EvaluateStaticGet();
|
||||
void EvaluateMethodInvocation();
|
||||
void EvaluateDirectMethodInvocation();
|
||||
void EvaluateSuperMethodInvocation();
|
||||
void EvaluateStaticInvocation();
|
||||
void EvaluateConstructorInvocationInternal();
|
||||
void EvaluateNot();
|
||||
void EvaluateLogicalExpression();
|
||||
void EvaluateConditionalExpression();
|
||||
void EvaluateStringConcatenation();
|
||||
void EvaluateSymbolLiteral();
|
||||
void EvaluateTypeLiteral();
|
||||
void EvaluateListLiteralInternal();
|
||||
void EvaluateMapLiteralInternal();
|
||||
void EvaluateLet();
|
||||
void EvaluatePartialTearoffInstantiation();
|
||||
void EvaluateBigIntLiteral();
|
||||
void EvaluateStringLiteral();
|
||||
void EvaluateIntLiteral(uint8_t payload);
|
||||
void EvaluateIntLiteral(bool is_negative);
|
||||
void EvaluateDoubleLiteral();
|
||||
void EvaluateBoolLiteral(bool value);
|
||||
void EvaluateNullLiteral();
|
||||
|
||||
void EvaluateGetStringLength(intptr_t expression_offset,
|
||||
TokenPosition position);
|
||||
|
||||
const Object& RunFunction(const TokenPosition position,
|
||||
const Function& function,
|
||||
intptr_t argument_count,
|
||||
const Instance* receiver,
|
||||
const TypeArguments* type_args);
|
||||
|
||||
const Object& RunFunction(const TokenPosition position,
|
||||
const Function& function,
|
||||
const Array& arguments,
|
||||
const Array& names);
|
||||
|
||||
const Object& RunMethodCall(const TokenPosition position,
|
||||
const Function& function,
|
||||
const Instance* receiver);
|
||||
|
||||
RawObject* EvaluateConstConstructorCall(const Class& type_class,
|
||||
const TypeArguments& type_arguments,
|
||||
const Function& constructor,
|
||||
const Object& argument);
|
||||
|
||||
const TypeArguments* TranslateTypeArguments(const Function& target,
|
||||
Class* target_klass);
|
||||
|
||||
void AssertBool() {
|
||||
if (!result_.IsBool()) {
|
||||
translation_helper_.ReportError("Expected boolean expression.");
|
||||
}
|
||||
}
|
||||
|
||||
bool EvaluateBooleanExpressionHere();
|
||||
|
||||
bool GetCachedConstant(intptr_t kernel_offset, Instance* value);
|
||||
void CacheConstantValue(intptr_t kernel_offset, const Instance& value);
|
||||
|
||||
KernelReaderHelper* helper_;
|
||||
Isolate* isolate_;
|
||||
Zone* zone_;
|
||||
TranslationHelper& translation_helper_;
|
||||
TypeTranslator& type_translator_;
|
||||
ActiveClass* active_class_;
|
||||
FlowGraphBuilder* flow_graph_builder_;
|
||||
const Script& script_;
|
||||
Instance& result_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ConstantEvaluator);
|
||||
};
|
||||
|
||||
class KernelConstMapKeyEqualsTraits : public AllStatic {
|
||||
public:
|
||||
static const char* Name() { return "KernelConstMapKeyEqualsTraits"; }
|
||||
static bool ReportStats() { return false; }
|
||||
|
||||
static bool IsMatch(const Object& a, const Object& b) {
|
||||
const Smi& key1 = Smi::Cast(a);
|
||||
const Smi& key2 = Smi::Cast(b);
|
||||
return (key1.Value() == key2.Value());
|
||||
}
|
||||
static bool IsMatch(const intptr_t key1, const Object& b) {
|
||||
return KeyAsSmi(key1) == Smi::Cast(b).raw();
|
||||
}
|
||||
static uword Hash(const Object& obj) {
|
||||
const Smi& key = Smi::Cast(obj);
|
||||
return HashValue(key.Value());
|
||||
}
|
||||
static uword Hash(const intptr_t key) {
|
||||
return HashValue(Smi::Value(KeyAsSmi(key)));
|
||||
}
|
||||
static RawObject* NewKey(const intptr_t key) { return KeyAsSmi(key); }
|
||||
|
||||
private:
|
||||
static uword HashValue(intptr_t pos) { return pos % (Smi::kMaxValue - 13); }
|
||||
|
||||
static RawSmi* KeyAsSmi(const intptr_t key) {
|
||||
ASSERT(key >= 0);
|
||||
return Smi::New(key);
|
||||
}
|
||||
};
|
||||
typedef UnorderedHashMap<KernelConstMapKeyEqualsTraits> KernelConstantsMap;
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace dart
|
||||
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
#endif // RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_EVALUATOR_H_
|
322
runtime/vm/compiler/frontend/constant_reader.cc
Normal file
322
runtime/vm/compiler/frontend/constant_reader.cc
Normal file
|
@ -0,0 +1,322 @@
|
|||
// 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.
|
||||
|
||||
#include "vm/compiler/frontend/constant_reader.h"
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
namespace dart {
|
||||
namespace kernel {
|
||||
|
||||
#define Z (zone_)
|
||||
#define H (translation_helper_)
|
||||
|
||||
ConstantReader::ConstantReader(KernelReaderHelper* helper,
|
||||
ActiveClass* active_class)
|
||||
: helper_(helper),
|
||||
zone_(helper->zone_),
|
||||
translation_helper_(helper->translation_helper_),
|
||||
active_class_(active_class),
|
||||
script_(helper->script()),
|
||||
result_(Instance::Handle(zone_)) {}
|
||||
|
||||
RawInstance* ConstantReader::ReadConstantExpression() {
|
||||
Tag tag = helper_->ReadTag(); // read tag.
|
||||
switch (tag) {
|
||||
case kConstantExpression:
|
||||
helper_->ReadPosition();
|
||||
helper_->SkipDartType();
|
||||
result_ = ReadConstant(helper_->ReadUInt());
|
||||
break;
|
||||
case kInvalidExpression: {
|
||||
helper_->ReadPosition(); // Skip position.
|
||||
const String& message = H.DartString(helper_->ReadStringReference());
|
||||
// Invalid expression message has pointer to the source code, no need to
|
||||
// report it twice.
|
||||
H.ReportError(helper_->script(), TokenPosition::kNoSource, "%s",
|
||||
message.ToCString());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
H.ReportError(script_, TokenPosition::kNoSource,
|
||||
"Not a constant expression: unexpected kernel tag %s (%d)",
|
||||
Reader::TagName(tag), tag);
|
||||
}
|
||||
return result_.raw();
|
||||
}
|
||||
|
||||
RawObject* ConstantReader::ReadAnnotations() {
|
||||
intptr_t list_length = helper_->ReadListLength(); // read list length.
|
||||
const Array& metadata_values =
|
||||
Array::Handle(Z, Array::New(list_length, H.allocation_space()));
|
||||
Instance& value = Instance::Handle(Z);
|
||||
for (intptr_t i = 0; i < list_length; ++i) {
|
||||
// This will read the expression.
|
||||
value = ReadConstantExpression();
|
||||
metadata_values.SetAt(i, value);
|
||||
}
|
||||
return metadata_values.raw();
|
||||
}
|
||||
|
||||
RawInstance* ConstantReader::ReadConstant(intptr_t constant_offset) {
|
||||
ASSERT(!H.constants().IsNull());
|
||||
ASSERT(!H.constants_table().IsNull()); // raw bytes
|
||||
|
||||
// For kernel-level cache (in contrast with script-level caching),
|
||||
// we need to access the raw constants array inside the shared
|
||||
// KernelProgramInfo directly, so that all scripts will see the
|
||||
// results after new insertions. These accesses at kernel-level
|
||||
// must be locked since mutator and background compiler can
|
||||
// access the array at the same time.
|
||||
{
|
||||
SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
|
||||
KernelConstantsMap constant_map(H.info().constants());
|
||||
result_ ^= constant_map.GetOrNull(constant_offset);
|
||||
ASSERT(constant_map.Release().raw() == H.info().constants());
|
||||
}
|
||||
|
||||
// On miss, evaluate, and insert value.
|
||||
if (result_.IsNull()) {
|
||||
result_ = ReadConstantInternal(constant_offset);
|
||||
SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
|
||||
KernelConstantsMap constant_map(H.info().constants());
|
||||
auto insert = constant_map.InsertNewOrGetValue(constant_offset, result_);
|
||||
ASSERT(insert == result_.raw());
|
||||
H.info().set_constants(constant_map.Release()); // update!
|
||||
}
|
||||
return result_.raw();
|
||||
}
|
||||
|
||||
bool ConstantReader::IsInstanceConstant(intptr_t constant_offset,
|
||||
const Class& clazz) {
|
||||
// Get reader directly into raw bytes of constant table.
|
||||
KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
|
||||
reader.ReadUInt(); // skip variable-sized int for adjusted constant offset
|
||||
reader.SetOffset(reader.ReaderOffset() + constant_offset);
|
||||
// Peek for an instance of the given clazz.
|
||||
if (reader.ReadByte() == kInstanceConstant) {
|
||||
const NameIndex index = reader.ReadCanonicalNameReference();
|
||||
return H.LookupClassByKernelClass(index) == clazz.raw();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RawInstance* ConstantReader::ReadConstantInternal(intptr_t constant_offset) {
|
||||
// Get reader directly into raw bytes of constant table.
|
||||
KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
|
||||
reader.ReadUInt(); // skip variable-sized int for adjusted constant offset
|
||||
reader.SetOffset(reader.ReaderOffset() + constant_offset);
|
||||
// Construct constant from raw bytes.
|
||||
Instance& instance = Instance::Handle(Z);
|
||||
const intptr_t constant_tag = reader.ReadByte();
|
||||
switch (constant_tag) {
|
||||
case kNullConstant:
|
||||
instance = Instance::null();
|
||||
break;
|
||||
case kBoolConstant:
|
||||
instance = reader.ReadByte() == 1 ? Object::bool_true().raw()
|
||||
: Object::bool_false().raw();
|
||||
break;
|
||||
case kIntConstant: {
|
||||
uint8_t payload = 0;
|
||||
Tag integer_tag = reader.ReadTag(&payload); // read tag.
|
||||
switch (integer_tag) {
|
||||
case kBigIntLiteral: {
|
||||
const String& value = H.DartString(reader.ReadStringReference());
|
||||
instance = Integer::New(value, Heap::kOld);
|
||||
break;
|
||||
}
|
||||
case kSpecializedIntLiteral: {
|
||||
const int64_t value =
|
||||
static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
|
||||
instance = Integer::New(value, Heap::kOld);
|
||||
break;
|
||||
}
|
||||
case kNegativeIntLiteral: {
|
||||
const int64_t value = -static_cast<int64_t>(reader.ReadUInt());
|
||||
instance = Integer::New(value, Heap::kOld);
|
||||
break;
|
||||
}
|
||||
case kPositiveIntLiteral: {
|
||||
const int64_t value = reader.ReadUInt();
|
||||
instance = Integer::New(value, Heap::kOld);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
H.ReportError(
|
||||
script_, TokenPosition::kNoSource,
|
||||
"Cannot lazily read integer: unexpected kernel tag %s (%d)",
|
||||
Reader::TagName(integer_tag), integer_tag);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kDoubleConstant:
|
||||
instance = Double::New(reader.ReadDouble(), Heap::kOld);
|
||||
break;
|
||||
case kStringConstant:
|
||||
instance = H.DartSymbolPlain(reader.ReadStringReference()).raw();
|
||||
break;
|
||||
case kSymbolConstant: {
|
||||
Library& library = Library::Handle(Z);
|
||||
library = Library::InternalLibrary();
|
||||
const auto& symbol_class =
|
||||
Class::Handle(Z, library.LookupClass(Symbols::Symbol()));
|
||||
const auto& symbol_name_field = Field::Handle(
|
||||
Z, symbol_class.LookupInstanceFieldAllowPrivate(Symbols::_name()));
|
||||
ASSERT(!symbol_name_field.IsNull());
|
||||
const NameIndex index = reader.ReadCanonicalNameReference();
|
||||
if (index == -1) {
|
||||
library = Library::null();
|
||||
} else {
|
||||
library = H.LookupLibraryByKernelLibrary(index);
|
||||
}
|
||||
const String& symbol =
|
||||
H.DartIdentifier(library, reader.ReadStringReference());
|
||||
instance = Instance::New(symbol_class, Heap::kOld);
|
||||
instance.SetField(symbol_name_field, symbol);
|
||||
break;
|
||||
}
|
||||
case kListConstant: {
|
||||
const auto& corelib = Library::Handle(Z, Library::CoreLibrary());
|
||||
const auto& list_class =
|
||||
Class::Handle(Z, corelib.LookupClassAllowPrivate(Symbols::_List()));
|
||||
// Build type from the raw bytes (needs temporary translator).
|
||||
TypeTranslator type_translator(&reader, active_class_, true);
|
||||
auto& type_arguments =
|
||||
TypeArguments::Handle(Z, TypeArguments::New(1, Heap::kOld));
|
||||
AbstractType& type = type_translator.BuildType();
|
||||
type_arguments.SetTypeAt(0, type);
|
||||
// Instantiate class.
|
||||
type = Type::New(list_class, type_arguments, TokenPosition::kNoSource);
|
||||
type = ClassFinalizer::FinalizeType(*active_class_->klass, type,
|
||||
ClassFinalizer::kCanonicalize);
|
||||
type_arguments = type.arguments();
|
||||
// Fill array with constant elements.
|
||||
const intptr_t length = reader.ReadUInt();
|
||||
const Array& array =
|
||||
Array::Handle(Z, ImmutableArray::New(length, Heap::kOld));
|
||||
array.SetTypeArguments(type_arguments);
|
||||
Instance& constant = Instance::Handle(Z);
|
||||
for (intptr_t j = 0; j < length; ++j) {
|
||||
// Recurse into lazily evaluating all "sub" constants
|
||||
// needed to evaluate the current constant.
|
||||
const intptr_t entry_offset = reader.ReadUInt();
|
||||
ASSERT(entry_offset < constant_offset); // DAG!
|
||||
constant = ReadConstant(entry_offset);
|
||||
array.SetAt(j, constant);
|
||||
}
|
||||
instance = array.raw();
|
||||
break;
|
||||
}
|
||||
case kInstanceConstant: {
|
||||
const NameIndex index = reader.ReadCanonicalNameReference();
|
||||
const auto& klass = Class::Handle(Z, H.LookupClassByKernelClass(index));
|
||||
if (!klass.is_declaration_loaded() && !klass.is_declared_in_bytecode()) {
|
||||
FATAL1(
|
||||
"Trying to evaluate an instance constant whose references class "
|
||||
"%s is not loaded yet.",
|
||||
klass.ToCString());
|
||||
}
|
||||
const auto& obj = Object::Handle(Z, klass.EnsureIsFinalized(H.thread()));
|
||||
ASSERT(obj.IsNull());
|
||||
instance = Instance::New(klass, Heap::kOld);
|
||||
// Build type from the raw bytes (needs temporary translator).
|
||||
TypeTranslator type_translator(&reader, active_class_, true);
|
||||
const intptr_t number_of_type_arguments = reader.ReadUInt();
|
||||
if (klass.NumTypeArguments() > 0) {
|
||||
auto& type_arguments = TypeArguments::Handle(
|
||||
Z, TypeArguments::New(number_of_type_arguments, Heap::kOld));
|
||||
for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
|
||||
type_arguments.SetTypeAt(j, type_translator.BuildType());
|
||||
}
|
||||
// Instantiate class.
|
||||
auto& type = AbstractType::Handle(
|
||||
Z, Type::New(klass, type_arguments, TokenPosition::kNoSource));
|
||||
type = ClassFinalizer::FinalizeType(*active_class_->klass, type,
|
||||
ClassFinalizer::kCanonicalize);
|
||||
type_arguments = type.arguments();
|
||||
instance.SetTypeArguments(type_arguments);
|
||||
} else {
|
||||
ASSERT(number_of_type_arguments == 0);
|
||||
}
|
||||
// Set the fields.
|
||||
const intptr_t number_of_fields = reader.ReadUInt();
|
||||
Field& field = Field::Handle(Z);
|
||||
Instance& constant = Instance::Handle(Z);
|
||||
for (intptr_t j = 0; j < number_of_fields; ++j) {
|
||||
field = H.LookupFieldByKernelField(reader.ReadCanonicalNameReference());
|
||||
// Recurse into lazily evaluating all "sub" constants
|
||||
// needed to evaluate the current constant.
|
||||
const intptr_t entry_offset = reader.ReadUInt();
|
||||
ASSERT(entry_offset < constant_offset); // DAG!
|
||||
constant = ReadConstant(entry_offset);
|
||||
instance.SetField(field, constant);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kPartialInstantiationConstant: {
|
||||
// Recurse into lazily evaluating the "sub" constant
|
||||
// needed to evaluate the current constant.
|
||||
const intptr_t entry_offset = reader.ReadUInt();
|
||||
ASSERT(entry_offset < constant_offset); // DAG!
|
||||
const auto& constant = Instance::Handle(Z, ReadConstant(entry_offset));
|
||||
ASSERT(!constant.IsNull());
|
||||
|
||||
// Build type from the raw bytes (needs temporary translator).
|
||||
TypeTranslator type_translator(&reader, active_class_, true);
|
||||
const intptr_t number_of_type_arguments = reader.ReadUInt();
|
||||
ASSERT(number_of_type_arguments > 0);
|
||||
auto& type_arguments = TypeArguments::Handle(
|
||||
Z, TypeArguments::New(number_of_type_arguments, Heap::kOld));
|
||||
for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
|
||||
type_arguments.SetTypeAt(j, type_translator.BuildType());
|
||||
}
|
||||
type_arguments = type_arguments.Canonicalize();
|
||||
// Make a copy of the old closure, and set delayed type arguments.
|
||||
Closure& closure = Closure::Handle(Z, Closure::RawCast(constant.raw()));
|
||||
Function& function = Function::Handle(Z, closure.function());
|
||||
const auto& type_arguments2 =
|
||||
TypeArguments::Handle(Z, closure.instantiator_type_arguments());
|
||||
// The function type arguments are used for type parameters from enclosing
|
||||
// closures. Though inner closures cannot be constants. We should
|
||||
// therefore see `null here.
|
||||
ASSERT(closure.function_type_arguments() == TypeArguments::null());
|
||||
Context& context = Context::Handle(Z, closure.context());
|
||||
instance = Closure::New(type_arguments2, Object::null_type_arguments(),
|
||||
type_arguments, function, context, Heap::kOld);
|
||||
break;
|
||||
}
|
||||
case kTearOffConstant: {
|
||||
const NameIndex index = reader.ReadCanonicalNameReference();
|
||||
Function& function =
|
||||
Function::Handle(Z, H.LookupStaticMethodByKernelProcedure(index));
|
||||
function = function.ImplicitClosureFunction();
|
||||
instance = function.ImplicitStaticClosure();
|
||||
break;
|
||||
}
|
||||
case kTypeLiteralConstant: {
|
||||
// Build type from the raw bytes (needs temporary translator).
|
||||
TypeTranslator type_translator(&reader, active_class_, true);
|
||||
instance = type_translator.BuildType().raw();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Set literals (kSetConstant) are currently desugared in the frontend
|
||||
// and will not reach the VM. See http://dartbug.com/35124 for some
|
||||
// discussion. Map constants (kMapConstant ) are already lowered to
|
||||
// InstanceConstant or ListConstant. We should never see unevaluated
|
||||
// constants (kUnevaluatedConstant) in the constant table, they should
|
||||
// have been fully evaluated before we get them.
|
||||
H.ReportError(script_, TokenPosition::kNoSource,
|
||||
"Cannot lazily read constant: unexpected kernel tag (%" Pd
|
||||
")",
|
||||
constant_tag);
|
||||
}
|
||||
return H.Canonicalize(instance);
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace dart
|
||||
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
84
runtime/vm/compiler/frontend/constant_reader.h
Normal file
84
runtime/vm/compiler/frontend/constant_reader.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
// 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_CONSTANT_READER_H_
|
||||
#define RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_READER_H_
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
#include "vm/compiler/frontend/kernel_translation_helper.h"
|
||||
#include "vm/hash_table.h"
|
||||
#include "vm/object.h"
|
||||
|
||||
namespace dart {
|
||||
namespace kernel {
|
||||
|
||||
// Reads and caches constants from the kernel constant pool.
|
||||
class ConstantReader {
|
||||
public:
|
||||
ConstantReader(KernelReaderHelper* helper, ActiveClass* active_class);
|
||||
|
||||
virtual ~ConstantReader() {}
|
||||
|
||||
RawInstance* ReadConstantExpression();
|
||||
RawObject* ReadAnnotations();
|
||||
|
||||
// Peeks to see if constant at the given offset will evaluate to
|
||||
// instance of the given clazz.
|
||||
bool IsInstanceConstant(intptr_t constant_offset, const Class& clazz);
|
||||
|
||||
// Reads a constant at the given offset (possibly by recursing
|
||||
// into sub-constants).
|
||||
RawInstance* ReadConstant(intptr_t constant_offset);
|
||||
|
||||
private:
|
||||
RawInstance* ReadConstantInternal(intptr_t constant_offset);
|
||||
|
||||
KernelReaderHelper* helper_;
|
||||
Zone* zone_;
|
||||
TranslationHelper& translation_helper_;
|
||||
ActiveClass* active_class_;
|
||||
const Script& script_;
|
||||
Instance& result_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ConstantReader);
|
||||
};
|
||||
|
||||
class KernelConstMapKeyEqualsTraits : public AllStatic {
|
||||
public:
|
||||
static const char* Name() { return "KernelConstMapKeyEqualsTraits"; }
|
||||
static bool ReportStats() { return false; }
|
||||
|
||||
static bool IsMatch(const Object& a, const Object& b) {
|
||||
const Smi& key1 = Smi::Cast(a);
|
||||
const Smi& key2 = Smi::Cast(b);
|
||||
return (key1.Value() == key2.Value());
|
||||
}
|
||||
static bool IsMatch(const intptr_t key1, const Object& b) {
|
||||
return KeyAsSmi(key1) == Smi::Cast(b).raw();
|
||||
}
|
||||
static uword Hash(const Object& obj) {
|
||||
const Smi& key = Smi::Cast(obj);
|
||||
return HashValue(key.Value());
|
||||
}
|
||||
static uword Hash(const intptr_t key) {
|
||||
return HashValue(Smi::Value(KeyAsSmi(key)));
|
||||
}
|
||||
static RawObject* NewKey(const intptr_t key) { return KeyAsSmi(key); }
|
||||
|
||||
private:
|
||||
static uword HashValue(intptr_t pos) { return pos % (Smi::kMaxValue - 13); }
|
||||
|
||||
static RawSmi* KeyAsSmi(const intptr_t key) {
|
||||
ASSERT(key >= 0);
|
||||
return Smi::New(key);
|
||||
}
|
||||
};
|
||||
typedef UnorderedHashMap<KernelConstMapKeyEqualsTraits> KernelConstantsMap;
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace dart
|
||||
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
#endif // RUNTIME_VM_COMPILER_FRONTEND_CONSTANT_READER_H_
|
|
@ -52,10 +52,9 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldInitializer() {
|
|||
Fragment body(normal_entry);
|
||||
body += B->CheckStackOverflowInPrologue(field_helper.position_);
|
||||
if (field_helper.IsConst()) {
|
||||
// this will (potentially) read the initializer, but reset the position.
|
||||
body += Constant(Instance::ZoneHandle(
|
||||
Z, constant_evaluator_.EvaluateExpression(ReaderOffset())));
|
||||
SkipExpression(); // read the initializer.
|
||||
// This will read the initializer.
|
||||
body += Constant(
|
||||
Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression()));
|
||||
} else {
|
||||
body += BuildExpression(); // read initializer.
|
||||
}
|
||||
|
@ -78,8 +77,8 @@ void StreamingFlowGraphBuilder::EvaluateConstFieldValue(const Field& field) {
|
|||
|
||||
ASSERT(initializer_tag == kSomething);
|
||||
|
||||
Instance& value = Instance::Handle(
|
||||
Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
|
||||
Instance& value =
|
||||
Instance::Handle(Z, constant_reader_.ReadConstantExpression());
|
||||
field.SetStaticValue(value);
|
||||
}
|
||||
|
||||
|
@ -114,11 +113,9 @@ void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
|
|||
helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
|
||||
Tag tag = ReadTag(); // read (first part of) initializer.
|
||||
if (tag == kSomething) {
|
||||
// this will (potentially) read the initializer,
|
||||
// but reset the position.
|
||||
// This will read the initializer.
|
||||
default_value = &Instance::ZoneHandle(
|
||||
Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
|
||||
SkipExpression(); // read (actual) initializer.
|
||||
Z, constant_reader_.ReadConstantExpression());
|
||||
} else {
|
||||
default_value = &Instance::ZoneHandle(Z, Instance::null());
|
||||
}
|
||||
|
@ -142,11 +139,9 @@ void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
|
|||
helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
|
||||
Tag tag = ReadTag(); // read (first part of) initializer.
|
||||
if (tag == kSomething) {
|
||||
// this will (potentially) read the initializer,
|
||||
// but reset the position.
|
||||
// This will read the initializer.
|
||||
default_value = &Instance::ZoneHandle(
|
||||
Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
|
||||
SkipExpression(); // read (actual) initializer.
|
||||
Z, constant_reader_.ReadConstantExpression());
|
||||
} else {
|
||||
default_value = &Instance::ZoneHandle(Z, Instance::null());
|
||||
}
|
||||
|
@ -1207,13 +1202,9 @@ Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) {
|
|||
case kDirectMethodInvocation:
|
||||
return BuildDirectMethodInvocation(position);
|
||||
case kStaticInvocation:
|
||||
return BuildStaticInvocation(false, position);
|
||||
case kConstStaticInvocation:
|
||||
return BuildStaticInvocation(true, position);
|
||||
return BuildStaticInvocation(position);
|
||||
case kConstructorInvocation:
|
||||
return BuildConstructorInvocation(false, position);
|
||||
case kConstConstructorInvocation:
|
||||
return BuildConstructorInvocation(true, position);
|
||||
return BuildConstructorInvocation(position);
|
||||
case kNot:
|
||||
return BuildNot(position);
|
||||
case kNullCheck:
|
||||
|
@ -1224,21 +1215,10 @@ Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) {
|
|||
return BuildConditionalExpression(position);
|
||||
case kStringConcatenation:
|
||||
return BuildStringConcatenation(position);
|
||||
case kListConcatenation:
|
||||
case kSetConcatenation:
|
||||
case kMapConcatenation:
|
||||
case kInstanceCreation:
|
||||
case kFileUriExpression:
|
||||
// Collection concatenation, instance creation operations and
|
||||
// in-expression URI changes are removed by the constant evaluator.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case kIsExpression:
|
||||
return BuildIsExpression(position);
|
||||
case kAsExpression:
|
||||
return BuildAsExpression(position);
|
||||
case kSymbolLiteral:
|
||||
return BuildSymbolLiteral(position);
|
||||
case kTypeLiteral:
|
||||
return BuildTypeLiteral(position);
|
||||
case kThisExpression:
|
||||
|
@ -1248,19 +1228,14 @@ Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) {
|
|||
case kThrow:
|
||||
return BuildThrow(position);
|
||||
case kListLiteral:
|
||||
return BuildListLiteral(false, position);
|
||||
case kConstListLiteral:
|
||||
return BuildListLiteral(true, position);
|
||||
return BuildListLiteral(position);
|
||||
case kSetLiteral:
|
||||
case kConstSetLiteral:
|
||||
// Set literals are currently desugared in the frontend and will not
|
||||
// reach the VM. See http://dartbug.com/35124 for discussion.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case kMapLiteral:
|
||||
return BuildMapLiteral(false, position);
|
||||
case kConstMapLiteral:
|
||||
return BuildMapLiteral(true, position);
|
||||
return BuildMapLiteral(position);
|
||||
case kFunctionExpression:
|
||||
return BuildFunctionExpression();
|
||||
case kLet:
|
||||
|
@ -1293,6 +1268,22 @@ Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) {
|
|||
case kCheckLibraryIsLoaded:
|
||||
ReadUInt(); // skip library index
|
||||
return BuildFutureNullValue(position);
|
||||
case kConstStaticInvocation:
|
||||
case kConstConstructorInvocation:
|
||||
case kConstListLiteral:
|
||||
case kConstSetLiteral:
|
||||
case kConstMapLiteral:
|
||||
case kSymbolLiteral:
|
||||
// Const invocations and const literals are removed by the
|
||||
// constant evaluator.
|
||||
case kListConcatenation:
|
||||
case kSetConcatenation:
|
||||
case kMapConcatenation:
|
||||
case kInstanceCreation:
|
||||
case kFileUriExpression:
|
||||
// Collection concatenation, instance creation operations and
|
||||
// in-expression URI changes are internal to the front end and
|
||||
// removed by the constant evaluator.
|
||||
default:
|
||||
ReportUnexpectedTag("expression", tag);
|
||||
UNREACHABLE();
|
||||
|
@ -2604,8 +2595,15 @@ Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition* p) {
|
|||
const Field& field =
|
||||
Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
|
||||
if (field.is_const()) {
|
||||
return Constant(Instance::ZoneHandle(
|
||||
Z, constant_evaluator_.EvaluateExpression(offset)));
|
||||
// Since the CFE inlines all references to const variables and fields,
|
||||
// it never emits a StaticGet of a const field.
|
||||
// This situation only arises because of the static const fields in
|
||||
// the ClassID class, which are generated internally in the VM
|
||||
// during loading. See also Class::InjectCIDFields.
|
||||
ASSERT(Class::Handle(field.Owner()).library() ==
|
||||
Library::InternalLibrary() &&
|
||||
Class::Handle(field.Owner()).Name() == Symbols::ClassID().raw());
|
||||
return Constant(Instance::ZoneHandle(Z, field.StaticValue()));
|
||||
} else {
|
||||
const Class& owner = Class::Handle(Z, field.Owner());
|
||||
const String& getter_name = H.DartGetterName(target);
|
||||
|
@ -2627,8 +2625,10 @@ Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition* p) {
|
|||
return StaticCall(position, function, 0, Array::null_array(),
|
||||
ICData::kStatic, &result_type);
|
||||
} else if (H.IsMethod(target)) {
|
||||
return Constant(Instance::ZoneHandle(
|
||||
Z, constant_evaluator_.EvaluateExpression(offset)));
|
||||
const auto& closure_function =
|
||||
Function::Handle(Z, function.ImplicitClosureFunction());
|
||||
return Constant(
|
||||
Instance::ZoneHandle(Z, closure_function.ImplicitStaticClosure()));
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
@ -3091,17 +3091,7 @@ Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
|
|||
}
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
|
||||
TokenPosition* p) {
|
||||
if (is_const) {
|
||||
const intptr_t offset = ReaderOffset() - 1; // Include the tag.
|
||||
(p != NULL) ? * p = ReadPosition() : ReadPosition(); // read position.
|
||||
|
||||
SetOffset(offset);
|
||||
SkipExpression(); // read past this StaticInvocation.
|
||||
return Constant(constant_evaluator_.EvaluateStaticInvocation(offset));
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) {
|
||||
const intptr_t offset = ReaderOffset() - 1; // Include the tag.
|
||||
TokenPosition position = ReadPosition(); // read position.
|
||||
if (p != NULL) *p = position;
|
||||
|
@ -3231,17 +3221,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
|
|||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(
|
||||
bool is_const,
|
||||
TokenPosition* p) {
|
||||
if (is_const) {
|
||||
intptr_t offset = ReaderOffset() - 1; // Include the tag.
|
||||
(p != NULL) ? * p = ReadPosition() : ReadPosition(); // read position.
|
||||
|
||||
SetOffset(offset);
|
||||
SkipExpression(); // read past this ConstructorInvocation.
|
||||
return Constant(constant_evaluator_.EvaluateConstructorInvocation(offset));
|
||||
}
|
||||
|
||||
TokenPosition position = ReadPosition(); // read position.
|
||||
if (p != NULL) *p = position;
|
||||
|
||||
|
@ -3574,16 +3554,6 @@ Fragment StreamingFlowGraphBuilder::BuildAsExpression(TokenPosition* p) {
|
|||
return instructions;
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildSymbolLiteral(
|
||||
TokenPosition* position) {
|
||||
if (position != NULL) *position = TokenPosition::kNoSource;
|
||||
|
||||
intptr_t offset = ReaderOffset() - 1; // EvaluateExpression needs the tag.
|
||||
SkipStringReference(); // read index into string table.
|
||||
return Constant(
|
||||
Instance::ZoneHandle(Z, constant_evaluator_.EvaluateExpression(offset)));
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildTypeLiteral(TokenPosition* position) {
|
||||
if (position != NULL) *position = TokenPosition::kNoSource;
|
||||
|
||||
|
@ -3646,17 +3616,7 @@ Fragment StreamingFlowGraphBuilder::BuildThrow(TokenPosition* p) {
|
|||
return instructions;
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildListLiteral(bool is_const,
|
||||
TokenPosition* p) {
|
||||
if (is_const) {
|
||||
intptr_t offset = ReaderOffset() - 1; // Include the tag.
|
||||
(p != NULL) ? * p = ReadPosition() : ReadPosition(); // read position.
|
||||
|
||||
SetOffset(offset);
|
||||
SkipExpression(); // read past the ListLiteral.
|
||||
return Constant(constant_evaluator_.EvaluateListLiteral(offset));
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) {
|
||||
TokenPosition position = ReadPosition(); // read position.
|
||||
if (p != NULL) *p = position;
|
||||
|
||||
|
@ -3699,17 +3659,7 @@ Fragment StreamingFlowGraphBuilder::BuildListLiteral(bool is_const,
|
|||
return instructions;
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildMapLiteral(bool is_const,
|
||||
TokenPosition* p) {
|
||||
if (is_const) {
|
||||
intptr_t offset = ReaderOffset() - 1; // Include the tag.
|
||||
(p != NULL) ? * p = ReadPosition() : ReadPosition();
|
||||
|
||||
SetOffset(offset);
|
||||
SkipExpression(); // Read past the MapLiteral.
|
||||
return Constant(constant_evaluator_.EvaluateMapLiteral(offset));
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition* p) {
|
||||
TokenPosition position = ReadPosition(); // read position.
|
||||
if (p != NULL) *p = position;
|
||||
|
||||
|
@ -3878,8 +3828,8 @@ Fragment StreamingFlowGraphBuilder::BuildConstantExpression(
|
|||
}
|
||||
if (position != nullptr) *position = p;
|
||||
const intptr_t constant_offset = ReadUInt();
|
||||
Fragment result = Constant(Object::ZoneHandle(
|
||||
Z, constant_evaluator_.EvaluateConstantExpression(constant_offset)));
|
||||
Fragment result = Constant(
|
||||
Object::ZoneHandle(Z, constant_reader_.ReadConstant(constant_offset)));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -4451,16 +4401,6 @@ Fragment StreamingFlowGraphBuilder::BuildSwitchStatement() {
|
|||
if (i == default_case) {
|
||||
ASSERT(i == (case_count - 1));
|
||||
|
||||
// Evaluate the conditions for the default [SwitchCase] just for the
|
||||
// purpose of potentially triggering a compile-time error.
|
||||
|
||||
for (intptr_t j = 0; j < expression_count; ++j) {
|
||||
ReadPosition(); // read jth position.
|
||||
// this reads the expression, but doesn't skip past it.
|
||||
constant_evaluator_.EvaluateExpression(ReaderOffset());
|
||||
SkipExpression(); // read jth expression.
|
||||
}
|
||||
|
||||
if (block.HadJumper(i)) {
|
||||
// There are several branches to the body, so we will make a goto to
|
||||
// the join block (and prepend a join instruction to the real body).
|
||||
|
@ -4484,9 +4424,8 @@ Fragment StreamingFlowGraphBuilder::BuildSwitchStatement() {
|
|||
TargetEntryInstr* otherwise;
|
||||
|
||||
TokenPosition position = ReadPosition(); // read jth position.
|
||||
current_instructions += Constant(Instance::ZoneHandle(
|
||||
Z, constant_evaluator_.EvaluateExpression(ReaderOffset())));
|
||||
SkipExpression(); // read jth expression.
|
||||
current_instructions += Constant(
|
||||
Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression()));
|
||||
current_instructions += PushArgument();
|
||||
current_instructions += LoadLocal(scopes()->switch_variable);
|
||||
current_instructions += PushArgument();
|
||||
|
@ -4936,12 +4875,11 @@ Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
|
|||
instructions += NullConstant();
|
||||
} else {
|
||||
if (helper.IsConst()) {
|
||||
const Instance& constant_value = Instance::ZoneHandle(
|
||||
Z, constant_evaluator_.EvaluateExpression(
|
||||
ReaderOffset())); // read initializer form current position.
|
||||
// Read const initializer form current position.
|
||||
const Instance& constant_value =
|
||||
Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression());
|
||||
variable->SetConstValue(constant_value);
|
||||
instructions += Constant(constant_value);
|
||||
SkipExpression(); // skip initializer.
|
||||
} else {
|
||||
// Initializer
|
||||
instructions += BuildExpression(); // read (actual) initializer.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
#include "vm/compiler/frontend/bytecode_reader.h"
|
||||
#include "vm/compiler/frontend/constant_evaluator.h"
|
||||
#include "vm/compiler/frontend/constant_reader.h"
|
||||
#include "vm/compiler/frontend/kernel_to_il.h"
|
||||
#include "vm/compiler/frontend/kernel_translation_helper.h"
|
||||
#include "vm/compiler/frontend/scope_builder.h"
|
||||
|
@ -37,10 +37,7 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
|
|||
flow_graph_builder_(flow_graph_builder),
|
||||
active_class_(&flow_graph_builder->active_class_),
|
||||
type_translator_(this, active_class_, /* finalize= */ true),
|
||||
constant_evaluator_(this,
|
||||
&type_translator_,
|
||||
active_class_,
|
||||
flow_graph_builder),
|
||||
constant_reader_(this, active_class_),
|
||||
bytecode_metadata_helper_(this, active_class_),
|
||||
direct_call_metadata_helper_(this),
|
||||
inferred_type_metadata_helper_(this),
|
||||
|
@ -299,8 +296,8 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
|
|||
Fragment BuildMethodInvocation(TokenPosition* position);
|
||||
Fragment BuildDirectMethodInvocation(TokenPosition* position);
|
||||
Fragment BuildSuperMethodInvocation(TokenPosition* position);
|
||||
Fragment BuildStaticInvocation(bool is_const, TokenPosition* position);
|
||||
Fragment BuildConstructorInvocation(bool is_const, TokenPosition* position);
|
||||
Fragment BuildStaticInvocation(TokenPosition* position);
|
||||
Fragment BuildConstructorInvocation(TokenPosition* position);
|
||||
Fragment BuildNot(TokenPosition* position);
|
||||
Fragment BuildNullCheck(TokenPosition* position);
|
||||
Fragment BuildLogicalExpression(TokenPosition* position);
|
||||
|
@ -310,13 +307,12 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
|
|||
Fragment BuildStringConcatenation(TokenPosition* position);
|
||||
Fragment BuildIsExpression(TokenPosition* position);
|
||||
Fragment BuildAsExpression(TokenPosition* position);
|
||||
Fragment BuildSymbolLiteral(TokenPosition* position);
|
||||
Fragment BuildTypeLiteral(TokenPosition* position);
|
||||
Fragment BuildThisExpression(TokenPosition* position);
|
||||
Fragment BuildRethrow(TokenPosition* position);
|
||||
Fragment BuildThrow(TokenPosition* position);
|
||||
Fragment BuildListLiteral(bool is_const, TokenPosition* position);
|
||||
Fragment BuildMapLiteral(bool is_const, TokenPosition* position);
|
||||
Fragment BuildListLiteral(TokenPosition* position);
|
||||
Fragment BuildMapLiteral(TokenPosition* position);
|
||||
Fragment BuildFunctionExpression();
|
||||
Fragment BuildLet(TokenPosition* position);
|
||||
Fragment BuildBlockExpression();
|
||||
|
@ -365,7 +361,7 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
|
|||
FlowGraphBuilder* flow_graph_builder_;
|
||||
ActiveClass* const active_class_;
|
||||
TypeTranslator type_translator_;
|
||||
ConstantEvaluator constant_evaluator_;
|
||||
ConstantReader constant_reader_;
|
||||
BytecodeMetadataHelper bytecode_metadata_helper_;
|
||||
DirectCallMetadataHelper direct_call_metadata_helper_;
|
||||
InferredTypeMetadataHelper inferred_type_metadata_helper_;
|
||||
|
|
|
@ -431,13 +431,11 @@ void KernelFingerprintHelper::CalculateExpressionFingerprint() {
|
|||
CalculateArgumentsFingerprint(); // read arguments.
|
||||
return;
|
||||
case kStaticInvocation:
|
||||
case kConstStaticInvocation:
|
||||
ReadPosition(); // read position.
|
||||
CalculateCanonicalNameFingerprint(); // read target_reference.
|
||||
CalculateArgumentsFingerprint(); // read arguments.
|
||||
return;
|
||||
case kConstructorInvocation:
|
||||
case kConstConstructorInvocation:
|
||||
ReadPosition(); // read position.
|
||||
CalculateCanonicalNameFingerprint(); // read target_reference.
|
||||
CalculateArgumentsFingerprint(); // read arguments.
|
||||
|
@ -464,15 +462,6 @@ void KernelFingerprintHelper::CalculateExpressionFingerprint() {
|
|||
ReadPosition(); // read position.
|
||||
CalculateListOfExpressionsFingerprint(); // read list of expressions.
|
||||
return;
|
||||
case kListConcatenation:
|
||||
case kSetConcatenation:
|
||||
case kMapConcatenation:
|
||||
case kInstanceCreation:
|
||||
case kFileUriExpression:
|
||||
// Collection concatenation, instance creation operations and
|
||||
// in-expression URI changes are removed by the constant evaluator.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case kIsExpression:
|
||||
ReadPosition(); // read position.
|
||||
CalculateExpressionFingerprint(); // read operand.
|
||||
|
@ -484,9 +473,6 @@ void KernelFingerprintHelper::CalculateExpressionFingerprint() {
|
|||
CalculateExpressionFingerprint(); // read operand.
|
||||
CalculateDartTypeFingerprint(); // read type.
|
||||
return;
|
||||
case kSymbolLiteral:
|
||||
CalculateStringReferenceFingerprint(); // read index into string table.
|
||||
return;
|
||||
case kTypeLiteral:
|
||||
CalculateDartTypeFingerprint(); // read type.
|
||||
return;
|
||||
|
@ -500,19 +486,16 @@ void KernelFingerprintHelper::CalculateExpressionFingerprint() {
|
|||
CalculateExpressionFingerprint(); // read expression.
|
||||
return;
|
||||
case kListLiteral:
|
||||
case kConstListLiteral:
|
||||
ReadPosition(); // read position.
|
||||
CalculateDartTypeFingerprint(); // read type.
|
||||
CalculateListOfExpressionsFingerprint(); // read list of expressions.
|
||||
return;
|
||||
case kSetLiteral:
|
||||
case kConstSetLiteral:
|
||||
// Set literals are currently desugared in the frontend and will not
|
||||
// reach the VM. See http://dartbug.com/35124 for discussion.
|
||||
UNREACHABLE();
|
||||
return;
|
||||
case kMapLiteral:
|
||||
case kConstMapLiteral: {
|
||||
case kMapLiteral: {
|
||||
ReadPosition(); // read position.
|
||||
CalculateDartTypeFingerprint(); // read type.
|
||||
CalculateDartTypeFingerprint(); // read value type.
|
||||
|
@ -575,6 +558,22 @@ void KernelFingerprintHelper::CalculateExpressionFingerprint() {
|
|||
case kCheckLibraryIsLoaded:
|
||||
ReadUInt(); // skip library index
|
||||
return;
|
||||
case kConstStaticInvocation:
|
||||
case kConstConstructorInvocation:
|
||||
case kConstListLiteral:
|
||||
case kConstSetLiteral:
|
||||
case kConstMapLiteral:
|
||||
case kSymbolLiteral:
|
||||
// Const invocations and const literals are removed by the
|
||||
// constant evaluator.
|
||||
case kListConcatenation:
|
||||
case kSetConcatenation:
|
||||
case kMapConcatenation:
|
||||
case kInstanceCreation:
|
||||
case kFileUriExpression:
|
||||
// Collection concatenation, instance creation operations and
|
||||
// in-expression URI changes are internal to the front end and
|
||||
// removed by the constant evaluator.
|
||||
default:
|
||||
ReportUnexpectedTag("expression", tag);
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -390,7 +390,6 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder {
|
|||
|
||||
friend class BreakableBlock;
|
||||
friend class CatchBlock;
|
||||
friend class ConstantEvaluator;
|
||||
friend class ProgramState;
|
||||
friend class StreamingFlowGraphBuilder;
|
||||
friend class SwitchBlock;
|
||||
|
|
|
@ -2212,13 +2212,11 @@ void KernelReaderHelper::SkipExpression() {
|
|||
SkipArguments(); // read arguments.
|
||||
return;
|
||||
case kStaticInvocation:
|
||||
case kConstStaticInvocation:
|
||||
ReadPosition(); // read position.
|
||||
SkipCanonicalNameReference(); // read procedure_reference.
|
||||
SkipArguments(); // read arguments.
|
||||
return;
|
||||
case kConstructorInvocation:
|
||||
case kConstConstructorInvocation:
|
||||
ReadPosition(); // read position.
|
||||
SkipCanonicalNameReference(); // read target_reference.
|
||||
SkipArguments(); // read arguments.
|
||||
|
@ -2245,15 +2243,6 @@ void KernelReaderHelper::SkipExpression() {
|
|||
ReadPosition(); // read position.
|
||||
SkipListOfExpressions(); // read list of expressions.
|
||||
return;
|
||||
case kListConcatenation:
|
||||
case kSetConcatenation:
|
||||
case kMapConcatenation:
|
||||
case kInstanceCreation:
|
||||
case kFileUriExpression:
|
||||
// Collection concatenation, instance creation operations and
|
||||
// in-expression URI changes are removed by the constant evaluator.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case kIsExpression:
|
||||
ReadPosition(); // read position.
|
||||
SkipExpression(); // read operand.
|
||||
|
@ -2265,9 +2254,6 @@ void KernelReaderHelper::SkipExpression() {
|
|||
SkipExpression(); // read operand.
|
||||
SkipDartType(); // read type.
|
||||
return;
|
||||
case kSymbolLiteral:
|
||||
SkipStringReference(); // read index into string table.
|
||||
return;
|
||||
case kTypeLiteral:
|
||||
SkipDartType(); // read type.
|
||||
return;
|
||||
|
@ -2281,19 +2267,16 @@ void KernelReaderHelper::SkipExpression() {
|
|||
SkipExpression(); // read expression.
|
||||
return;
|
||||
case kListLiteral:
|
||||
case kConstListLiteral:
|
||||
ReadPosition(); // read position.
|
||||
SkipDartType(); // read type.
|
||||
SkipListOfExpressions(); // read list of expressions.
|
||||
return;
|
||||
case kSetLiteral:
|
||||
case kConstSetLiteral:
|
||||
// Set literals are currently desugared in the frontend and will not
|
||||
// reach the VM. See http://dartbug.com/35124 for discussion.
|
||||
UNREACHABLE();
|
||||
return;
|
||||
case kMapLiteral:
|
||||
case kConstMapLiteral: {
|
||||
case kMapLiteral: {
|
||||
ReadPosition(); // read position.
|
||||
SkipDartType(); // read key type.
|
||||
SkipDartType(); // read value type.
|
||||
|
@ -2352,6 +2335,22 @@ void KernelReaderHelper::SkipExpression() {
|
|||
case kCheckLibraryIsLoaded:
|
||||
ReadUInt(); // skip library index
|
||||
return;
|
||||
case kConstStaticInvocation:
|
||||
case kConstConstructorInvocation:
|
||||
case kConstListLiteral:
|
||||
case kConstSetLiteral:
|
||||
case kConstMapLiteral:
|
||||
case kSymbolLiteral:
|
||||
// Const invocations and const literals are removed by the
|
||||
// constant evaluator.
|
||||
case kListConcatenation:
|
||||
case kSetConcatenation:
|
||||
case kMapConcatenation:
|
||||
case kInstanceCreation:
|
||||
case kFileUriExpression:
|
||||
// Collection concatenation, instance creation operations and
|
||||
// in-expression URI changes are internal to the front end and
|
||||
// removed by the constant evaluator.
|
||||
default:
|
||||
ReportUnexpectedTag("expression", tag);
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -1125,7 +1125,7 @@ class KernelReaderHelper {
|
|||
friend class BytecodeReaderHelper;
|
||||
friend class ClassHelper;
|
||||
friend class CallSiteAttributesMetadataHelper;
|
||||
friend class ConstantEvaluator;
|
||||
friend class ConstantReader;
|
||||
friend class ConstantHelper;
|
||||
friend class ConstructorHelper;
|
||||
friend class DirectCallMetadataHelper;
|
||||
|
|
|
@ -750,13 +750,11 @@ void ScopeBuilder::VisitExpression() {
|
|||
helper_.SkipCanonicalNameReference();
|
||||
return;
|
||||
case kStaticInvocation:
|
||||
case kConstStaticInvocation:
|
||||
helper_.ReadPosition(); // read position.
|
||||
helper_.SkipCanonicalNameReference(); // read procedure_reference.
|
||||
VisitArguments(); // read arguments.
|
||||
return;
|
||||
case kConstructorInvocation:
|
||||
case kConstConstructorInvocation:
|
||||
helper_.ReadPosition(); // read position.
|
||||
helper_.SkipCanonicalNameReference(); // read target_reference.
|
||||
VisitArguments(); // read arguments.
|
||||
|
@ -790,15 +788,6 @@ void ScopeBuilder::VisitExpression() {
|
|||
}
|
||||
return;
|
||||
}
|
||||
case kListConcatenation:
|
||||
case kSetConcatenation:
|
||||
case kMapConcatenation:
|
||||
case kInstanceCreation:
|
||||
case kFileUriExpression:
|
||||
// Collection concatenation, instance creation operations and
|
||||
// in-expression URI changes are removed by the constant evaluator.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case kIsExpression:
|
||||
helper_.ReadPosition(); // read position.
|
||||
VisitExpression(); // read operand.
|
||||
|
@ -810,9 +799,6 @@ void ScopeBuilder::VisitExpression() {
|
|||
VisitExpression(); // read operand.
|
||||
VisitDartType(); // read type.
|
||||
return;
|
||||
case kSymbolLiteral:
|
||||
helper_.SkipStringReference(); // read index into string table.
|
||||
return;
|
||||
case kTypeLiteral:
|
||||
VisitDartType(); // read type.
|
||||
return;
|
||||
|
@ -826,8 +812,7 @@ void ScopeBuilder::VisitExpression() {
|
|||
helper_.ReadPosition(); // read position.
|
||||
VisitExpression(); // read expression.
|
||||
return;
|
||||
case kListLiteral:
|
||||
case kConstListLiteral: {
|
||||
case kListLiteral: {
|
||||
helper_.ReadPosition(); // read position.
|
||||
VisitDartType(); // read type.
|
||||
intptr_t list_length = helper_.ReadListLength(); // read list length.
|
||||
|
@ -836,15 +821,13 @@ void ScopeBuilder::VisitExpression() {
|
|||
}
|
||||
return;
|
||||
}
|
||||
case kSetLiteral:
|
||||
case kConstSetLiteral: {
|
||||
case kSetLiteral: {
|
||||
// Set literals are currently desugared in the frontend and will not
|
||||
// reach the VM. See http://dartbug.com/35124 for discussion.
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
case kMapLiteral:
|
||||
case kConstMapLiteral: {
|
||||
case kMapLiteral: {
|
||||
helper_.ReadPosition(); // read position.
|
||||
VisitDartType(); // read key type.
|
||||
VisitDartType(); // read value type.
|
||||
|
@ -930,6 +913,22 @@ void ScopeBuilder::VisitExpression() {
|
|||
case kCheckLibraryIsLoaded:
|
||||
helper_.ReadUInt(); // library index
|
||||
break;
|
||||
case kConstStaticInvocation:
|
||||
case kConstConstructorInvocation:
|
||||
case kConstListLiteral:
|
||||
case kConstSetLiteral:
|
||||
case kConstMapLiteral:
|
||||
case kSymbolLiteral:
|
||||
// Const invocations and const literals are removed by the
|
||||
// constant evaluator.
|
||||
case kListConcatenation:
|
||||
case kSetConcatenation:
|
||||
case kMapConcatenation:
|
||||
case kInstanceCreation:
|
||||
case kFileUriExpression:
|
||||
// Collection concatenation, instance creation operations and
|
||||
// in-expression URI changes are internal to the front end and
|
||||
// removed by the constant evaluator.
|
||||
default:
|
||||
ReportUnexpectedTag("expression", tag);
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "vm/bit_vector.h"
|
||||
#include "vm/compiler/frontend/bytecode_reader.h"
|
||||
#include "vm/compiler/frontend/constant_evaluator.h"
|
||||
#include "vm/compiler/frontend/constant_reader.h"
|
||||
#include "vm/compiler/frontend/kernel_translation_helper.h"
|
||||
#include "vm/compiler/jit/compiler.h"
|
||||
#include "vm/longjump.h"
|
||||
|
@ -489,8 +489,7 @@ class MetadataEvaluator : public KernelReaderHelper {
|
|||
script,
|
||||
data,
|
||||
data_program_offset),
|
||||
type_translator_(this, active_class, /* finalize= */ true),
|
||||
constant_evaluator_(this, &type_translator_, active_class, nullptr) {}
|
||||
constant_reader_(this, active_class) {}
|
||||
|
||||
RawObject* EvaluateMetadata(intptr_t kernel_offset,
|
||||
bool is_annotations_offset) {
|
||||
|
@ -519,12 +518,11 @@ class MetadataEvaluator : public KernelReaderHelper {
|
|||
}
|
||||
}
|
||||
|
||||
return constant_evaluator_.EvaluateAnnotations();
|
||||
return constant_reader_.ReadAnnotations();
|
||||
}
|
||||
|
||||
private:
|
||||
TypeTranslator type_translator_;
|
||||
ConstantEvaluator constant_evaluator_;
|
||||
ConstantReader constant_reader_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MetadataEvaluator);
|
||||
};
|
||||
|
@ -569,14 +567,12 @@ class ParameterDescriptorBuilder : public KernelReaderHelper {
|
|||
script,
|
||||
data,
|
||||
data_program_offset),
|
||||
type_translator_(this, active_class, /* finalize= */ true),
|
||||
constant_evaluator_(this, &type_translator_, active_class, nullptr) {}
|
||||
constant_reader_(this, active_class) {}
|
||||
|
||||
RawObject* BuildParameterDescriptor(const Function& function);
|
||||
|
||||
private:
|
||||
TypeTranslator type_translator_;
|
||||
ConstantEvaluator constant_evaluator_;
|
||||
ConstantReader constant_reader_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ParameterDescriptorBuilder);
|
||||
};
|
||||
|
@ -612,25 +608,25 @@ RawObject* ParameterDescriptorBuilder::BuildParameterDescriptor(
|
|||
|
||||
Tag tag = ReadTag(); // read (first part of) initializer.
|
||||
if ((tag == kSomething) && !function.is_abstract()) {
|
||||
// this will (potentially) read the initializer, but reset the position.
|
||||
// This will read the initializer.
|
||||
Instance& constant = Instance::ZoneHandle(
|
||||
zone_, constant_evaluator_.EvaluateExpression(ReaderOffset()));
|
||||
zone_, constant_reader_.ReadConstantExpression());
|
||||
param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
|
||||
constant);
|
||||
} else {
|
||||
if (tag == kSomething) {
|
||||
SkipExpression(); // Skip initializer.
|
||||
}
|
||||
param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
|
||||
Object::null_instance());
|
||||
}
|
||||
if (tag == kSomething) {
|
||||
SkipExpression(); // read (actual) initializer.
|
||||
}
|
||||
|
||||
if (FLAG_enable_mirrors && (helper.annotation_count_ > 0)) {
|
||||
AlternativeReadingScope alt(&reader_, param_kernel_offset);
|
||||
VariableDeclarationHelper helper(this);
|
||||
helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
|
||||
Object& metadata =
|
||||
Object::ZoneHandle(zone_, constant_evaluator_.EvaluateAnnotations());
|
||||
Object::ZoneHandle(zone_, constant_reader_.ReadAnnotations());
|
||||
param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
|
||||
metadata);
|
||||
} else {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
#include "vm/compiler/frontend/constant_evaluator.h"
|
||||
#include "vm/compiler/frontend/constant_reader.h"
|
||||
#include "vm/compiler/frontend/kernel_translation_helper.h"
|
||||
#include "vm/dart_api_impl.h"
|
||||
#include "vm/flags.h"
|
||||
|
@ -500,8 +500,7 @@ void KernelLoader::AnnotateNativeProcedures() {
|
|||
if (length == 0) return;
|
||||
|
||||
// Prepare lazy constant reading.
|
||||
ConstantEvaluator constant_evaluator(&helper_, &type_translator_,
|
||||
&active_class_);
|
||||
ConstantReader constant_reader(&helper_, &active_class_);
|
||||
|
||||
// Obtain `dart:_internal::ExternalName.name`.
|
||||
EnsureExternalClassIsLookedUp();
|
||||
|
@ -532,10 +531,9 @@ void KernelLoader::AnnotateNativeProcedures() {
|
|||
// We have a candidate. Let's look if it's an instance of the
|
||||
// ExternalName class.
|
||||
const intptr_t constant_table_offset = helper_.ReadUInt();
|
||||
if (constant_evaluator.IsInstanceConstant(constant_table_offset,
|
||||
external_name_class_)) {
|
||||
constant = constant_evaluator.EvaluateConstantExpression(
|
||||
constant_table_offset);
|
||||
if (constant_reader.IsInstanceConstant(constant_table_offset,
|
||||
external_name_class_)) {
|
||||
constant = constant_reader.ReadConstant(constant_table_offset);
|
||||
ASSERT(constant.clazz() == external_name_class_.raw());
|
||||
// We found the annotation, let's flag the function as native and
|
||||
// set the native name!
|
||||
|
@ -619,8 +617,7 @@ void KernelLoader::LoadNativeExtensionLibraries() {
|
|||
}
|
||||
|
||||
// Prepare lazy constant reading.
|
||||
ConstantEvaluator constant_evaluator(&helper_, &type_translator_,
|
||||
&active_class_);
|
||||
ConstantReader constant_reader(&helper_, &active_class_);
|
||||
|
||||
// Obtain `dart:_internal::ExternalName.name`.
|
||||
EnsureExternalClassIsLookedUp();
|
||||
|
@ -665,10 +662,9 @@ void KernelLoader::LoadNativeExtensionLibraries() {
|
|||
// We have a candidate. Let's look if it's an instance of the
|
||||
// ExternalName class.
|
||||
const intptr_t constant_table_offset = helper_.ReadUInt();
|
||||
if (constant_evaluator.IsInstanceConstant(constant_table_offset,
|
||||
external_name_class_)) {
|
||||
constant = constant_evaluator.EvaluateConstantExpression(
|
||||
constant_table_offset);
|
||||
if (constant_reader.IsInstanceConstant(constant_table_offset,
|
||||
external_name_class_)) {
|
||||
constant = constant_reader.ReadConstant(constant_table_offset);
|
||||
ASSERT(constant.clazz() == external_name_class_.raw());
|
||||
uri_path ^= constant.GetField(external_name_field_);
|
||||
}
|
||||
|
@ -1823,8 +1819,7 @@ void KernelLoader::ReadVMAnnotations(const Library& library,
|
|||
const dart::Class& toplevel_class =
|
||||
Class::Handle(Z, library.toplevel_class());
|
||||
ActiveClassScope active_class_scope(&active_class_, &toplevel_class);
|
||||
ConstantEvaluator constant_evaluator(&helper_, &type_translator_,
|
||||
&active_class_);
|
||||
ConstantReader constant_reader(&helper_, &active_class_);
|
||||
|
||||
helper_.ReadByte(); // Skip the tag.
|
||||
|
||||
|
@ -1841,14 +1836,13 @@ void KernelLoader::ReadVMAnnotations(const Library& library,
|
|||
const intptr_t constant_table_offset = helper_.ReadUInt();
|
||||
// We have a candidate. Let's look if it's an instance of the
|
||||
// ExternalName or Pragma class.
|
||||
if (constant_evaluator.IsInstanceConstant(constant_table_offset,
|
||||
external_name_class_)) {
|
||||
constant = constant_evaluator.EvaluateConstantExpression(
|
||||
constant_table_offset);
|
||||
if (constant_reader.IsInstanceConstant(constant_table_offset,
|
||||
external_name_class_)) {
|
||||
constant = constant_reader.ReadConstant(constant_table_offset);
|
||||
ASSERT(constant.clazz() == external_name_class_.raw());
|
||||
*native_name ^= constant.GetField(external_name_field_);
|
||||
} else if (constant_evaluator.IsInstanceConstant(constant_table_offset,
|
||||
pragma_class_)) {
|
||||
} else if (constant_reader.IsInstanceConstant(constant_table_offset,
|
||||
pragma_class_)) {
|
||||
*has_pragma_annotation = true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue