[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:
Aske Simon Christensen 2019-11-11 10:32:24 +00:00 committed by commit-bot@chromium.org
parent 0e9eadcb71
commit e8de03915b
14 changed files with 548 additions and 1778 deletions

View file

@ -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

View file

@ -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_

View 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)

View 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_

View file

@ -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.

View file

@ -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_;

View file

@ -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();

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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();

View file

@ -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 {

View file

@ -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;
}
}