mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 15:09:45 +00:00
[vm] Refactoring: move out classes independent of StreamingFlowGraphBuilder
This change continues refactoring to split kernel_binary_flowgraph and kernel_to_il and move out parts which have no dependencies on flow graph construction. Bytecode reading is moved to a separate file bytecode_reader{.h, .cc}. Metadata helpers, TypeTranslator, ActiveClass and other Active* are moved to kernel_translation_helper. Removed dependency of ICData tags on IL Instruction tags, so ICData objects can be created by bytecode reader without depending on IL. Unused AlternativeScriptScope is removed. Change-Id: Ic9f98af82697b48013fb89802076b56833acf55d Reviewed-on: https://dart-review.googlesource.com/63262 Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Régis Crelier <regis@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
aa009339b3
commit
8c63d578a6
|
@ -2444,7 +2444,7 @@ class ICDataSerializationCluster : public SerializationCluster {
|
|||
}
|
||||
s->Write<uint32_t>(ic->ptr()->state_bits_);
|
||||
#if defined(TAG_IC_DATA)
|
||||
s->Write<int32_t>(ic->ptr()->tag_);
|
||||
s->Write<int32_t>(static_cast<int32_t>(ic->ptr()->tag_));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -2489,7 +2489,7 @@ class ICDataDeserializationCluster : public DeserializationCluster {
|
|||
NOT_IN_PRECOMPILED(ic->ptr()->deopt_id_ = d->Read<int32_t>());
|
||||
ic->ptr()->state_bits_ = d->Read<int32_t>();
|
||||
#if defined(TAG_IC_DATA)
|
||||
ic->ptr()->tag_ = d->Read<int32_t>();
|
||||
ic->ptr()->tag_ = static_cast<ICData::Tag>(d->Read<int32_t>());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1649,7 +1649,7 @@ const ICData* FlowGraphCompiler::GetOrAddInstanceCallICData(
|
|||
arguments_descriptor, deopt_id, num_args_tested,
|
||||
ICData::kInstance));
|
||||
#if defined(TAG_IC_DATA)
|
||||
ic_data.set_tag(Instruction::kInstanceCall);
|
||||
ic_data.set_tag(ICData::Tag::kInstanceCall);
|
||||
#endif
|
||||
if (deopt_id_to_ic_data_ != NULL) {
|
||||
(*deopt_id_to_ic_data_)[deopt_id] = &ic_data;
|
||||
|
@ -1683,7 +1683,7 @@ const ICData* FlowGraphCompiler::GetOrAddStaticCallICData(
|
|||
deopt_id, num_args_tested, rebind_rule));
|
||||
ic_data.AddTarget(target);
|
||||
#if defined(TAG_IC_DATA)
|
||||
ic_data.set_tag(Instruction::kStaticCall);
|
||||
ic_data.set_tag(ICData::Tag::kStaticCall);
|
||||
#endif
|
||||
if (deopt_id_to_ic_data_ != NULL) {
|
||||
(*deopt_id_to_ic_data_)[deopt_id] = &ic_data;
|
||||
|
|
|
@ -320,9 +320,20 @@ const ICData* Instruction::GetICData(
|
|||
const ICData* result = ic_data_array[deopt_id_];
|
||||
#if defined(TAG_IC_DATA)
|
||||
if (result != NULL) {
|
||||
if (result->tag() == -1) {
|
||||
result->set_tag(tag());
|
||||
} else if (result->tag() != tag()) {
|
||||
ICData::Tag ic_data_tag = ICData::Tag::kUnknown;
|
||||
switch (tag()) {
|
||||
case kInstanceCall:
|
||||
ic_data_tag = ICData::Tag::kInstanceCall;
|
||||
break;
|
||||
case kStaticCall:
|
||||
ic_data_tag = ICData::Tag::kStaticCall;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
if (result->tag() == ICData::Tag::kUnknown) {
|
||||
result->set_tag(ic_data_tag);
|
||||
} else if (result->tag() != ic_data_tag) {
|
||||
FATAL("ICData tag mismatch");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@ compiler_sources = [
|
|||
"cha.h",
|
||||
"compiler_pass.cc",
|
||||
"compiler_pass.h",
|
||||
"frontend/bytecode_reader.cc",
|
||||
"frontend/bytecode_reader.h",
|
||||
"frontend/flow_graph_builder.cc",
|
||||
"frontend/flow_graph_builder.h",
|
||||
"frontend/kernel_binary_flowgraph.cc",
|
||||
|
|
612
runtime/vm/compiler/frontend/bytecode_reader.cc
Normal file
612
runtime/vm/compiler/frontend/bytecode_reader.cc
Normal file
|
@ -0,0 +1,612 @@
|
|||
// 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/bytecode_reader.h"
|
||||
|
||||
#include "vm/bootstrap.h"
|
||||
#include "vm/code_descriptors.h"
|
||||
#include "vm/compiler/assembler/disassembler_kbc.h"
|
||||
#include "vm/dart_entry.h"
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
#if defined(DART_USE_INTERPRETER)
|
||||
|
||||
#define Z (zone_)
|
||||
#define H (translation_helper_)
|
||||
#define T (type_translator_)
|
||||
#define I Isolate::Current()
|
||||
|
||||
namespace dart {
|
||||
|
||||
DEFINE_FLAG(bool, dump_kernel_bytecode, false, "Dump kernel bytecode");
|
||||
|
||||
namespace kernel {
|
||||
|
||||
BytecodeMetadataHelper::BytecodeMetadataHelper(KernelReaderHelper* helper,
|
||||
TypeTranslator* type_translator,
|
||||
ActiveClass* active_class)
|
||||
: MetadataHelper(helper, tag(), /* precompiler_only = */ false),
|
||||
type_translator_(*type_translator),
|
||||
active_class_(active_class) {}
|
||||
|
||||
void BytecodeMetadataHelper::ReadMetadata(const Function& function) {
|
||||
const intptr_t node_offset = function.kernel_offset();
|
||||
const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
|
||||
if (md_offset < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
|
||||
md_offset);
|
||||
|
||||
// Create object pool and read pool entries.
|
||||
const intptr_t obj_count = helper_->reader_.ReadListLength();
|
||||
const ObjectPool& pool =
|
||||
ObjectPool::Handle(helper_->zone_, ObjectPool::New(obj_count));
|
||||
ReadPoolEntries(function, function, pool, 0);
|
||||
|
||||
// Read bytecode and attach to function.
|
||||
const Code& bytecode = Code::Handle(helper_->zone_, ReadBytecode(pool));
|
||||
function.AttachBytecode(bytecode);
|
||||
|
||||
// Read exceptions table.
|
||||
ReadExceptionsTable(bytecode);
|
||||
|
||||
if (FLAG_dump_kernel_bytecode) {
|
||||
KernelBytecodeDisassembler::Disassemble(function);
|
||||
}
|
||||
|
||||
// Read closures.
|
||||
Function& closure = Function::Handle(helper_->zone_);
|
||||
Code& closure_bytecode = Code::Handle(helper_->zone_);
|
||||
intptr_t num_closures = helper_->ReadListLength();
|
||||
for (intptr_t i = 0; i < num_closures; i++) {
|
||||
intptr_t closure_index = helper_->ReadUInt();
|
||||
ASSERT(closure_index < obj_count);
|
||||
closure ^= pool.ObjectAt(closure_index);
|
||||
|
||||
// Read closure bytecode and attach to closure function.
|
||||
closure_bytecode = ReadBytecode(pool);
|
||||
closure.AttachBytecode(closure_bytecode);
|
||||
|
||||
// Read closure exceptions table.
|
||||
ReadExceptionsTable(closure_bytecode);
|
||||
|
||||
if (FLAG_dump_kernel_bytecode) {
|
||||
KernelBytecodeDisassembler::Disassemble(closure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
|
||||
const Function& inner_function,
|
||||
const ObjectPool& pool,
|
||||
intptr_t from_index) {
|
||||
// These enums and the code below reading the constant pool from kernel must
|
||||
// be kept in sync with pkg/vm/lib/bytecode/constant_pool.dart.
|
||||
enum ConstantPoolTag {
|
||||
kInvalid,
|
||||
kNull,
|
||||
kString,
|
||||
kInt,
|
||||
kDouble,
|
||||
kBool,
|
||||
kArgDesc,
|
||||
kICData,
|
||||
kStaticICData,
|
||||
kField,
|
||||
kFieldOffset,
|
||||
kClass,
|
||||
kTypeArgumentsFieldOffset,
|
||||
kTearOff,
|
||||
kType,
|
||||
kTypeArguments,
|
||||
kList,
|
||||
kInstance,
|
||||
kSymbol,
|
||||
kTypeArgumentsForInstanceAllocation,
|
||||
kContextOffset,
|
||||
kClosureFunction,
|
||||
kEndClosureFunctionScope,
|
||||
kNativeEntry,
|
||||
kSubtypeTestCache,
|
||||
};
|
||||
|
||||
enum InvocationKind {
|
||||
method, // x.foo(...) or foo(...)
|
||||
getter, // x.foo
|
||||
setter // x.foo = ...
|
||||
};
|
||||
|
||||
Object& obj = Object::Handle(helper_->zone_);
|
||||
Object& elem = Object::Handle(helper_->zone_);
|
||||
Array& array = Array::Handle(helper_->zone_);
|
||||
Field& field = Field::Handle(helper_->zone_);
|
||||
Class& cls = Class::Handle(helper_->zone_);
|
||||
String& name = String::Handle(helper_->zone_);
|
||||
TypeArguments& type_args = TypeArguments::Handle(helper_->zone_);
|
||||
const intptr_t obj_count = pool.Length();
|
||||
for (intptr_t i = from_index; i < obj_count; ++i) {
|
||||
const intptr_t tag = helper_->ReadTag();
|
||||
switch (tag) {
|
||||
case ConstantPoolTag::kInvalid:
|
||||
UNREACHABLE();
|
||||
case ConstantPoolTag::kNull:
|
||||
obj = Object::null();
|
||||
break;
|
||||
case ConstantPoolTag::kString:
|
||||
obj = H.DartString(helper_->ReadStringReference()).raw();
|
||||
ASSERT(obj.IsString());
|
||||
obj = H.Canonicalize(String::Cast(obj));
|
||||
break;
|
||||
case ConstantPoolTag::kInt: {
|
||||
uint32_t low_bits = helper_->ReadUInt32();
|
||||
int64_t value = helper_->ReadUInt32();
|
||||
value = (value << 32) | low_bits;
|
||||
obj = Integer::New(value);
|
||||
} break;
|
||||
case ConstantPoolTag::kDouble: {
|
||||
uint32_t low_bits = helper_->ReadUInt32();
|
||||
uint64_t bits = helper_->ReadUInt32();
|
||||
bits = (bits << 32) | low_bits;
|
||||
double value = bit_cast<double, uint64_t>(bits);
|
||||
obj = Double::New(value);
|
||||
} break;
|
||||
case ConstantPoolTag::kBool:
|
||||
if (helper_->ReadUInt() == 1) {
|
||||
obj = Bool::True().raw();
|
||||
} else {
|
||||
obj = Bool::False().raw();
|
||||
}
|
||||
break;
|
||||
case ConstantPoolTag::kArgDesc: {
|
||||
intptr_t num_arguments = helper_->ReadUInt();
|
||||
intptr_t num_type_args = helper_->ReadUInt();
|
||||
intptr_t num_arg_names = helper_->ReadListLength();
|
||||
if (num_arg_names == 0) {
|
||||
obj = ArgumentsDescriptor::New(num_type_args, num_arguments);
|
||||
} else {
|
||||
array = Array::New(num_arg_names);
|
||||
for (intptr_t j = 0; j < num_arg_names; j++) {
|
||||
array.SetAt(j, H.DartSymbolPlain(helper_->ReadStringReference()));
|
||||
}
|
||||
obj = ArgumentsDescriptor::New(num_type_args, num_arguments, array);
|
||||
}
|
||||
} break;
|
||||
case ConstantPoolTag::kICData: {
|
||||
InvocationKind kind = static_cast<InvocationKind>(helper_->ReadByte());
|
||||
if (kind == InvocationKind::getter) {
|
||||
name = helper_->ReadNameAsGetterName().raw();
|
||||
} else if (kind == InvocationKind::setter) {
|
||||
name = helper_->ReadNameAsSetterName().raw();
|
||||
} else {
|
||||
ASSERT(kind == InvocationKind::method);
|
||||
name = helper_->ReadNameAsMethodName().raw();
|
||||
}
|
||||
intptr_t arg_desc_index = helper_->ReadUInt();
|
||||
ASSERT(arg_desc_index < i);
|
||||
array ^= pool.ObjectAt(arg_desc_index);
|
||||
// TODO(regis): Should num_args_tested be explicitly provided?
|
||||
obj = ICData::New(function, name,
|
||||
array, // Arguments descriptor.
|
||||
Thread::kNoDeoptId, 1 /* num_args_tested */,
|
||||
ICData::RebindRule::kInstance);
|
||||
#if defined(TAG_IC_DATA)
|
||||
ICData::Cast(obj).set_tag(ICData::Tag::kInstanceCall);
|
||||
#endif
|
||||
} break;
|
||||
case ConstantPoolTag::kStaticICData: {
|
||||
InvocationKind kind = static_cast<InvocationKind>(helper_->ReadByte());
|
||||
NameIndex target = helper_->ReadCanonicalNameReference();
|
||||
if (H.IsConstructor(target)) {
|
||||
name = H.DartConstructorName(target).raw();
|
||||
elem = H.LookupConstructorByKernelConstructor(target);
|
||||
} else if (H.IsField(target)) {
|
||||
if (kind == InvocationKind::getter) {
|
||||
name = H.DartGetterName(target).raw();
|
||||
} else if (kind == InvocationKind::setter) {
|
||||
name = H.DartSetterName(target).raw();
|
||||
} else {
|
||||
ASSERT(kind == InvocationKind::method);
|
||||
UNIMPLEMENTED(); // TODO(regis): Revisit.
|
||||
}
|
||||
field = H.LookupFieldByKernelField(target);
|
||||
cls = field.Owner();
|
||||
elem = cls.LookupFunctionAllowPrivate(name);
|
||||
} else {
|
||||
if ((kind == InvocationKind::method) && H.IsGetter(target)) {
|
||||
UNIMPLEMENTED(); // TODO(regis): Revisit.
|
||||
}
|
||||
name = H.DartProcedureName(target).raw();
|
||||
elem = H.LookupStaticMethodByKernelProcedure(target);
|
||||
}
|
||||
ASSERT(elem.IsFunction());
|
||||
intptr_t arg_desc_index = helper_->ReadUInt();
|
||||
ASSERT(arg_desc_index < i);
|
||||
array ^= pool.ObjectAt(arg_desc_index);
|
||||
obj = ICData::New(function, name,
|
||||
array, // Arguments descriptor.
|
||||
Thread::kNoDeoptId, 0 /* num_args_tested */,
|
||||
ICData::RebindRule::kStatic);
|
||||
ICData::Cast(obj).AddTarget(Function::Cast(elem));
|
||||
#if defined(TAG_IC_DATA)
|
||||
ICData::Cast(obj).set_tag(ICData::Tag::kStaticCall);
|
||||
#endif
|
||||
} break;
|
||||
case ConstantPoolTag::kField:
|
||||
obj = H.LookupFieldByKernelField(helper_->ReadCanonicalNameReference());
|
||||
ASSERT(obj.IsField());
|
||||
break;
|
||||
case ConstantPoolTag::kFieldOffset:
|
||||
obj = H.LookupFieldByKernelField(helper_->ReadCanonicalNameReference());
|
||||
ASSERT(obj.IsField());
|
||||
obj = Smi::New(Field::Cast(obj).Offset() / kWordSize);
|
||||
break;
|
||||
case ConstantPoolTag::kClass:
|
||||
obj = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
|
||||
ASSERT(obj.IsClass());
|
||||
break;
|
||||
case ConstantPoolTag::kTypeArgumentsFieldOffset:
|
||||
cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
|
||||
obj = Smi::New(cls.type_arguments_field_offset() / kWordSize);
|
||||
break;
|
||||
case ConstantPoolTag::kTearOff:
|
||||
obj = H.LookupStaticMethodByKernelProcedure(
|
||||
helper_->ReadCanonicalNameReference());
|
||||
ASSERT(obj.IsFunction());
|
||||
obj = Function::Cast(obj).ImplicitClosureFunction();
|
||||
ASSERT(obj.IsFunction());
|
||||
obj = Function::Cast(obj).ImplicitStaticClosure();
|
||||
ASSERT(obj.IsInstance());
|
||||
obj = H.Canonicalize(Instance::Cast(obj));
|
||||
break;
|
||||
case ConstantPoolTag::kType:
|
||||
obj = type_translator_.BuildType().raw();
|
||||
ASSERT(obj.IsAbstractType());
|
||||
break;
|
||||
case ConstantPoolTag::kTypeArguments:
|
||||
obj = type_translator_.BuildTypeArguments(helper_->ReadListLength())
|
||||
.raw();
|
||||
ASSERT(obj.IsNull() || obj.IsTypeArguments());
|
||||
break;
|
||||
case ConstantPoolTag::kList: {
|
||||
obj = type_translator_.BuildType().raw();
|
||||
ASSERT(obj.IsAbstractType());
|
||||
const intptr_t length = helper_->ReadListLength();
|
||||
array = Array::New(length, AbstractType::Cast(obj));
|
||||
for (intptr_t j = 0; j < length; j++) {
|
||||
intptr_t elem_index = helper_->ReadUInt();
|
||||
ASSERT(elem_index < i);
|
||||
elem = pool.ObjectAt(elem_index);
|
||||
array.SetAt(j, elem);
|
||||
}
|
||||
obj = H.Canonicalize(Array::Cast(array));
|
||||
ASSERT(!obj.IsNull());
|
||||
} break;
|
||||
case ConstantPoolTag::kInstance: {
|
||||
cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
|
||||
obj = Instance::New(cls, Heap::kOld);
|
||||
intptr_t type_args_index = helper_->ReadUInt();
|
||||
ASSERT(type_args_index < i);
|
||||
type_args ^= pool.ObjectAt(type_args_index);
|
||||
if (!type_args.IsNull()) {
|
||||
Instance::Cast(obj).SetTypeArguments(type_args);
|
||||
}
|
||||
intptr_t num_fields = helper_->ReadUInt();
|
||||
for (intptr_t j = 0; j < num_fields; j++) {
|
||||
NameIndex field_name = helper_->ReadCanonicalNameReference();
|
||||
ASSERT(H.IsField(field_name));
|
||||
field = H.LookupFieldByKernelField(field_name);
|
||||
intptr_t elem_index = helper_->ReadUInt();
|
||||
ASSERT(elem_index < i);
|
||||
elem = pool.ObjectAt(elem_index);
|
||||
Instance::Cast(obj).SetField(field, elem);
|
||||
}
|
||||
obj = H.Canonicalize(Instance::Cast(obj));
|
||||
} break;
|
||||
case ConstantPoolTag::kSymbol:
|
||||
obj = H.DartSymbolPlain(helper_->ReadStringReference()).raw();
|
||||
ASSERT(String::Cast(obj).IsSymbol());
|
||||
break;
|
||||
case ConstantPoolTag::kTypeArgumentsForInstanceAllocation: {
|
||||
cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
|
||||
obj =
|
||||
type_translator_
|
||||
.BuildInstantiatedTypeArguments(cls, helper_->ReadListLength())
|
||||
.raw();
|
||||
ASSERT(obj.IsNull() || obj.IsTypeArguments());
|
||||
} break;
|
||||
case ConstantPoolTag::kContextOffset: {
|
||||
intptr_t index = helper_->ReadUInt();
|
||||
if (index == 0) {
|
||||
obj = Smi::New(Context::parent_offset() / kWordSize);
|
||||
} else {
|
||||
obj = Smi::New(Context::variable_offset(index - 1) / kWordSize);
|
||||
}
|
||||
} break;
|
||||
case ConstantPoolTag::kClosureFunction: {
|
||||
name = H.DartSymbolPlain(helper_->ReadStringReference()).raw();
|
||||
const Function& closure = Function::Handle(
|
||||
helper_->zone_,
|
||||
Function::NewClosureFunction(name, inner_function,
|
||||
TokenPosition::kNoSource));
|
||||
|
||||
FunctionNodeHelper function_node_helper(helper_);
|
||||
function_node_helper.ReadUntilExcluding(
|
||||
FunctionNodeHelper::kTypeParameters);
|
||||
type_translator_.LoadAndSetupTypeParameters(
|
||||
active_class_, closure, helper_->ReadListLength(), closure);
|
||||
function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
|
||||
|
||||
// Scope remains opened until ConstantPoolTag::kEndClosureFunctionScope.
|
||||
ActiveTypeParametersScope scope(
|
||||
active_class_, &closure,
|
||||
TypeArguments::Handle(helper_->zone_, closure.type_parameters()),
|
||||
helper_->zone_);
|
||||
|
||||
function_node_helper.ReadUntilExcluding(
|
||||
FunctionNodeHelper::kPositionalParameters);
|
||||
|
||||
intptr_t required_parameter_count =
|
||||
function_node_helper.required_parameter_count_;
|
||||
intptr_t total_parameter_count =
|
||||
function_node_helper.total_parameter_count_;
|
||||
|
||||
intptr_t positional_parameter_count = helper_->ReadListLength();
|
||||
|
||||
intptr_t named_parameter_count =
|
||||
total_parameter_count - positional_parameter_count;
|
||||
|
||||
const intptr_t extra_parameters = 1;
|
||||
closure.set_num_fixed_parameters(extra_parameters +
|
||||
required_parameter_count);
|
||||
if (named_parameter_count > 0) {
|
||||
closure.SetNumOptionalParameters(named_parameter_count, false);
|
||||
} else {
|
||||
closure.SetNumOptionalParameters(
|
||||
positional_parameter_count - required_parameter_count, true);
|
||||
}
|
||||
intptr_t parameter_count = extra_parameters + total_parameter_count;
|
||||
closure.set_parameter_types(Array::Handle(
|
||||
helper_->zone_, Array::New(parameter_count, Heap::kOld)));
|
||||
closure.set_parameter_names(Array::Handle(
|
||||
helper_->zone_, Array::New(parameter_count, Heap::kOld)));
|
||||
|
||||
intptr_t pos = 0;
|
||||
closure.SetParameterTypeAt(pos, AbstractType::dynamic_type());
|
||||
closure.SetParameterNameAt(pos, Symbols::ClosureParameter());
|
||||
pos++;
|
||||
|
||||
const Library& lib =
|
||||
Library::Handle(helper_->zone_, active_class_->klass->library());
|
||||
for (intptr_t j = 0; j < positional_parameter_count; ++j, ++pos) {
|
||||
VariableDeclarationHelper helper(helper_);
|
||||
helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
|
||||
const AbstractType& type = type_translator_.BuildVariableType();
|
||||
Tag tag = helper_->ReadTag(); // read (first part of) initializer.
|
||||
if (tag == kSomething) {
|
||||
helper_->SkipExpression(); // read (actual) initializer.
|
||||
}
|
||||
|
||||
closure.SetParameterTypeAt(pos, type);
|
||||
closure.SetParameterNameAt(pos,
|
||||
H.DartIdentifier(lib, helper.name_index_));
|
||||
}
|
||||
|
||||
intptr_t named_parameter_count_check = helper_->ReadListLength();
|
||||
ASSERT(named_parameter_count_check == named_parameter_count);
|
||||
for (intptr_t j = 0; j < named_parameter_count; ++j, ++pos) {
|
||||
VariableDeclarationHelper helper(helper_);
|
||||
helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
|
||||
const AbstractType& type = type_translator_.BuildVariableType();
|
||||
Tag tag = helper_->ReadTag(); // read (first part of) initializer.
|
||||
if (tag == kSomething) {
|
||||
helper_->SkipExpression(); // read (actual) initializer.
|
||||
}
|
||||
|
||||
closure.SetParameterTypeAt(pos, type);
|
||||
closure.SetParameterNameAt(pos,
|
||||
H.DartIdentifier(lib, helper.name_index_));
|
||||
}
|
||||
|
||||
function_node_helper.SetJustRead(FunctionNodeHelper::kNamedParameters);
|
||||
|
||||
const AbstractType& return_type = type_translator_.BuildVariableType();
|
||||
closure.set_result_type(return_type);
|
||||
function_node_helper.SetJustRead(FunctionNodeHelper::kReturnType);
|
||||
// The closure has no body.
|
||||
function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
|
||||
|
||||
pool.SetTypeAt(i, ObjectPool::kTaggedObject);
|
||||
pool.SetObjectAt(i, closure);
|
||||
|
||||
// Continue reading the constant pool entries inside the opened
|
||||
// ActiveTypeParametersScope until the scope gets closed by a
|
||||
// kEndClosureFunctionScope tag, in which case control returns here.
|
||||
i = ReadPoolEntries(function, closure, pool, i + 1);
|
||||
// Pool entry at index i has been set to null, because it was a
|
||||
// kEndClosureFunctionScope.
|
||||
ASSERT(pool.ObjectAt(i) == Object::null());
|
||||
continue;
|
||||
}
|
||||
case ConstantPoolTag::kEndClosureFunctionScope: {
|
||||
// Entry is not used and set to null.
|
||||
obj = Object::null();
|
||||
pool.SetTypeAt(i, ObjectPool::kTaggedObject);
|
||||
pool.SetObjectAt(i, obj);
|
||||
return i; // The caller will close the scope.
|
||||
} break;
|
||||
case ConstantPoolTag::kNativeEntry: {
|
||||
name = H.DartString(helper_->ReadStringReference()).raw();
|
||||
obj = NativeEntry(function, name);
|
||||
} break;
|
||||
case ConstantPoolTag::kSubtypeTestCache: {
|
||||
obj = SubtypeTestCache::New();
|
||||
} break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
pool.SetTypeAt(i, ObjectPool::kTaggedObject);
|
||||
pool.SetObjectAt(i, obj);
|
||||
}
|
||||
// Return the index of the last read pool entry.
|
||||
return obj_count - 1;
|
||||
}
|
||||
|
||||
RawCode* BytecodeMetadataHelper::ReadBytecode(const ObjectPool& pool) {
|
||||
intptr_t size = helper_->reader_.ReadUInt();
|
||||
intptr_t offset = helper_->reader_.offset();
|
||||
const uint8_t* data = helper_->reader_.BufferAt(offset);
|
||||
helper_->reader_.set_offset(offset + size);
|
||||
|
||||
// Create and return code object.
|
||||
return Code::FinalizeBytecode(reinterpret_cast<const void*>(data), size,
|
||||
pool);
|
||||
}
|
||||
|
||||
void BytecodeMetadataHelper::ReadExceptionsTable(const Code& bytecode) {
|
||||
const intptr_t try_block_count = helper_->reader_.ReadListLength();
|
||||
if (try_block_count > 0) {
|
||||
const ObjectPool& pool =
|
||||
ObjectPool::Handle(helper_->zone_, bytecode.object_pool());
|
||||
AbstractType& handler_type = AbstractType::Handle(helper_->zone_);
|
||||
Array& handler_types = Array::ZoneHandle(helper_->zone_);
|
||||
DescriptorList* pc_descriptors_list =
|
||||
new (helper_->zone_) DescriptorList(64);
|
||||
ExceptionHandlerList* exception_handlers_list =
|
||||
new (helper_->zone_) ExceptionHandlerList();
|
||||
|
||||
// Encoding of ExceptionsTable is described in
|
||||
// pkg/vm/lib/bytecode/exceptions.dart.
|
||||
for (intptr_t try_index = 0; try_index < try_block_count; try_index++) {
|
||||
intptr_t outer_try_index_plus1 = helper_->reader_.ReadUInt();
|
||||
intptr_t outer_try_index = outer_try_index_plus1 - 1;
|
||||
intptr_t start_pc = helper_->reader_.ReadUInt();
|
||||
intptr_t end_pc = helper_->reader_.ReadUInt();
|
||||
intptr_t handler_pc = helper_->reader_.ReadUInt();
|
||||
uint8_t flags = helper_->reader_.ReadByte();
|
||||
const uint8_t kFlagNeedsStackTrace = 1 << 0;
|
||||
const uint8_t kFlagIsSynthetic = 1 << 1;
|
||||
const bool needs_stacktrace = (flags & kFlagNeedsStackTrace) != 0;
|
||||
const bool is_generated = (flags & kFlagIsSynthetic) != 0;
|
||||
intptr_t type_count = helper_->reader_.ReadListLength();
|
||||
ASSERT(type_count > 0);
|
||||
handler_types = Array::New(type_count, Heap::kOld);
|
||||
for (intptr_t i = 0; i < type_count; i++) {
|
||||
intptr_t type_index = helper_->reader_.ReadUInt();
|
||||
ASSERT(type_index < pool.Length());
|
||||
handler_type ^= pool.ObjectAt(type_index);
|
||||
handler_types.SetAt(i, handler_type);
|
||||
}
|
||||
pc_descriptors_list->AddDescriptor(RawPcDescriptors::kOther, start_pc,
|
||||
Thread::kNoDeoptId,
|
||||
TokenPosition::kNoSource, try_index);
|
||||
pc_descriptors_list->AddDescriptor(RawPcDescriptors::kOther, end_pc,
|
||||
Thread::kNoDeoptId,
|
||||
TokenPosition::kNoSource, -1);
|
||||
|
||||
exception_handlers_list->AddHandler(
|
||||
try_index, outer_try_index, handler_pc, TokenPosition::kNoSource,
|
||||
is_generated, handler_types, needs_stacktrace);
|
||||
}
|
||||
const PcDescriptors& descriptors = PcDescriptors::Handle(
|
||||
helper_->zone_,
|
||||
pc_descriptors_list->FinalizePcDescriptors(bytecode.PayloadStart()));
|
||||
bytecode.set_pc_descriptors(descriptors);
|
||||
const ExceptionHandlers& handlers = ExceptionHandlers::Handle(
|
||||
helper_->zone_, exception_handlers_list->FinalizeExceptionHandlers(
|
||||
bytecode.PayloadStart()));
|
||||
bytecode.set_exception_handlers(handlers);
|
||||
} else {
|
||||
bytecode.set_pc_descriptors(Object::empty_descriptors());
|
||||
bytecode.set_exception_handlers(Object::empty_exception_handlers());
|
||||
}
|
||||
}
|
||||
|
||||
RawTypedData* BytecodeMetadataHelper::NativeEntry(const Function& function,
|
||||
const String& external_name) {
|
||||
Zone* zone = helper_->zone_;
|
||||
MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
|
||||
// This list of recognized methods must be kept in sync with the list of
|
||||
// methods handled specially by the NativeCall bytecode in the interpreter.
|
||||
switch (kind) {
|
||||
case MethodRecognizer::kObjectEquals:
|
||||
case MethodRecognizer::kStringBaseLength:
|
||||
case MethodRecognizer::kStringBaseIsEmpty:
|
||||
case MethodRecognizer::kGrowableArrayLength:
|
||||
case MethodRecognizer::kObjectArrayLength:
|
||||
case MethodRecognizer::kImmutableArrayLength:
|
||||
case MethodRecognizer::kTypedDataLength:
|
||||
case MethodRecognizer::kClassIDgetID:
|
||||
case MethodRecognizer::kGrowableArrayCapacity:
|
||||
case MethodRecognizer::kListFactory:
|
||||
case MethodRecognizer::kObjectArrayAllocate:
|
||||
case MethodRecognizer::kLinkedHashMap_getIndex:
|
||||
case MethodRecognizer::kLinkedHashMap_setIndex:
|
||||
case MethodRecognizer::kLinkedHashMap_getData:
|
||||
case MethodRecognizer::kLinkedHashMap_setData:
|
||||
case MethodRecognizer::kLinkedHashMap_getHashMask:
|
||||
case MethodRecognizer::kLinkedHashMap_setHashMask:
|
||||
case MethodRecognizer::kLinkedHashMap_getUsedData:
|
||||
case MethodRecognizer::kLinkedHashMap_setUsedData:
|
||||
case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
|
||||
case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
|
||||
break;
|
||||
default:
|
||||
kind = MethodRecognizer::kUnknown;
|
||||
}
|
||||
NativeFunctionWrapper trampoline = NULL;
|
||||
NativeFunction native_function = NULL;
|
||||
intptr_t argc_tag = 0;
|
||||
if (kind == MethodRecognizer::kUnknown) {
|
||||
if (FLAG_link_natives_lazily) {
|
||||
trampoline = &NativeEntry::BootstrapNativeCallWrapper;
|
||||
native_function =
|
||||
reinterpret_cast<NativeFunction>(&NativeEntry::LinkNativeCall);
|
||||
} else {
|
||||
const Class& cls = Class::Handle(zone, function.Owner());
|
||||
const Library& library = Library::Handle(zone, cls.library());
|
||||
Dart_NativeEntryResolver resolver = library.native_entry_resolver();
|
||||
const bool is_bootstrap_native = Bootstrap::IsBootstrapResolver(resolver);
|
||||
const int num_params =
|
||||
NativeArguments::ParameterCountForResolution(function);
|
||||
bool is_auto_scope = true;
|
||||
native_function = NativeEntry::ResolveNative(library, external_name,
|
||||
num_params, &is_auto_scope);
|
||||
ASSERT(native_function != NULL); // TODO(regis): Should we throw instead?
|
||||
if (is_bootstrap_native) {
|
||||
trampoline = &NativeEntry::BootstrapNativeCallWrapper;
|
||||
} else if (is_auto_scope) {
|
||||
trampoline = &NativeEntry::AutoScopeNativeCallWrapper;
|
||||
} else {
|
||||
trampoline = &NativeEntry::NoScopeNativeCallWrapper;
|
||||
}
|
||||
}
|
||||
argc_tag = NativeArguments::ComputeArgcTag(function);
|
||||
}
|
||||
// TODO(regis): Introduce a new VM class subclassing Object and containing
|
||||
// these four untagged values.
|
||||
#ifdef ARCH_IS_32_BIT
|
||||
const TypedData& native_entry = TypedData::Handle(
|
||||
zone, TypedData::New(kTypedDataUint32ArrayCid, 4, Heap::kOld));
|
||||
native_entry.SetUint32(0 << 2, static_cast<uint32_t>(kind));
|
||||
native_entry.SetUint32(1 << 2, reinterpret_cast<uint32_t>(trampoline));
|
||||
native_entry.SetUint32(2 << 2, reinterpret_cast<uint32_t>(native_function));
|
||||
native_entry.SetUint32(3 << 2, static_cast<uint32_t>(argc_tag));
|
||||
#else
|
||||
const TypedData& native_entry = TypedData::Handle(
|
||||
zone, TypedData::New(kTypedDataUint64ArrayCid, 4, Heap::kOld));
|
||||
native_entry.SetUint64(0 << 3, static_cast<uint64_t>(kind));
|
||||
native_entry.SetUint64(1 << 3, reinterpret_cast<uint64_t>(trampoline));
|
||||
native_entry.SetUint64(2 << 3, reinterpret_cast<uint64_t>(native_function));
|
||||
native_entry.SetUint64(3 << 3, static_cast<uint64_t>(argc_tag));
|
||||
#endif
|
||||
return native_entry.raw();
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(DART_USE_INTERPRETER)
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
48
runtime/vm/compiler/frontend/bytecode_reader.h
Normal file
48
runtime/vm/compiler/frontend/bytecode_reader.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
|
||||
#define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
|
||||
|
||||
#include "vm/compiler/frontend/kernel_translation_helper.h"
|
||||
#include "vm/object.h"
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
#if defined(DART_USE_INTERPRETER)
|
||||
|
||||
namespace dart {
|
||||
namespace kernel {
|
||||
|
||||
// Helper class which provides access to bytecode metadata.
|
||||
class BytecodeMetadataHelper : public MetadataHelper {
|
||||
public:
|
||||
static const char* tag() { return "vm.bytecode"; }
|
||||
|
||||
explicit BytecodeMetadataHelper(KernelReaderHelper* helper,
|
||||
TypeTranslator* type_translator,
|
||||
ActiveClass* active_class);
|
||||
|
||||
void ReadMetadata(const Function& function);
|
||||
|
||||
private:
|
||||
// Returns the index of the last read pool entry.
|
||||
intptr_t ReadPoolEntries(const Function& function,
|
||||
const Function& inner_function,
|
||||
const ObjectPool& pool,
|
||||
intptr_t from_index);
|
||||
RawCode* ReadBytecode(const ObjectPool& pool);
|
||||
void ReadExceptionsTable(const Code& bytecode);
|
||||
RawTypedData* NativeEntry(const Function& function,
|
||||
const String& external_name);
|
||||
|
||||
TypeTranslator& type_translator_;
|
||||
ActiveClass* const active_class_;
|
||||
};
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(DART_USE_INTERPRETER)
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
#endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
|
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,7 @@
|
|||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
#include "vm/compiler/frontend/bytecode_reader.h"
|
||||
#include "vm/compiler/frontend/kernel_to_il.h"
|
||||
#include "vm/compiler/frontend/kernel_translation_helper.h"
|
||||
#include "vm/kernel.h"
|
||||
|
@ -16,184 +17,6 @@
|
|||
namespace dart {
|
||||
namespace kernel {
|
||||
|
||||
class TypeTranslator;
|
||||
|
||||
struct DirectCallMetadata {
|
||||
DirectCallMetadata(const Function& target, bool check_receiver_for_null)
|
||||
: target_(target), check_receiver_for_null_(check_receiver_for_null) {}
|
||||
|
||||
const Function& target_;
|
||||
const bool check_receiver_for_null_;
|
||||
};
|
||||
|
||||
// Helper class which provides access to direct call metadata.
|
||||
class DirectCallMetadataHelper : public MetadataHelper {
|
||||
public:
|
||||
static const char* tag() { return "vm.direct-call.metadata"; }
|
||||
|
||||
explicit DirectCallMetadataHelper(KernelReaderHelper* helper);
|
||||
|
||||
DirectCallMetadata GetDirectTargetForPropertyGet(intptr_t node_offset);
|
||||
DirectCallMetadata GetDirectTargetForPropertySet(intptr_t node_offset);
|
||||
DirectCallMetadata GetDirectTargetForMethodInvocation(intptr_t node_offset);
|
||||
|
||||
private:
|
||||
bool ReadMetadata(intptr_t node_offset,
|
||||
NameIndex* target_name,
|
||||
bool* check_receiver_for_null);
|
||||
};
|
||||
|
||||
struct InferredTypeMetadata {
|
||||
InferredTypeMetadata(intptr_t cid_, bool nullable_)
|
||||
: cid(cid_), nullable(nullable_) {}
|
||||
|
||||
const intptr_t cid;
|
||||
const bool nullable;
|
||||
|
||||
bool IsTrivial() const { return (cid == kDynamicCid) && nullable; }
|
||||
};
|
||||
|
||||
// Helper class which provides access to inferred type metadata.
|
||||
class InferredTypeMetadataHelper : public MetadataHelper {
|
||||
public:
|
||||
static const char* tag() { return "vm.inferred-type.metadata"; }
|
||||
|
||||
explicit InferredTypeMetadataHelper(KernelReaderHelper* helper);
|
||||
|
||||
InferredTypeMetadata GetInferredType(intptr_t node_offset);
|
||||
};
|
||||
|
||||
struct ProcedureAttributesMetadata {
|
||||
ProcedureAttributesMetadata(bool has_dynamic_invocations = true,
|
||||
bool has_non_this_uses = true,
|
||||
bool has_tearoff_uses = true)
|
||||
: has_dynamic_invocations(has_dynamic_invocations),
|
||||
has_non_this_uses(has_non_this_uses),
|
||||
has_tearoff_uses(has_tearoff_uses) {}
|
||||
bool has_dynamic_invocations;
|
||||
bool has_non_this_uses;
|
||||
bool has_tearoff_uses;
|
||||
};
|
||||
|
||||
// Helper class which provides access to direct call metadata.
|
||||
class ProcedureAttributesMetadataHelper : public MetadataHelper {
|
||||
public:
|
||||
static const char* tag() { return "vm.procedure-attributes.metadata"; }
|
||||
|
||||
explicit ProcedureAttributesMetadataHelper(KernelReaderHelper* helper);
|
||||
|
||||
ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset);
|
||||
|
||||
private:
|
||||
bool ReadMetadata(intptr_t node_offset,
|
||||
ProcedureAttributesMetadata* metadata);
|
||||
};
|
||||
|
||||
#if defined(DART_USE_INTERPRETER)
|
||||
|
||||
// Helper class which provides access to bytecode metadata.
|
||||
class BytecodeMetadataHelper : public MetadataHelper {
|
||||
public:
|
||||
static const char* tag() { return "vm.bytecode"; }
|
||||
|
||||
explicit BytecodeMetadataHelper(KernelReaderHelper* helper,
|
||||
TypeTranslator* type_translator,
|
||||
ActiveClass* active_class);
|
||||
|
||||
void ReadMetadata(const Function& function);
|
||||
|
||||
private:
|
||||
// Returns the index of the last read pool entry.
|
||||
intptr_t ReadPoolEntries(const Function& function,
|
||||
const Function& inner_function,
|
||||
const ObjectPool& pool,
|
||||
intptr_t from_index);
|
||||
RawCode* ReadBytecode(const ObjectPool& pool);
|
||||
void ReadExceptionsTable(const Code& bytecode);
|
||||
RawTypedData* NativeEntry(const Function& function,
|
||||
const String& external_name);
|
||||
|
||||
TypeTranslator& type_translator_;
|
||||
ActiveClass* const active_class_;
|
||||
};
|
||||
|
||||
#endif // defined(DART_USE_INTERPRETER)
|
||||
|
||||
class TypeTranslator {
|
||||
public:
|
||||
TypeTranslator(KernelReaderHelper* helper,
|
||||
ActiveClass* active_class,
|
||||
bool finalize = false);
|
||||
|
||||
// Can return a malformed type.
|
||||
AbstractType& BuildType();
|
||||
// Can return a malformed type.
|
||||
AbstractType& BuildTypeWithoutFinalization();
|
||||
// Is guaranteed to be not malformed.
|
||||
AbstractType& BuildVariableType();
|
||||
|
||||
// Will return `TypeArguments::null()` in case any of the arguments are
|
||||
// malformed.
|
||||
const TypeArguments& BuildTypeArguments(intptr_t length);
|
||||
|
||||
// Will return `TypeArguments::null()` in case any of the arguments are
|
||||
// malformed.
|
||||
const TypeArguments& BuildInstantiatedTypeArguments(
|
||||
const Class& receiver_class,
|
||||
intptr_t length);
|
||||
|
||||
void LoadAndSetupTypeParameters(ActiveClass* active_class,
|
||||
const Object& set_on,
|
||||
intptr_t type_parameter_count,
|
||||
const Function& parameterized_function);
|
||||
|
||||
const Type& ReceiverType(const Class& klass);
|
||||
|
||||
private:
|
||||
// Can build a malformed type.
|
||||
void BuildTypeInternal(bool invalid_as_dynamic = false);
|
||||
void BuildInterfaceType(bool simple);
|
||||
void BuildFunctionType(bool simple);
|
||||
void BuildTypeParameterType();
|
||||
|
||||
class TypeParameterScope {
|
||||
public:
|
||||
TypeParameterScope(TypeTranslator* translator, intptr_t parameter_count)
|
||||
: parameter_count_(parameter_count),
|
||||
outer_(translator->type_parameter_scope_),
|
||||
translator_(translator) {
|
||||
outer_parameter_count_ = 0;
|
||||
if (outer_ != NULL) {
|
||||
outer_parameter_count_ =
|
||||
outer_->outer_parameter_count_ + outer_->parameter_count_;
|
||||
}
|
||||
translator_->type_parameter_scope_ = this;
|
||||
}
|
||||
~TypeParameterScope() { translator_->type_parameter_scope_ = outer_; }
|
||||
|
||||
TypeParameterScope* outer() const { return outer_; }
|
||||
intptr_t parameter_count() const { return parameter_count_; }
|
||||
intptr_t outer_parameter_count() const { return outer_parameter_count_; }
|
||||
|
||||
private:
|
||||
intptr_t parameter_count_;
|
||||
intptr_t outer_parameter_count_;
|
||||
TypeParameterScope* outer_;
|
||||
TypeTranslator* translator_;
|
||||
};
|
||||
|
||||
KernelReaderHelper* helper_;
|
||||
TranslationHelper& translation_helper_;
|
||||
ActiveClass* const active_class_;
|
||||
TypeParameterScope* type_parameter_scope_;
|
||||
Zone* zone_;
|
||||
AbstractType& result_;
|
||||
bool finalize_;
|
||||
|
||||
friend class StreamingScopeBuilder;
|
||||
friend class KernelLoader;
|
||||
};
|
||||
|
||||
class StreamingScopeBuilder {
|
||||
public:
|
||||
explicit StreamingScopeBuilder(ParsedFunction* parsed_function);
|
||||
|
@ -919,24 +742,6 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
|
|||
friend class StreamingScopeBuilder;
|
||||
};
|
||||
|
||||
class AlternativeScriptScope {
|
||||
public:
|
||||
AlternativeScriptScope(TranslationHelper* helper,
|
||||
const Script& new_script,
|
||||
const Script& old_script)
|
||||
: helper_(helper), old_script_(old_script) {
|
||||
helper_->Reset();
|
||||
helper_->InitFromScript(new_script);
|
||||
}
|
||||
~AlternativeScriptScope() {
|
||||
helper_->Reset();
|
||||
helper_->InitFromScript(old_script_);
|
||||
}
|
||||
|
||||
TranslationHelper* helper_;
|
||||
const Script& old_script_;
|
||||
};
|
||||
|
||||
// Helper class that reads a kernel Constant from binary.
|
||||
class ConstantHelper {
|
||||
public:
|
||||
|
|
|
@ -28,67 +28,6 @@ namespace kernel {
|
|||
#define T (type_translator_)
|
||||
#define I Isolate::Current()
|
||||
|
||||
ActiveTypeParametersScope::ActiveTypeParametersScope(ActiveClass* active_class,
|
||||
const Function& innermost,
|
||||
Zone* Z)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
active_class_->enclosing = &innermost;
|
||||
|
||||
intptr_t num_params = 0;
|
||||
|
||||
Function& f = Function::Handle(Z);
|
||||
TypeArguments& f_params = TypeArguments::Handle(Z);
|
||||
for (f = innermost.raw(); f.parent_function() != Object::null();
|
||||
f = f.parent_function()) {
|
||||
f_params = f.type_parameters();
|
||||
num_params += f_params.Length();
|
||||
}
|
||||
if (num_params == 0) return;
|
||||
|
||||
TypeArguments& params =
|
||||
TypeArguments::Handle(Z, TypeArguments::New(num_params));
|
||||
|
||||
intptr_t index = num_params;
|
||||
for (f = innermost.raw(); f.parent_function() != Object::null();
|
||||
f = f.parent_function()) {
|
||||
f_params = f.type_parameters();
|
||||
for (intptr_t j = f_params.Length() - 1; j >= 0; --j) {
|
||||
params.SetTypeAt(--index, AbstractType::Handle(Z, f_params.TypeAt(j)));
|
||||
}
|
||||
}
|
||||
|
||||
active_class_->local_type_parameters = ¶ms;
|
||||
}
|
||||
|
||||
ActiveTypeParametersScope::ActiveTypeParametersScope(
|
||||
ActiveClass* active_class,
|
||||
const Function* function,
|
||||
const TypeArguments& new_params,
|
||||
Zone* Z)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
active_class_->enclosing = function;
|
||||
|
||||
if (new_params.IsNull()) return;
|
||||
|
||||
const TypeArguments* old_params = active_class->local_type_parameters;
|
||||
const intptr_t old_param_count =
|
||||
old_params == NULL ? 0 : old_params->Length();
|
||||
const TypeArguments& extended_params = TypeArguments::Handle(
|
||||
Z, TypeArguments::New(old_param_count + new_params.Length()));
|
||||
|
||||
intptr_t index = 0;
|
||||
for (intptr_t i = 0; i < old_param_count; ++i) {
|
||||
extended_params.SetTypeAt(
|
||||
index++, AbstractType::ZoneHandle(Z, old_params->TypeAt(i)));
|
||||
}
|
||||
for (intptr_t i = 0; i < new_params.Length(); ++i) {
|
||||
extended_params.SetTypeAt(
|
||||
index++, AbstractType::ZoneHandle(Z, new_params.TypeAt(i)));
|
||||
}
|
||||
|
||||
active_class_->local_type_parameters = &extended_params;
|
||||
}
|
||||
|
||||
Fragment& Fragment::operator+=(const Fragment& other) {
|
||||
if (entry == NULL) {
|
||||
entry = other.entry;
|
||||
|
@ -136,25 +75,6 @@ Fragment operator<<(const Fragment& fragment, Instruction* next) {
|
|||
return result;
|
||||
}
|
||||
|
||||
intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) {
|
||||
ASSERT(member != NULL);
|
||||
if (member->IsFactory()) {
|
||||
TypeArguments& class_types =
|
||||
TypeArguments::Handle(zone, klass->type_parameters());
|
||||
return class_types.Length();
|
||||
} else if (member->IsMethodExtractor()) {
|
||||
Function& extracted =
|
||||
Function::Handle(zone, member->extracted_method_closure());
|
||||
TypeArguments& function_types =
|
||||
TypeArguments::Handle(zone, extracted.type_parameters());
|
||||
return function_types.Length();
|
||||
} else {
|
||||
TypeArguments& function_types =
|
||||
TypeArguments::Handle(zone, member->type_parameters());
|
||||
return function_types.Length();
|
||||
}
|
||||
}
|
||||
|
||||
FlowGraphBuilder::FlowGraphBuilder(
|
||||
intptr_t kernel_offset,
|
||||
ParsedFunction* parsed_function,
|
||||
|
|
|
@ -201,110 +201,6 @@ Fragment operator<<(const Fragment& fragment, Instruction* next);
|
|||
|
||||
typedef ZoneGrowableArray<PushArgumentInstr*>* ArgumentArray;
|
||||
|
||||
class ActiveClass {
|
||||
public:
|
||||
ActiveClass()
|
||||
: klass(NULL),
|
||||
member(NULL),
|
||||
enclosing(NULL),
|
||||
local_type_parameters(NULL) {}
|
||||
|
||||
bool HasMember() { return member != NULL; }
|
||||
|
||||
bool MemberIsProcedure() {
|
||||
ASSERT(member != NULL);
|
||||
RawFunction::Kind function_kind = member->kind();
|
||||
return function_kind == RawFunction::kRegularFunction ||
|
||||
function_kind == RawFunction::kGetterFunction ||
|
||||
function_kind == RawFunction::kSetterFunction ||
|
||||
function_kind == RawFunction::kMethodExtractor ||
|
||||
function_kind == RawFunction::kDynamicInvocationForwarder ||
|
||||
member->IsFactory();
|
||||
}
|
||||
|
||||
bool MemberIsFactoryProcedure() {
|
||||
ASSERT(member != NULL);
|
||||
return member->IsFactory();
|
||||
}
|
||||
|
||||
intptr_t MemberTypeParameterCount(Zone* zone);
|
||||
|
||||
intptr_t ClassNumTypeArguments() {
|
||||
ASSERT(klass != NULL);
|
||||
return klass->NumTypeArguments();
|
||||
}
|
||||
|
||||
const char* ToCString() {
|
||||
return member != NULL ? member->ToCString() : klass->ToCString();
|
||||
}
|
||||
|
||||
// The current enclosing class (or the library top-level class).
|
||||
const Class* klass;
|
||||
|
||||
const Function* member;
|
||||
|
||||
// The innermost enclosing function. This is used for building types, as a
|
||||
// parent for function types.
|
||||
const Function* enclosing;
|
||||
|
||||
const TypeArguments* local_type_parameters;
|
||||
};
|
||||
|
||||
class ActiveClassScope {
|
||||
public:
|
||||
ActiveClassScope(ActiveClass* active_class, const Class* klass)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
active_class_->klass = klass;
|
||||
}
|
||||
|
||||
~ActiveClassScope() { *active_class_ = saved_; }
|
||||
|
||||
private:
|
||||
ActiveClass* active_class_;
|
||||
ActiveClass saved_;
|
||||
};
|
||||
|
||||
class ActiveMemberScope {
|
||||
public:
|
||||
ActiveMemberScope(ActiveClass* active_class, const Function* member)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
// The class is inherited.
|
||||
active_class_->member = member;
|
||||
}
|
||||
|
||||
~ActiveMemberScope() { *active_class_ = saved_; }
|
||||
|
||||
private:
|
||||
ActiveClass* active_class_;
|
||||
ActiveClass saved_;
|
||||
};
|
||||
|
||||
class ActiveTypeParametersScope {
|
||||
public:
|
||||
// Set the local type parameters of the ActiveClass to be exactly all type
|
||||
// parameters defined by 'innermost' and any enclosing *closures* (but not
|
||||
// enclosing methods/top-level functions/classes).
|
||||
//
|
||||
// Also, the enclosing function is set to 'innermost'.
|
||||
ActiveTypeParametersScope(ActiveClass* active_class,
|
||||
const Function& innermost,
|
||||
Zone* Z);
|
||||
|
||||
// Append the list of the local type parameters to the list in ActiveClass.
|
||||
//
|
||||
// Also, the enclosing function is set to 'function'.
|
||||
ActiveTypeParametersScope(ActiveClass* active_class,
|
||||
const Function* function,
|
||||
const TypeArguments& new_params,
|
||||
Zone* Z);
|
||||
|
||||
~ActiveTypeParametersScope() { *active_class_ = saved_; }
|
||||
|
||||
private:
|
||||
ActiveClass* active_class_;
|
||||
ActiveClass saved_;
|
||||
};
|
||||
|
||||
struct FunctionScope {
|
||||
intptr_t kernel_offset;
|
||||
LocalScope* scope;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "vm/class_finalizer.h"
|
||||
#include "vm/compiler/aot/precompiler.h"
|
||||
#include "vm/log.h"
|
||||
#include "vm/object_store.h"
|
||||
#include "vm/symbols.h"
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
@ -1499,6 +1500,153 @@ intptr_t MetadataHelper::GetNextMetadataPayloadOffset(intptr_t node_offset) {
|
|||
}
|
||||
}
|
||||
|
||||
DirectCallMetadataHelper::DirectCallMetadataHelper(KernelReaderHelper* helper)
|
||||
: MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
|
||||
|
||||
bool DirectCallMetadataHelper::ReadMetadata(intptr_t node_offset,
|
||||
NameIndex* target_name,
|
||||
bool* check_receiver_for_null) {
|
||||
intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
|
||||
if (md_offset < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
|
||||
md_offset);
|
||||
|
||||
*target_name = helper_->ReadCanonicalNameReference();
|
||||
*check_receiver_for_null = helper_->ReadBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertyGet(
|
||||
intptr_t node_offset) {
|
||||
NameIndex kernel_name;
|
||||
bool check_receiver_for_null = false;
|
||||
if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
|
||||
return DirectCallMetadata(Function::null_function(), false);
|
||||
}
|
||||
|
||||
if (H.IsProcedure(kernel_name) && !H.IsGetter(kernel_name)) {
|
||||
// Tear-off. Use method extractor as direct call target.
|
||||
const String& method_name = H.DartMethodName(kernel_name);
|
||||
const Function& target_method = Function::ZoneHandle(
|
||||
helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
|
||||
const String& getter_name = H.DartGetterName(kernel_name);
|
||||
return DirectCallMetadata(
|
||||
Function::ZoneHandle(helper_->zone_,
|
||||
target_method.GetMethodExtractor(getter_name)),
|
||||
check_receiver_for_null);
|
||||
} else {
|
||||
const String& getter_name = H.DartGetterName(kernel_name);
|
||||
const Function& target = Function::ZoneHandle(
|
||||
helper_->zone_, H.LookupMethodByMember(kernel_name, getter_name));
|
||||
ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
|
||||
return DirectCallMetadata(target, check_receiver_for_null);
|
||||
}
|
||||
}
|
||||
|
||||
DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertySet(
|
||||
intptr_t node_offset) {
|
||||
NameIndex kernel_name;
|
||||
bool check_receiver_for_null = false;
|
||||
if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
|
||||
return DirectCallMetadata(Function::null_function(), false);
|
||||
}
|
||||
|
||||
const String& method_name = H.DartSetterName(kernel_name);
|
||||
const Function& target = Function::ZoneHandle(
|
||||
helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
|
||||
ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction());
|
||||
|
||||
return DirectCallMetadata(target, check_receiver_for_null);
|
||||
}
|
||||
|
||||
DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForMethodInvocation(
|
||||
intptr_t node_offset) {
|
||||
NameIndex kernel_name;
|
||||
bool check_receiver_for_null = false;
|
||||
if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
|
||||
return DirectCallMetadata(Function::null_function(), false);
|
||||
}
|
||||
|
||||
const String& method_name = H.DartProcedureName(kernel_name);
|
||||
const Function& target = Function::ZoneHandle(
|
||||
helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
|
||||
|
||||
return DirectCallMetadata(target, check_receiver_for_null);
|
||||
}
|
||||
|
||||
InferredTypeMetadataHelper::InferredTypeMetadataHelper(
|
||||
KernelReaderHelper* helper)
|
||||
: MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
|
||||
|
||||
InferredTypeMetadata InferredTypeMetadataHelper::GetInferredType(
|
||||
intptr_t node_offset) {
|
||||
const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
|
||||
if (md_offset < 0) {
|
||||
return InferredTypeMetadata(kDynamicCid, true);
|
||||
}
|
||||
|
||||
AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
|
||||
md_offset);
|
||||
|
||||
const NameIndex kernel_name = helper_->ReadCanonicalNameReference();
|
||||
const bool nullable = helper_->ReadBool();
|
||||
|
||||
if (H.IsRoot(kernel_name)) {
|
||||
return InferredTypeMetadata(kDynamicCid, nullable);
|
||||
}
|
||||
|
||||
const Class& klass =
|
||||
Class::Handle(helper_->zone_, H.LookupClassByKernelClass(kernel_name));
|
||||
ASSERT(!klass.IsNull());
|
||||
|
||||
intptr_t cid = klass.id();
|
||||
if (cid == kClosureCid) {
|
||||
// VM uses more specific function types and doesn't expect instances of
|
||||
// _Closure class, so inferred _Closure class doesn't make sense for the VM.
|
||||
cid = kDynamicCid;
|
||||
}
|
||||
|
||||
return InferredTypeMetadata(cid, nullable);
|
||||
}
|
||||
|
||||
ProcedureAttributesMetadataHelper::ProcedureAttributesMetadataHelper(
|
||||
KernelReaderHelper* helper)
|
||||
: MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
|
||||
|
||||
bool ProcedureAttributesMetadataHelper::ReadMetadata(
|
||||
intptr_t node_offset,
|
||||
ProcedureAttributesMetadata* metadata) {
|
||||
intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
|
||||
if (md_offset < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
|
||||
md_offset);
|
||||
|
||||
const int kDynamicUsesBit = 1 << 0;
|
||||
const int kNonThisUsesBit = 1 << 1;
|
||||
const int kTearOffUsesBit = 1 << 2;
|
||||
|
||||
const uint8_t flags = helper_->ReadByte();
|
||||
metadata->has_dynamic_invocations =
|
||||
(flags & kDynamicUsesBit) == kDynamicUsesBit;
|
||||
metadata->has_non_this_uses = (flags & kNonThisUsesBit) == kNonThisUsesBit;
|
||||
metadata->has_tearoff_uses = (flags & kTearOffUsesBit) == kTearOffUsesBit;
|
||||
return true;
|
||||
}
|
||||
|
||||
ProcedureAttributesMetadata
|
||||
ProcedureAttributesMetadataHelper::GetProcedureAttributes(
|
||||
intptr_t node_offset) {
|
||||
ProcedureAttributesMetadata metadata;
|
||||
ReadMetadata(node_offset, &metadata);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
intptr_t KernelReaderHelper::ReaderOffset() const {
|
||||
return reader_.offset();
|
||||
}
|
||||
|
@ -2199,6 +2347,536 @@ TokenPosition KernelReaderHelper::ReadPosition(bool record) {
|
|||
return position;
|
||||
}
|
||||
|
||||
intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) {
|
||||
ASSERT(member != NULL);
|
||||
if (member->IsFactory()) {
|
||||
TypeArguments& class_types =
|
||||
TypeArguments::Handle(zone, klass->type_parameters());
|
||||
return class_types.Length();
|
||||
} else if (member->IsMethodExtractor()) {
|
||||
Function& extracted =
|
||||
Function::Handle(zone, member->extracted_method_closure());
|
||||
TypeArguments& function_types =
|
||||
TypeArguments::Handle(zone, extracted.type_parameters());
|
||||
return function_types.Length();
|
||||
} else {
|
||||
TypeArguments& function_types =
|
||||
TypeArguments::Handle(zone, member->type_parameters());
|
||||
return function_types.Length();
|
||||
}
|
||||
}
|
||||
|
||||
ActiveTypeParametersScope::ActiveTypeParametersScope(ActiveClass* active_class,
|
||||
const Function& innermost,
|
||||
Zone* Z)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
active_class_->enclosing = &innermost;
|
||||
|
||||
intptr_t num_params = 0;
|
||||
|
||||
Function& f = Function::Handle(Z);
|
||||
TypeArguments& f_params = TypeArguments::Handle(Z);
|
||||
for (f = innermost.raw(); f.parent_function() != Object::null();
|
||||
f = f.parent_function()) {
|
||||
f_params = f.type_parameters();
|
||||
num_params += f_params.Length();
|
||||
}
|
||||
if (num_params == 0) return;
|
||||
|
||||
TypeArguments& params =
|
||||
TypeArguments::Handle(Z, TypeArguments::New(num_params));
|
||||
|
||||
intptr_t index = num_params;
|
||||
for (f = innermost.raw(); f.parent_function() != Object::null();
|
||||
f = f.parent_function()) {
|
||||
f_params = f.type_parameters();
|
||||
for (intptr_t j = f_params.Length() - 1; j >= 0; --j) {
|
||||
params.SetTypeAt(--index, AbstractType::Handle(Z, f_params.TypeAt(j)));
|
||||
}
|
||||
}
|
||||
|
||||
active_class_->local_type_parameters = ¶ms;
|
||||
}
|
||||
|
||||
ActiveTypeParametersScope::ActiveTypeParametersScope(
|
||||
ActiveClass* active_class,
|
||||
const Function* function,
|
||||
const TypeArguments& new_params,
|
||||
Zone* Z)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
active_class_->enclosing = function;
|
||||
|
||||
if (new_params.IsNull()) return;
|
||||
|
||||
const TypeArguments* old_params = active_class->local_type_parameters;
|
||||
const intptr_t old_param_count =
|
||||
old_params == NULL ? 0 : old_params->Length();
|
||||
const TypeArguments& extended_params = TypeArguments::Handle(
|
||||
Z, TypeArguments::New(old_param_count + new_params.Length()));
|
||||
|
||||
intptr_t index = 0;
|
||||
for (intptr_t i = 0; i < old_param_count; ++i) {
|
||||
extended_params.SetTypeAt(
|
||||
index++, AbstractType::ZoneHandle(Z, old_params->TypeAt(i)));
|
||||
}
|
||||
for (intptr_t i = 0; i < new_params.Length(); ++i) {
|
||||
extended_params.SetTypeAt(
|
||||
index++, AbstractType::ZoneHandle(Z, new_params.TypeAt(i)));
|
||||
}
|
||||
|
||||
active_class_->local_type_parameters = &extended_params;
|
||||
}
|
||||
|
||||
TypeTranslator::TypeTranslator(KernelReaderHelper* helper,
|
||||
ActiveClass* active_class,
|
||||
bool finalize)
|
||||
: helper_(helper),
|
||||
translation_helper_(helper->translation_helper_),
|
||||
active_class_(active_class),
|
||||
type_parameter_scope_(NULL),
|
||||
zone_(translation_helper_.zone()),
|
||||
result_(AbstractType::Handle(translation_helper_.zone())),
|
||||
finalize_(finalize) {}
|
||||
|
||||
AbstractType& TypeTranslator::BuildType() {
|
||||
BuildTypeInternal();
|
||||
|
||||
// We return a new `ZoneHandle` here on purpose: The intermediate language
|
||||
// instructions do not make a copy of the handle, so we do it.
|
||||
return AbstractType::ZoneHandle(Z, result_.raw());
|
||||
}
|
||||
|
||||
AbstractType& TypeTranslator::BuildTypeWithoutFinalization() {
|
||||
bool saved_finalize = finalize_;
|
||||
finalize_ = false;
|
||||
BuildTypeInternal();
|
||||
finalize_ = saved_finalize;
|
||||
|
||||
// We return a new `ZoneHandle` here on purpose: The intermediate language
|
||||
// instructions do not make a copy of the handle, so we do it.
|
||||
return AbstractType::ZoneHandle(Z, result_.raw());
|
||||
}
|
||||
|
||||
AbstractType& TypeTranslator::BuildVariableType() {
|
||||
AbstractType& abstract_type = BuildType();
|
||||
|
||||
// We return a new `ZoneHandle` here on purpose: The intermediate language
|
||||
// instructions do not make a copy of the handle, so we do it.
|
||||
AbstractType& type = Type::ZoneHandle(Z);
|
||||
|
||||
if (abstract_type.IsMalformed()) {
|
||||
type = AbstractType::dynamic_type().raw();
|
||||
} else {
|
||||
type = result_.raw();
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
void TypeTranslator::BuildTypeInternal(bool invalid_as_dynamic) {
|
||||
Tag tag = helper_->ReadTag();
|
||||
switch (tag) {
|
||||
case kInvalidType:
|
||||
if (invalid_as_dynamic) {
|
||||
result_ = Object::dynamic_type().raw();
|
||||
} else {
|
||||
result_ = ClassFinalizer::NewFinalizedMalformedType(
|
||||
Error::Handle(Z), // No previous error.
|
||||
Script::Handle(Z, Script::null()), TokenPosition::kNoSource,
|
||||
"[InvalidType] in Kernel IR.");
|
||||
}
|
||||
break;
|
||||
case kDynamicType:
|
||||
result_ = Object::dynamic_type().raw();
|
||||
break;
|
||||
case kVoidType:
|
||||
result_ = Object::void_type().raw();
|
||||
break;
|
||||
case kBottomType:
|
||||
result_ =
|
||||
Class::Handle(Z, I->object_store()->null_class()).CanonicalType();
|
||||
break;
|
||||
case kInterfaceType:
|
||||
BuildInterfaceType(false);
|
||||
break;
|
||||
case kSimpleInterfaceType:
|
||||
BuildInterfaceType(true);
|
||||
break;
|
||||
case kFunctionType:
|
||||
BuildFunctionType(false);
|
||||
break;
|
||||
case kSimpleFunctionType:
|
||||
BuildFunctionType(true);
|
||||
break;
|
||||
case kTypeParameterType:
|
||||
BuildTypeParameterType();
|
||||
break;
|
||||
default:
|
||||
helper_->ReportUnexpectedTag("type", tag);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void TypeTranslator::BuildInterfaceType(bool simple) {
|
||||
// NOTE: That an interface type like `T<A, B>` is considered to be
|
||||
// malformed iff `T` is malformed.
|
||||
// => We therefore ignore errors in `A` or `B`.
|
||||
|
||||
NameIndex klass_name =
|
||||
helper_->ReadCanonicalNameReference(); // read klass_name.
|
||||
|
||||
intptr_t length;
|
||||
if (simple) {
|
||||
length = 0;
|
||||
} else {
|
||||
length = helper_->ReadListLength(); // read type_arguments list length.
|
||||
}
|
||||
const TypeArguments& type_arguments =
|
||||
BuildTypeArguments(length); // read type arguments.
|
||||
|
||||
Object& klass = Object::Handle(Z, H.LookupClassByKernelClass(klass_name));
|
||||
result_ = Type::New(klass, type_arguments, TokenPosition::kNoSource);
|
||||
if (finalize_) {
|
||||
ASSERT(active_class_->klass != NULL);
|
||||
result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeTranslator::BuildFunctionType(bool simple) {
|
||||
Function& signature_function = Function::ZoneHandle(
|
||||
Z, Function::NewSignatureFunction(*active_class_->klass,
|
||||
active_class_->enclosing != NULL
|
||||
? *active_class_->enclosing
|
||||
: Function::Handle(Z),
|
||||
TokenPosition::kNoSource));
|
||||
|
||||
// Suspend finalization of types inside this one. They will be finalized after
|
||||
// the whole function type is constructed.
|
||||
//
|
||||
// TODO(31213): Test further when nested generic function types
|
||||
// are supported by fasta.
|
||||
bool finalize = finalize_;
|
||||
finalize_ = false;
|
||||
|
||||
if (!simple) {
|
||||
LoadAndSetupTypeParameters(active_class_, signature_function,
|
||||
helper_->ReadListLength(), signature_function);
|
||||
}
|
||||
|
||||
ActiveTypeParametersScope scope(
|
||||
active_class_, &signature_function,
|
||||
TypeArguments::Handle(Z, signature_function.type_parameters()), Z);
|
||||
|
||||
intptr_t required_count;
|
||||
intptr_t all_count;
|
||||
intptr_t positional_count;
|
||||
if (!simple) {
|
||||
required_count = helper_->ReadUInt(); // read required parameter count.
|
||||
all_count = helper_->ReadUInt(); // read total parameter count.
|
||||
positional_count =
|
||||
helper_->ReadListLength(); // read positional_parameters list length.
|
||||
} else {
|
||||
positional_count =
|
||||
helper_->ReadListLength(); // read positional_parameters list length.
|
||||
required_count = positional_count;
|
||||
all_count = positional_count;
|
||||
}
|
||||
|
||||
const Array& parameter_types =
|
||||
Array::Handle(Z, Array::New(1 + all_count, Heap::kOld));
|
||||
signature_function.set_parameter_types(parameter_types);
|
||||
const Array& parameter_names =
|
||||
Array::Handle(Z, Array::New(1 + all_count, Heap::kOld));
|
||||
signature_function.set_parameter_names(parameter_names);
|
||||
|
||||
intptr_t pos = 0;
|
||||
parameter_types.SetAt(pos, AbstractType::dynamic_type());
|
||||
parameter_names.SetAt(pos, H.DartSymbolPlain("_receiver_"));
|
||||
++pos;
|
||||
for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
|
||||
BuildTypeInternal(); // read ith positional parameter.
|
||||
if (result_.IsMalformed()) {
|
||||
result_ = AbstractType::dynamic_type().raw();
|
||||
}
|
||||
parameter_types.SetAt(pos, result_);
|
||||
parameter_names.SetAt(pos, H.DartSymbolPlain("noname"));
|
||||
}
|
||||
|
||||
// The additional first parameter is the receiver type (set to dynamic).
|
||||
signature_function.set_num_fixed_parameters(1 + required_count);
|
||||
signature_function.SetNumOptionalParameters(
|
||||
all_count - required_count, positional_count > required_count);
|
||||
|
||||
if (!simple) {
|
||||
const intptr_t named_count =
|
||||
helper_->ReadListLength(); // read named_parameters list length.
|
||||
for (intptr_t i = 0; i < named_count; ++i, ++pos) {
|
||||
// read string reference (i.e. named_parameters[i].name).
|
||||
String& name = H.DartSymbolObfuscate(helper_->ReadStringReference());
|
||||
BuildTypeInternal(); // read named_parameters[i].type.
|
||||
if (result_.IsMalformed()) {
|
||||
result_ = AbstractType::dynamic_type().raw();
|
||||
}
|
||||
parameter_types.SetAt(pos, result_);
|
||||
parameter_names.SetAt(pos, name);
|
||||
}
|
||||
}
|
||||
|
||||
helper_->SkipListOfStrings(); // read positional parameter names.
|
||||
|
||||
if (!simple) {
|
||||
helper_->SkipCanonicalNameReference(); // read typedef reference.
|
||||
}
|
||||
|
||||
BuildTypeInternal(); // read return type.
|
||||
if (result_.IsMalformed()) {
|
||||
result_ = AbstractType::dynamic_type().raw();
|
||||
}
|
||||
signature_function.set_result_type(result_);
|
||||
|
||||
finalize_ = finalize;
|
||||
|
||||
Type& signature_type =
|
||||
Type::ZoneHandle(Z, signature_function.SignatureType());
|
||||
|
||||
if (finalize_) {
|
||||
signature_type ^=
|
||||
ClassFinalizer::FinalizeType(*active_class_->klass, signature_type);
|
||||
// Do not refer to signature_function anymore, since it may have been
|
||||
// replaced during canonicalization.
|
||||
signature_function = Function::null();
|
||||
}
|
||||
|
||||
result_ = signature_type.raw();
|
||||
}
|
||||
|
||||
void TypeTranslator::BuildTypeParameterType() {
|
||||
intptr_t parameter_index = helper_->ReadUInt(); // read parameter index.
|
||||
helper_->SkipOptionalDartType(); // read bound.
|
||||
|
||||
const TypeArguments& class_types =
|
||||
TypeArguments::Handle(Z, active_class_->klass->type_parameters());
|
||||
if (parameter_index < class_types.Length()) {
|
||||
// The index of the type parameter in [parameters] is
|
||||
// the same index into the `klass->type_parameters()` array.
|
||||
result_ ^= class_types.TypeAt(parameter_index);
|
||||
return;
|
||||
}
|
||||
parameter_index -= class_types.Length();
|
||||
|
||||
if (active_class_->HasMember()) {
|
||||
if (active_class_->MemberIsFactoryProcedure()) {
|
||||
//
|
||||
// WARNING: This is a little hackish:
|
||||
//
|
||||
// We have a static factory constructor. The kernel IR gives the factory
|
||||
// constructor function its own type parameters (which are equal in name
|
||||
// and number to the ones of the enclosing class). I.e.,
|
||||
//
|
||||
// class A<T> {
|
||||
// factory A.x() { return new B<T>(); }
|
||||
// }
|
||||
//
|
||||
// is basically translated to this:
|
||||
//
|
||||
// class A<T> {
|
||||
// static A.x<T'>() { return new B<T'>(); }
|
||||
// }
|
||||
//
|
||||
if (class_types.Length() > parameter_index) {
|
||||
result_ ^= class_types.TypeAt(parameter_index);
|
||||
return;
|
||||
}
|
||||
parameter_index -= class_types.Length();
|
||||
}
|
||||
|
||||
intptr_t procedure_type_parameter_count =
|
||||
active_class_->MemberIsProcedure()
|
||||
? active_class_->MemberTypeParameterCount(Z)
|
||||
: 0;
|
||||
if (procedure_type_parameter_count > 0) {
|
||||
if (procedure_type_parameter_count > parameter_index) {
|
||||
if (I->reify_generic_functions()) {
|
||||
result_ ^=
|
||||
TypeArguments::Handle(Z, active_class_->member->type_parameters())
|
||||
.TypeAt(parameter_index);
|
||||
} else {
|
||||
result_ ^= Type::DynamicType();
|
||||
}
|
||||
return;
|
||||
}
|
||||
parameter_index -= procedure_type_parameter_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (active_class_->local_type_parameters != NULL) {
|
||||
if (parameter_index < active_class_->local_type_parameters->Length()) {
|
||||
if (I->reify_generic_functions()) {
|
||||
result_ ^=
|
||||
active_class_->local_type_parameters->TypeAt(parameter_index);
|
||||
} else {
|
||||
result_ ^= Type::DynamicType();
|
||||
}
|
||||
return;
|
||||
}
|
||||
parameter_index -= active_class_->local_type_parameters->Length();
|
||||
}
|
||||
|
||||
if (type_parameter_scope_ != NULL &&
|
||||
parameter_index < type_parameter_scope_->outer_parameter_count() +
|
||||
type_parameter_scope_->parameter_count()) {
|
||||
result_ ^= Type::DynamicType();
|
||||
return;
|
||||
}
|
||||
|
||||
H.ReportError(
|
||||
helper_->script(), TokenPosition::kNoSource,
|
||||
"Unbound type parameter found in %s. Please report this at dartbug.com.",
|
||||
active_class_->ToCString());
|
||||
}
|
||||
|
||||
const TypeArguments& TypeTranslator::BuildTypeArguments(intptr_t length) {
|
||||
bool only_dynamic = true;
|
||||
intptr_t offset = helper_->ReaderOffset();
|
||||
for (intptr_t i = 0; i < length; ++i) {
|
||||
if (helper_->ReadTag() != kDynamicType) { // Read the ith types tag.
|
||||
only_dynamic = false;
|
||||
helper_->SetOffset(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
TypeArguments& type_arguments = TypeArguments::ZoneHandle(Z);
|
||||
if (!only_dynamic) {
|
||||
type_arguments = TypeArguments::New(length);
|
||||
for (intptr_t i = 0; i < length; ++i) {
|
||||
BuildTypeInternal(true); // read ith type.
|
||||
type_arguments.SetTypeAt(i, result_);
|
||||
}
|
||||
|
||||
if (finalize_) {
|
||||
type_arguments = type_arguments.Canonicalize();
|
||||
}
|
||||
}
|
||||
return type_arguments;
|
||||
}
|
||||
|
||||
const TypeArguments& TypeTranslator::BuildInstantiatedTypeArguments(
|
||||
const Class& receiver_class,
|
||||
intptr_t length) {
|
||||
const TypeArguments& type_arguments = BuildTypeArguments(length);
|
||||
|
||||
// If type_arguments is null all arguments are dynamic.
|
||||
// If, however, this class doesn't specify all the type arguments directly we
|
||||
// still need to finalize the type below in order to get any non-dynamic types
|
||||
// from any super. See http://www.dartbug.com/29537.
|
||||
if (type_arguments.IsNull() && receiver_class.NumTypeArguments() == length) {
|
||||
return type_arguments;
|
||||
}
|
||||
|
||||
// We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to
|
||||
// finalize the argument types.
|
||||
// (This can for example make the [type_arguments] vector larger)
|
||||
Type& type = Type::Handle(
|
||||
Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource));
|
||||
if (finalize_) {
|
||||
type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type);
|
||||
}
|
||||
|
||||
const TypeArguments& instantiated_type_arguments =
|
||||
TypeArguments::ZoneHandle(Z, type.arguments());
|
||||
return instantiated_type_arguments;
|
||||
}
|
||||
|
||||
void TypeTranslator::LoadAndSetupTypeParameters(
|
||||
ActiveClass* active_class,
|
||||
const Object& set_on,
|
||||
intptr_t type_parameter_count,
|
||||
const Function& parameterized_function) {
|
||||
ASSERT(type_parameter_count >= 0);
|
||||
if (type_parameter_count == 0) {
|
||||
return;
|
||||
}
|
||||
ASSERT(set_on.IsClass() || set_on.IsFunction());
|
||||
bool set_on_class = set_on.IsClass();
|
||||
ASSERT(set_on_class == parameterized_function.IsNull());
|
||||
|
||||
// First setup the type parameters, so if any of the following code uses it
|
||||
// (in a recursive way) we're fine.
|
||||
TypeArguments& type_parameters = TypeArguments::Handle(Z);
|
||||
TypeParameter& parameter = TypeParameter::Handle(Z);
|
||||
const Type& null_bound = Type::Handle(Z);
|
||||
|
||||
// Step a) Create array of [TypeParameter] objects (without bound).
|
||||
type_parameters = TypeArguments::New(type_parameter_count);
|
||||
const Library& lib = Library::Handle(Z, active_class->klass->library());
|
||||
{
|
||||
AlternativeReadingScope alt(&helper_->reader_);
|
||||
for (intptr_t i = 0; i < type_parameter_count; i++) {
|
||||
TypeParameterHelper helper(helper_);
|
||||
helper.Finish();
|
||||
parameter = TypeParameter::New(
|
||||
set_on_class ? *active_class->klass : Class::Handle(Z),
|
||||
parameterized_function, i,
|
||||
H.DartIdentifier(lib, helper.name_index_), // read ith name index.
|
||||
null_bound, TokenPosition::kNoSource);
|
||||
type_parameters.SetTypeAt(i, parameter);
|
||||
}
|
||||
}
|
||||
|
||||
if (set_on.IsClass()) {
|
||||
Class::Cast(set_on).set_type_parameters(type_parameters);
|
||||
} else {
|
||||
Function::Cast(set_on).set_type_parameters(type_parameters);
|
||||
}
|
||||
|
||||
const Function* enclosing = NULL;
|
||||
if (!parameterized_function.IsNull()) {
|
||||
enclosing = ¶meterized_function;
|
||||
}
|
||||
ActiveTypeParametersScope scope(active_class, enclosing, type_parameters, Z);
|
||||
|
||||
// Step b) Fill in the bounds of all [TypeParameter]s.
|
||||
for (intptr_t i = 0; i < type_parameter_count; i++) {
|
||||
TypeParameterHelper helper(helper_);
|
||||
helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
|
||||
|
||||
// TODO(github.com/dart-lang/kernel/issues/42): This should be handled
|
||||
// by the frontend.
|
||||
parameter ^= type_parameters.TypeAt(i);
|
||||
const Tag tag = helper_->PeekTag(); // peek ith bound type.
|
||||
if (tag == kDynamicType) {
|
||||
helper_->SkipDartType(); // read ith bound.
|
||||
parameter.set_bound(Type::Handle(Z, I->object_store()->object_type()));
|
||||
} else {
|
||||
AbstractType& bound = BuildTypeWithoutFinalization(); // read ith bound.
|
||||
if (bound.IsMalformedOrMalbounded()) {
|
||||
bound = I->object_store()->object_type();
|
||||
}
|
||||
parameter.set_bound(bound);
|
||||
}
|
||||
|
||||
helper.Finish();
|
||||
}
|
||||
}
|
||||
|
||||
const Type& TypeTranslator::ReceiverType(const Class& klass) {
|
||||
ASSERT(!klass.IsNull());
|
||||
ASSERT(!klass.IsTypedefClass());
|
||||
// Note that if klass is _Closure, the returned type will be _Closure,
|
||||
// and not the signature type.
|
||||
Type& type = Type::ZoneHandle(Z, klass.CanonicalType());
|
||||
if (!type.IsNull()) {
|
||||
return type;
|
||||
}
|
||||
type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
|
||||
klass.token_pos());
|
||||
if (klass.is_type_finalized()) {
|
||||
type ^= ClassFinalizer::FinalizeType(klass, type);
|
||||
klass.SetCanonicalType(type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace dart
|
||||
|
||||
|
|
|
@ -778,6 +778,77 @@ class MetadataHelper {
|
|||
intptr_t last_mapping_index_;
|
||||
};
|
||||
|
||||
struct DirectCallMetadata {
|
||||
DirectCallMetadata(const Function& target, bool check_receiver_for_null)
|
||||
: target_(target), check_receiver_for_null_(check_receiver_for_null) {}
|
||||
|
||||
const Function& target_;
|
||||
const bool check_receiver_for_null_;
|
||||
};
|
||||
|
||||
// Helper class which provides access to direct call metadata.
|
||||
class DirectCallMetadataHelper : public MetadataHelper {
|
||||
public:
|
||||
static const char* tag() { return "vm.direct-call.metadata"; }
|
||||
|
||||
explicit DirectCallMetadataHelper(KernelReaderHelper* helper);
|
||||
|
||||
DirectCallMetadata GetDirectTargetForPropertyGet(intptr_t node_offset);
|
||||
DirectCallMetadata GetDirectTargetForPropertySet(intptr_t node_offset);
|
||||
DirectCallMetadata GetDirectTargetForMethodInvocation(intptr_t node_offset);
|
||||
|
||||
private:
|
||||
bool ReadMetadata(intptr_t node_offset,
|
||||
NameIndex* target_name,
|
||||
bool* check_receiver_for_null);
|
||||
};
|
||||
|
||||
struct InferredTypeMetadata {
|
||||
InferredTypeMetadata(intptr_t cid_, bool nullable_)
|
||||
: cid(cid_), nullable(nullable_) {}
|
||||
|
||||
const intptr_t cid;
|
||||
const bool nullable;
|
||||
|
||||
bool IsTrivial() const { return (cid == kDynamicCid) && nullable; }
|
||||
};
|
||||
|
||||
// Helper class which provides access to inferred type metadata.
|
||||
class InferredTypeMetadataHelper : public MetadataHelper {
|
||||
public:
|
||||
static const char* tag() { return "vm.inferred-type.metadata"; }
|
||||
|
||||
explicit InferredTypeMetadataHelper(KernelReaderHelper* helper);
|
||||
|
||||
InferredTypeMetadata GetInferredType(intptr_t node_offset);
|
||||
};
|
||||
|
||||
struct ProcedureAttributesMetadata {
|
||||
ProcedureAttributesMetadata(bool has_dynamic_invocations = true,
|
||||
bool has_non_this_uses = true,
|
||||
bool has_tearoff_uses = true)
|
||||
: has_dynamic_invocations(has_dynamic_invocations),
|
||||
has_non_this_uses(has_non_this_uses),
|
||||
has_tearoff_uses(has_tearoff_uses) {}
|
||||
bool has_dynamic_invocations;
|
||||
bool has_non_this_uses;
|
||||
bool has_tearoff_uses;
|
||||
};
|
||||
|
||||
// Helper class which provides access to direct call metadata.
|
||||
class ProcedureAttributesMetadataHelper : public MetadataHelper {
|
||||
public:
|
||||
static const char* tag() { return "vm.procedure-attributes.metadata"; }
|
||||
|
||||
explicit ProcedureAttributesMetadataHelper(KernelReaderHelper* helper);
|
||||
|
||||
ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset);
|
||||
|
||||
private:
|
||||
bool ReadMetadata(intptr_t node_offset,
|
||||
ProcedureAttributesMetadata* metadata);
|
||||
};
|
||||
|
||||
class KernelReaderHelper {
|
||||
public:
|
||||
KernelReaderHelper(Zone* zone,
|
||||
|
@ -910,6 +981,185 @@ class KernelReaderHelper {
|
|||
#endif // defined(DART_USE_INTERPRETER)
|
||||
};
|
||||
|
||||
class ActiveClass {
|
||||
public:
|
||||
ActiveClass()
|
||||
: klass(NULL),
|
||||
member(NULL),
|
||||
enclosing(NULL),
|
||||
local_type_parameters(NULL) {}
|
||||
|
||||
bool HasMember() { return member != NULL; }
|
||||
|
||||
bool MemberIsProcedure() {
|
||||
ASSERT(member != NULL);
|
||||
RawFunction::Kind function_kind = member->kind();
|
||||
return function_kind == RawFunction::kRegularFunction ||
|
||||
function_kind == RawFunction::kGetterFunction ||
|
||||
function_kind == RawFunction::kSetterFunction ||
|
||||
function_kind == RawFunction::kMethodExtractor ||
|
||||
function_kind == RawFunction::kDynamicInvocationForwarder ||
|
||||
member->IsFactory();
|
||||
}
|
||||
|
||||
bool MemberIsFactoryProcedure() {
|
||||
ASSERT(member != NULL);
|
||||
return member->IsFactory();
|
||||
}
|
||||
|
||||
intptr_t MemberTypeParameterCount(Zone* zone);
|
||||
|
||||
intptr_t ClassNumTypeArguments() {
|
||||
ASSERT(klass != NULL);
|
||||
return klass->NumTypeArguments();
|
||||
}
|
||||
|
||||
const char* ToCString() {
|
||||
return member != NULL ? member->ToCString() : klass->ToCString();
|
||||
}
|
||||
|
||||
// The current enclosing class (or the library top-level class).
|
||||
const Class* klass;
|
||||
|
||||
const Function* member;
|
||||
|
||||
// The innermost enclosing function. This is used for building types, as a
|
||||
// parent for function types.
|
||||
const Function* enclosing;
|
||||
|
||||
const TypeArguments* local_type_parameters;
|
||||
};
|
||||
|
||||
class ActiveClassScope {
|
||||
public:
|
||||
ActiveClassScope(ActiveClass* active_class, const Class* klass)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
active_class_->klass = klass;
|
||||
}
|
||||
|
||||
~ActiveClassScope() { *active_class_ = saved_; }
|
||||
|
||||
private:
|
||||
ActiveClass* active_class_;
|
||||
ActiveClass saved_;
|
||||
};
|
||||
|
||||
class ActiveMemberScope {
|
||||
public:
|
||||
ActiveMemberScope(ActiveClass* active_class, const Function* member)
|
||||
: active_class_(active_class), saved_(*active_class) {
|
||||
// The class is inherited.
|
||||
active_class_->member = member;
|
||||
}
|
||||
|
||||
~ActiveMemberScope() { *active_class_ = saved_; }
|
||||
|
||||
private:
|
||||
ActiveClass* active_class_;
|
||||
ActiveClass saved_;
|
||||
};
|
||||
|
||||
class ActiveTypeParametersScope {
|
||||
public:
|
||||
// Set the local type parameters of the ActiveClass to be exactly all type
|
||||
// parameters defined by 'innermost' and any enclosing *closures* (but not
|
||||
// enclosing methods/top-level functions/classes).
|
||||
//
|
||||
// Also, the enclosing function is set to 'innermost'.
|
||||
ActiveTypeParametersScope(ActiveClass* active_class,
|
||||
const Function& innermost,
|
||||
Zone* Z);
|
||||
|
||||
// Append the list of the local type parameters to the list in ActiveClass.
|
||||
//
|
||||
// Also, the enclosing function is set to 'function'.
|
||||
ActiveTypeParametersScope(ActiveClass* active_class,
|
||||
const Function* function,
|
||||
const TypeArguments& new_params,
|
||||
Zone* Z);
|
||||
|
||||
~ActiveTypeParametersScope() { *active_class_ = saved_; }
|
||||
|
||||
private:
|
||||
ActiveClass* active_class_;
|
||||
ActiveClass saved_;
|
||||
};
|
||||
|
||||
class TypeTranslator {
|
||||
public:
|
||||
TypeTranslator(KernelReaderHelper* helper,
|
||||
ActiveClass* active_class,
|
||||
bool finalize = false);
|
||||
|
||||
// Can return a malformed type.
|
||||
AbstractType& BuildType();
|
||||
// Can return a malformed type.
|
||||
AbstractType& BuildTypeWithoutFinalization();
|
||||
// Is guaranteed to be not malformed.
|
||||
AbstractType& BuildVariableType();
|
||||
|
||||
// Will return `TypeArguments::null()` in case any of the arguments are
|
||||
// malformed.
|
||||
const TypeArguments& BuildTypeArguments(intptr_t length);
|
||||
|
||||
// Will return `TypeArguments::null()` in case any of the arguments are
|
||||
// malformed.
|
||||
const TypeArguments& BuildInstantiatedTypeArguments(
|
||||
const Class& receiver_class,
|
||||
intptr_t length);
|
||||
|
||||
void LoadAndSetupTypeParameters(ActiveClass* active_class,
|
||||
const Object& set_on,
|
||||
intptr_t type_parameter_count,
|
||||
const Function& parameterized_function);
|
||||
|
||||
const Type& ReceiverType(const Class& klass);
|
||||
|
||||
private:
|
||||
// Can build a malformed type.
|
||||
void BuildTypeInternal(bool invalid_as_dynamic = false);
|
||||
void BuildInterfaceType(bool simple);
|
||||
void BuildFunctionType(bool simple);
|
||||
void BuildTypeParameterType();
|
||||
|
||||
class TypeParameterScope {
|
||||
public:
|
||||
TypeParameterScope(TypeTranslator* translator, intptr_t parameter_count)
|
||||
: parameter_count_(parameter_count),
|
||||
outer_(translator->type_parameter_scope_),
|
||||
translator_(translator) {
|
||||
outer_parameter_count_ = 0;
|
||||
if (outer_ != NULL) {
|
||||
outer_parameter_count_ =
|
||||
outer_->outer_parameter_count_ + outer_->parameter_count_;
|
||||
}
|
||||
translator_->type_parameter_scope_ = this;
|
||||
}
|
||||
~TypeParameterScope() { translator_->type_parameter_scope_ = outer_; }
|
||||
|
||||
TypeParameterScope* outer() const { return outer_; }
|
||||
intptr_t parameter_count() const { return parameter_count_; }
|
||||
intptr_t outer_parameter_count() const { return outer_parameter_count_; }
|
||||
|
||||
private:
|
||||
intptr_t parameter_count_;
|
||||
intptr_t outer_parameter_count_;
|
||||
TypeParameterScope* outer_;
|
||||
TypeTranslator* translator_;
|
||||
};
|
||||
|
||||
KernelReaderHelper* helper_;
|
||||
TranslationHelper& translation_helper_;
|
||||
ActiveClass* const active_class_;
|
||||
TypeParameterScope* type_parameter_scope_;
|
||||
Zone* zone_;
|
||||
AbstractType& result_;
|
||||
bool finalize_;
|
||||
|
||||
friend class StreamingScopeBuilder;
|
||||
friend class KernelLoader;
|
||||
};
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace dart
|
||||
|
||||
|
|
|
@ -13540,7 +13540,7 @@ void ICData::set_ic_data_array(const Array& value) const {
|
|||
}
|
||||
|
||||
#if defined(TAG_IC_DATA)
|
||||
void ICData::set_tag(intptr_t value) const {
|
||||
void ICData::set_tag(Tag value) const {
|
||||
StoreNonPointer(&raw_ptr()->tag_, value);
|
||||
}
|
||||
#endif
|
||||
|
@ -14427,7 +14427,7 @@ RawICData* ICData::NewDescriptor(Zone* zone,
|
|||
NOT_IN_PRECOMPILED(result.set_deopt_id(deopt_id));
|
||||
result.set_state_bits(0);
|
||||
#if defined(TAG_IC_DATA)
|
||||
result.set_tag(-1);
|
||||
result.set_tag(ICData::Tag::kUnknown);
|
||||
#endif
|
||||
result.set_rebind_rule(rebind_rule);
|
||||
result.SetNumArgsTested(num_args_tested);
|
||||
|
@ -14451,7 +14451,7 @@ RawICData* ICData::New() {
|
|||
result.set_deopt_id(Thread::kNoDeoptId);
|
||||
result.set_state_bits(0);
|
||||
#if defined(TAG_IC_DATA)
|
||||
result.set_tag(-1);
|
||||
result.set_tag(ICData::Tag::kUnknown);
|
||||
#endif
|
||||
return result.raw();
|
||||
}
|
||||
|
|
|
@ -2004,8 +2004,9 @@ class ICData : public Object {
|
|||
enum { kCachedICDataArrayCount = 4 };
|
||||
|
||||
#if defined(TAG_IC_DATA)
|
||||
void set_tag(intptr_t value) const;
|
||||
intptr_t tag() const { return raw_ptr()->tag_; }
|
||||
using Tag = RawICData::Tag;
|
||||
void set_tag(Tag value) const;
|
||||
Tag tag() const { return raw_ptr()->tag_; }
|
||||
#endif
|
||||
|
||||
bool is_static_call() const;
|
||||
|
|
|
@ -1663,8 +1663,10 @@ class RawICData : public RawObject {
|
|||
NOT_IN_PRECOMPILED(int32_t deopt_id_);
|
||||
uint32_t state_bits_; // Number of arguments tested in IC, deopt reasons.
|
||||
#if defined(TAG_IC_DATA)
|
||||
intptr_t tag_; // Debugging, verifying that the icdata is assigned to the
|
||||
// same instruction again. Store -1 or Instruction::Tag.
|
||||
enum class Tag : intptr_t{kUnknown, kInstanceCall, kStaticCall};
|
||||
|
||||
Tag tag_; // Debugging, verifying that the icdata is assigned to the
|
||||
// same instruction again.
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -1639,7 +1639,7 @@ RawICData* ICData::ReadFrom(SnapshotReader* reader,
|
|||
NOT_IN_PRECOMPILED(result.set_deopt_id(reader->Read<int32_t>()));
|
||||
result.set_state_bits(reader->Read<uint32_t>());
|
||||
#if defined(TAG_IC_DATA)
|
||||
result.set_tag(reader->Read<int16_t>());
|
||||
result.set_tag(static_cast<ICData::Tag>(reader->Read<int16_t>()));
|
||||
#endif
|
||||
|
||||
// Set all the object fields.
|
||||
|
@ -1666,7 +1666,7 @@ void RawICData::WriteTo(SnapshotWriter* writer,
|
|||
NOT_IN_PRECOMPILED(writer->Write<int32_t>(ptr()->deopt_id_));
|
||||
writer->Write<uint32_t>(ptr()->state_bits_);
|
||||
#if defined(TAG_IC_DATA)
|
||||
writer->Write<int16_t>(ptr()->tag_);
|
||||
writer->Write<int16_t>(static_cast<int64_t>(ptr()->tag_));
|
||||
#endif
|
||||
|
||||
// Write out all the object pointer fields.
|
||||
|
|
Loading…
Reference in a new issue