Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(549)

Unified Diff: runtime/vm/kernel_binary_flowgraph.cc

Issue 2941483003: Revert "[kernel] Stream everything. Replace .kernel_function with .kernel_offset" (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/kernel_binary_flowgraph.h ('k') | runtime/vm/kernel_reader.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/kernel_binary_flowgraph.cc
diff --git a/runtime/vm/kernel_binary_flowgraph.cc b/runtime/vm/kernel_binary_flowgraph.cc
index adcfcec719e3b803ee48ddef5a1239653079e14e..c88ddce65eb74777894c05761bfd4fd69d1c7b92 100644
--- a/runtime/vm/kernel_binary_flowgraph.cc
+++ b/runtime/vm/kernel_binary_flowgraph.cc
@@ -4,7 +4,6 @@
#include "vm/kernel_binary_flowgraph.h"
-#include "vm/compiler.h"
#include "vm/longjump.h"
#include "vm/object_store.h"
@@ -55,6 +54,27 @@ StreamingScopeBuilder::~StreamingScopeBuilder() {
delete builder_;
}
+void StreamingScopeBuilder::DiscoverEnclosingElements(
+ Zone* zone,
+ const Function& function,
+ Function* outermost_function,
+ intptr_t* outermost_kernel_offset,
+ intptr_t* parent_class_offset) {
+ // Find out if there is an enclosing kernel class (which will be used to
+ // resolve type parameters).
+ *outermost_function = function.raw();
+ while (outermost_function->parent_function() != Object::null()) {
+ *outermost_function = outermost_function->parent_function();
+ }
+
+ if (outermost_function->kernel_function() != NULL) {
+ *outermost_kernel_offset =
+ static_cast<TreeNode*>(outermost_function->kernel_function())
+ ->kernel_offset();
+ *parent_class_offset = GetParentOffset(*outermost_kernel_offset);
+ }
+}
+
ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
if (result_ != NULL) return result_;
@@ -71,18 +91,16 @@ ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
Function& outermost_function = Function::Handle(Z);
intptr_t outermost_kernel_offset = -1;
intptr_t parent_class_offset = -1;
- builder_->DiscoverEnclosingElements(Z, function, &outermost_function,
- &outermost_kernel_offset,
- &parent_class_offset);
+ DiscoverEnclosingElements(Z, function, &outermost_function,
+ &outermost_kernel_offset, &parent_class_offset);
// Use [klass]/[kernel_class] as active class. Type parameters will get
// resolved via [kernel_class] unless we are nested inside a static factory
// in which case we will use [member].
intptr_t class_type_parameters = 0;
intptr_t class_type_parameters_offset_start = -1;
if (parent_class_offset > 0) {
- builder_->GetTypeParameterInfoForClass(parent_class_offset,
- &class_type_parameters,
- &class_type_parameters_offset_start);
+ GetTypeParameterInfoForClass(parent_class_offset, &class_type_parameters,
+ &class_type_parameters_offset_start);
}
ActiveClassScope active_class_scope(&active_class_, class_type_parameters,
class_type_parameters_offset_start,
@@ -92,7 +110,7 @@ ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
bool is_factory_procedure = false;
intptr_t member_type_parameters = 0;
intptr_t member_type_parameters_offset_start = -1;
- builder_->GetTypeParameterInfoForPossibleProcedure(
+ GetTypeParameterInfoForPossibleProcedure(
outermost_kernel_offset, &member_is_procedure, &is_factory_procedure,
&member_type_parameters, &member_type_parameters_offset_start);
@@ -126,10 +144,27 @@ ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
case RawFunction::kSetterFunction:
case RawFunction::kConstructor: {
const Tag tag = builder_->PeekTag();
- parent_offset = builder_->ReadUntilFunctionNode();
+ if (tag == kProcedure) {
+ Tag has_function_node = ReadProcedureUntilFunctionNode(
+ &unused_word, &unused_intptr); // read first part of procedure.
+ if (has_function_node == kNothing) {
+ // Running a procedure without a function node doesn't make sense.
+ UNREACHABLE();
+ }
+ // Now at start of FunctionNode.
+ } else if (tag == kConstructor) {
+ // read first part of constructor.
+ parent_offset = ReadConstructorUntilFunctionNode();
+ // Now at start of FunctionNode.
+ // Notice that we also have a list of initializers after that!
+ } else if (tag == kFunctionNode) {
+ // Already at start of FunctionNode.
+ } else {
+ UNREACHABLE();
+ }
word async_marker_word;
- builder_->ReadFunctionNodeUntilTypeParameters(
- &unused_tokenposition, &unused_tokenposition, &async_marker_word,
+ ReadFunctionNodeUntilTypeParameters(
+ &async_marker_word,
&unused_word); // read first part of function node.
current_function_async_marker_ =
static_cast<FunctionNode::AsyncMarker>(async_marker_word);
@@ -158,7 +193,7 @@ ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
if (tag == kConstructor) {
ASSERT(parent_offset >= 0);
AlternativeReadingScope alt(builder_->reader_, parent_offset);
- builder_->ReadClassUntilFields(); // read first part of class.
+ ReadClassUntilFields(); // read first part of class.
intptr_t list_length =
builder_->ReadListLength(); // read fields list length.
for (intptr_t i = 0; i < list_length; i++) {
@@ -166,14 +201,12 @@ ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
TokenPosition position;
TokenPosition end_position;
word flags;
- builder_->ReadFieldUntilAnnotation(&unused_nameindex, &position,
- &end_position, &flags,
- &unused_intptr);
+ ReadFieldUntilAnnotation(&position, &end_position, &flags,
+ &unused_intptr);
bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
builder_->SkipListOfExpressions(); // read annotations.
builder_->SkipDartType(); // read type.
- Tag initializer_tag =
- builder_->ReadTag(); // read first part of initializer.
+ Tag initializer_tag = builder_->ReadTag();
if (!is_static && initializer_tag == kSomething) {
EnterScope(field_offset);
VisitExpression(); // read initializer.
@@ -193,7 +226,6 @@ ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
// Continue reading FunctionNode.
builder_->SkipTypeParametersList(); // read type_parameters.
- builder_->ReadUInt(); // read total parameter count.
builder_->ReadUInt(); // read required_parameter_count.
AddPositionalAndNamedParameters(
pos); // read positional_parameters and named_parameters.
@@ -287,6 +319,40 @@ ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
return result_;
}
+intptr_t StreamingScopeBuilder::GetParentOffset(intptr_t offset) {
+ AlternativeReadingScope alt(builder_->reader_, offset);
+
+ Tag tag = builder_->PeekTag();
+ intptr_t parent_offset = -1;
+ switch (tag) {
+ case kConstructor:
+ return ReadConstructorUntilFunctionNode();
+ case kProcedure:
+ ReadProcedureUntilFunctionNode(
+ &unused_word, &parent_offset); // read first part of procedure.
+ return parent_offset;
+ case kField:
+ ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition,
+ &unused_word, &parent_offset);
+ return parent_offset;
+ default:
+ UNIMPLEMENTED();
+ return -1;
+ }
+}
+
+void StreamingScopeBuilder::GetTypeParameterInfoForClass(
+ intptr_t class_offset,
+ intptr_t* type_paremeter_counts,
+ intptr_t* type_paremeter_offset) {
+ AlternativeReadingScope alt(builder_->reader_, class_offset);
+
+ ReadClassUntilTypeParameters();
+ *type_paremeter_counts =
+ builder_->ReadListLength(); // read type_parameters list length.
+ *type_paremeter_offset = builder_->ReaderOffset();
+}
+
void StreamingScopeBuilder::VisitNode() {
Tag tag = builder_->PeekTag();
switch (tag) {
@@ -308,25 +374,37 @@ void StreamingScopeBuilder::VisitNode() {
}
}
+intptr_t StreamingScopeBuilder::ReadConstructorUntilFunctionNode() {
+ Tag tag = builder_->ReadTag();
+ ASSERT(tag == kConstructor);
+ builder_->SkipCanonicalNameReference(); // read canonical name reference.
+ builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read end position.
+ builder_->ReadFlags(); // read flags.
+ intptr_t parent_offset = builder_->ReadUInt(); // parent class binary offset.
+ builder_->SkipName(); // read name.
+ builder_->SkipListOfExpressions(); // read annotations.
+ return parent_offset;
+}
+
void StreamingScopeBuilder::VisitConstructor() {
// Field initializers that come from non-static field declarations are
// compiled as if they appear in the constructor initializer list. This is
// important for closure-valued field initializers because the VM expects the
// corresponding closure functions to appear as if they were nested inside the
// constructor.
- intptr_t parent_offset = builder_->ReadConstructorUntilFunctionNode();
+ intptr_t parent_offset = ReadConstructorUntilFunctionNode();
ASSERT(parent_offset >= 0);
{
AlternativeReadingScope alt(builder_->reader_, parent_offset);
- builder_->ReadClassUntilFields(); // read first part of class.
+ ReadClassUntilFields(); // read first part of class.
intptr_t list_length =
builder_->ReadListLength(); // read fields list length.
for (intptr_t i = 0; i < list_length; i++) {
word flags;
- builder_->ReadFieldUntilAnnotation(
- &unused_nameindex, &unused_tokenposition, &unused_tokenposition,
- &flags, &unused_intptr);
+ ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition,
+ &flags, &unused_intptr);
bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
builder_->SkipListOfExpressions(); // read annotations.
builder_->SkipDartType(); // read type.
@@ -349,17 +427,34 @@ void StreamingScopeBuilder::VisitConstructor() {
}
void StreamingScopeBuilder::VisitProcedure() {
- Tag function_node = builder_->ReadProcedureUntilFunctionNode(
+ Tag function_node = ReadProcedureUntilFunctionNode(
&unused_word, &unused_intptr); // read first part of procedure.
if (function_node == kSomething) {
VisitFunctionNode();
}
}
+void StreamingScopeBuilder::ReadFieldUntilAnnotation(
+ TokenPosition* position,
+ TokenPosition* end_position,
+ word* flags,
+ intptr_t* parent_offset) {
+ Tag tag = builder_->ReadTag();
+ ASSERT(tag == kField);
+
+ builder_->SkipCanonicalNameReference(); // read canonical_name.
+ *position = builder_->ReadPosition(); // read position.
+ *end_position = builder_->ReadPosition(); // read end position.
+ *flags = builder_->ReadFlags(); // read flags.
+ *parent_offset = builder_->ReadUInt(); // read parent class binary offset.
+ builder_->SkipName(); // read name.
+ builder_->ReadUInt(); // source_uri_index.
+}
+
void StreamingScopeBuilder::VisitField() {
- builder_->ReadFieldUntilAnnotation(
- &unused_nameindex, &unused_tokenposition, &unused_tokenposition,
- &unused_intptr, &unused_word); // read first part of field.
+ ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition,
+ &unused_intptr,
+ &unused_word); // read first part of field.
builder_->SkipListOfExpressions(); // read annotations.
VisitDartType(); // read type.
Tag tag = builder_->ReadTag(); // read initializer (part 1).
@@ -368,12 +463,98 @@ void StreamingScopeBuilder::VisitField() {
}
}
+Tag StreamingScopeBuilder::ReadProcedureUntilFunctionNode(
+ word* kind,
+ intptr_t* parent_offset) {
+ Tag tag = builder_->ReadTag(); // read tag.
+ ASSERT(tag == kProcedure);
+ builder_->SkipCanonicalNameReference(); // read canonical name reference.
+ builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read end position.
+ *kind = builder_->ReadByte(); // read kind.
+ builder_->ReadFlags(); // read flags.
+ *parent_offset = builder_->ReadUInt(); // read parent class binary offset.
+ builder_->SkipName(); // read name,
+ builder_->ReadUInt(); // read source_uri_index.
+ builder_->SkipListOfExpressions(); // read annotations.
+ return builder_->ReadTag(); // read tag for optional function node.
+}
+
+void StreamingScopeBuilder::GetTypeParameterInfoForPossibleProcedure(
+ intptr_t outermost_kernel_offset,
+ bool* member_is_procedure,
+ bool* is_factory_procedure,
+ intptr_t* member_type_parameters,
+ intptr_t* member_type_parameters_offset_start) {
+ if (outermost_kernel_offset >= 0) {
+ AlternativeReadingScope alt(builder_->reader_, outermost_kernel_offset);
+ Tag tag = builder_->PeekTag();
+ if (tag == kProcedure) {
+ *member_is_procedure = true;
+
+ word kind;
+ tag = ReadProcedureUntilFunctionNode(
+ &kind, &unused_intptr); // read first part of procedure.
+ *is_factory_procedure =
+ static_cast<Procedure::ProcedureKind>(kind) == Procedure::kFactory;
+
+ if (tag == kSomething) {
+ ReadFunctionNodeUntilTypeParameters(
+ &unused_word, &unused_word); // read first part of function node.
+
+ intptr_t list_length =
+ builder_->ReadListLength(); // read type_parameters list length.
+ if (list_length > 0) {
+ *member_type_parameters = list_length;
+ *member_type_parameters_offset_start = builder_->ReaderOffset();
+ }
+ }
+ }
+ }
+}
+
+void StreamingScopeBuilder::ReadClassUntilTypeParameters() {
+ Tag class_tag = builder_->ReadTag();
+ ASSERT(class_tag == kClass);
+ builder_->SkipCanonicalNameReference(); // read canonical_name.
+ builder_->ReadPosition(); // read position.
+ builder_->ReadBool(); // read is_abstract.
+ builder_->SkipStringReference(); // read name index.
+ builder_->ReadUInt(); // read source_uri_index.
+ builder_->SkipListOfExpressions(); // read annotations.
+}
+
+void StreamingScopeBuilder::ReadClassUntilFields() {
+ ReadClassUntilTypeParameters();
+ builder_->SkipTypeParametersList(); // read type_parameters.
+ Tag type_tag = builder_->ReadTag(); // read type (part 1).
+ if (type_tag == kSomething) {
+ builder_->SkipDartType(); // read type (part 2).
+ }
+ type_tag = builder_->ReadTag(); // read Mixed-in type (part 1).
+ if (type_tag == kSomething) {
+ builder_->SkipDartType(); // read Mixed-in type (part 2).
+ }
+ builder_->SkipListOfDartTypes(); // read implemented_classes.
+}
+
+void StreamingScopeBuilder::ReadFunctionNodeUntilTypeParameters(
+ word* async_marker,
+ word* dart_async_marker) {
+ Tag tag = builder_->ReadTag(); // read tag.
+ ASSERT(tag == kFunctionNode);
+
+ builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read end position.
+ *async_marker = builder_->ReadByte(); // read async marker.
+ *dart_async_marker = builder_->ReadByte(); // read dart async marker.
+}
+
void StreamingScopeBuilder::VisitFunctionNode() {
word async_marker_word;
word dart_async_marker_word;
- builder_->ReadFunctionNodeUntilTypeParameters(
- &unused_tokenposition, &unused_tokenposition, &async_marker_word,
- &dart_async_marker_word);
+ ReadFunctionNodeUntilTypeParameters(&async_marker_word,
+ &dart_async_marker_word);
FunctionNode::AsyncMarker async_marker =
static_cast<FunctionNode::AsyncMarker>(async_marker_word);
FunctionNode::AsyncMarker dart_async_marker =
@@ -408,7 +589,6 @@ void StreamingScopeBuilder::VisitFunctionNode() {
// Read (but don't visit) the positional and named parameters, because they've
// already been added to the scope.
- builder_->ReadUInt(); // read total parameter count.
builder_->ReadUInt(); // read required_parameter_count.
builder_->SkipListOfVariableDeclarations(); // read list of positionals.
@@ -463,11 +643,11 @@ void StreamingScopeBuilder::VisitInitializer() {
VisitExpression(); // read value.
return;
case kSuperInitializer:
- builder_->SkipCanonicalNameReference(); // read target_reference.
+ builder_->SkipCanonicalNameReference(); // read field_reference.
VisitArguments(); // read arguments.
return;
case kRedirectingInitializer:
- builder_->SkipCanonicalNameReference(); // read target_reference.
+ builder_->SkipCanonicalNameReference(); // read field_reference.
VisitArguments(); // read arguments.
return;
case kLocalInitializer:
@@ -1140,7 +1320,6 @@ void StreamingScopeBuilder::HandleLocalFunction(intptr_t parent_kernel_offset) {
result_->function_scopes.Add(function_scope);
}
- builder_->ReadUInt(); // read total parameter count.
builder_->ReadUInt(); // read required_parameter_count.
// read positional_parameters and named_parameters.
AddPositionalAndNamedParameters();
@@ -1302,6 +1481,16 @@ void StreamingScopeBuilder::AddSwitchVariable() {
}
}
+StringIndex StreamingScopeBuilder::GetNameFromVariableDeclaration(
+ intptr_t kernel_offset) {
+ // Temporarily go to the variable declaration, read the name.
+ AlternativeReadingScope alt(builder_->reader_, kernel_offset);
+ builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read equals position.
+ builder_->ReadFlags(); // read flags.
+ return builder_->ReadStringReference(); // read name index.
+}
+
void StreamingScopeBuilder::LookupVariable(intptr_t declaration_binary_offest) {
LocalVariable* variable = result_->locals.Lookup(declaration_binary_offest);
if (variable == NULL) {
@@ -1312,7 +1501,7 @@ void StreamingScopeBuilder::LookupVariable(intptr_t declaration_binary_offest) {
ASSERT(current_function_scope_->parent() != NULL);
StringIndex var_name =
- builder_->GetNameFromVariableDeclaration(declaration_binary_offest);
+ GetNameFromVariableDeclaration(declaration_binary_offest);
const dart::String& name = H.DartSymbol(var_name);
variable = current_function_scope_->parent()->LookupVariable(name, true);
@@ -1397,17 +1586,6 @@ AbstractType& StreamingDartTypeTranslator::BuildType() {
return dart::AbstractType::ZoneHandle(Z, result_.raw());
}
-AbstractType& StreamingDartTypeTranslator::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 dart::AbstractType::ZoneHandle(Z, result_.raw());
-}
-
AbstractType& StreamingDartTypeTranslator::BuildVariableType() {
AbstractType& abstract_type = BuildType();
@@ -2011,6 +2189,7 @@ void StreamingConstantEvaluator::EvaluateStaticGet() {
if (H.IsMethod(target)) {
Function& closure_function =
Function::ZoneHandle(Z, function.ImplicitClosureFunction());
+ closure_function.set_kernel_function(function.kernel_function());
result_ = closure_function.ImplicitStaticClosure();
result_ = H.Canonicalize(result_);
} else if (H.IsGetter(target)) {
@@ -2408,1198 +2587,115 @@ RawObject* StreamingConstantEvaluator::EvaluateConstConstructorCall(
instance = Instance::New(type_class, Heap::kOld);
if (!type_arguments.IsNull()) {
ASSERT(type_arguments.IsInstantiated());
- instance.SetTypeArguments(
- TypeArguments::Handle(Z, type_arguments.Canonicalize()));
- }
- arg_values.SetAt(0, instance);
- } else {
- // Prepend type_arguments to list of arguments to factory.
- ASSERT(type_arguments.IsZoneHandle());
- arg_values.SetAt(0, type_arguments);
- }
- arg_values.SetAt((0 + kNumExtraArgs), argument);
- const Array& args_descriptor =
- Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, num_arguments,
- Object::empty_array()));
- const Object& result = Object::Handle(
- Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
- ASSERT(!result.IsError());
- if (constructor.IsFactory()) {
- // The factory method returns the allocated object.
- instance ^= result.raw();
- }
- return H.Canonicalize(instance);
-}
-
-const TypeArguments* StreamingConstantEvaluator::TranslateTypeArguments(
- const Function& target,
- dart::Class* target_klass) {
- intptr_t types_count = builder_->ReadListLength(); // read types count.
-
- const TypeArguments* type_arguments = NULL;
- if (types_count > 0) {
- type_arguments = &T.BuildInstantiatedTypeArguments(
- *target_klass, types_count); // read types.
-
- if (!(type_arguments->IsNull() || type_arguments->IsInstantiated())) {
- H.ReportError("Type must be constant in const constructor.");
- }
- } else if (target.IsFactory() && type_arguments == NULL) {
- // All factories take a type arguments vector as first argument (independent
- // of whether the class is generic or not).
- type_arguments = &TypeArguments::ZoneHandle(Z, TypeArguments::null());
- }
- return type_arguments;
-}
-
-bool StreamingConstantEvaluator::EvaluateBooleanExpressionHere() {
- EvaluateExpression(builder_->ReaderOffset(), false);
- AssertBoolInCheckedMode();
- return result_.raw() == Bool::True().raw();
-}
-
-bool StreamingConstantEvaluator::GetCachedConstant(intptr_t kernel_offset,
- Instance* value) {
- if (builder_ == NULL || builder_->flow_graph_builder_ == NULL) return false;
-
- const Function& function = builder_->parsed_function()->function();
- if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
- // Don't cache constants in initializer expressions. They get
- // evaluated only once.
- return false;
- }
-
- bool is_present = false;
- ASSERT(!script_.InVMHeap());
- if (script_.compile_time_constants() == Array::null()) {
- return false;
- }
- KernelConstantsMap constants(script_.compile_time_constants());
- *value ^= constants.GetOrNull(kernel_offset, &is_present);
- // Mutator compiler thread may add constants while background compiler
- // is running, and thus change the value of 'compile_time_constants';
- // do not assert that 'compile_time_constants' has not changed.
- constants.Release();
- if (FLAG_compiler_stats && is_present) {
- ++H.thread()->compiler_stats()->num_const_cache_hits;
- }
- return is_present;
-}
-
-
-void StreamingConstantEvaluator::CacheConstantValue(intptr_t kernel_offset,
- const Instance& value) {
- ASSERT(Thread::Current()->IsMutatorThread());
-
- if (builder_ == NULL || builder_->flow_graph_builder_ == NULL) return;
-
- const Function& function = builder_->parsed_function()->function();
- if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
- // Don't cache constants in initializer expressions. They get
- // evaluated only once.
- return;
- }
- const intptr_t kInitialConstMapSize = 16;
- ASSERT(!script_.InVMHeap());
- if (script_.compile_time_constants() == Array::null()) {
- const Array& array = Array::Handle(
- HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew));
- script_.set_compile_time_constants(array);
- }
- KernelConstantsMap constants(script_.compile_time_constants());
- constants.InsertNewOrGetValue(kernel_offset, value);
- script_.set_compile_time_constants(constants.Release());
-}
-
-void StreamingFlowGraphBuilder::DiscoverEnclosingElements(
- Zone* zone,
- const Function& function,
- Function* outermost_function,
- intptr_t* outermost_kernel_offset,
- intptr_t* parent_class_offset) {
- // Find out if there is an enclosing kernel class (which will be used to
- // resolve type parameters).
- *outermost_function = function.raw();
- while (outermost_function->parent_function() != Object::null()) {
- *outermost_function = outermost_function->parent_function();
- }
-
- if (outermost_function->kernel_offset() > 0) {
- *outermost_kernel_offset = outermost_function->kernel_offset();
- *parent_class_offset = GetParentOffset(*outermost_kernel_offset);
- }
-}
-
-intptr_t StreamingFlowGraphBuilder::GetParentOffset(intptr_t offset) {
- AlternativeReadingScope alt(reader_, offset);
-
- Tag tag = PeekTag();
- intptr_t parent_offset = -1;
- switch (tag) {
- case kConstructor:
- return ReadConstructorUntilFunctionNode();
- case kProcedure:
- ReadProcedureUntilFunctionNode(
- &unused_word, &parent_offset); // read first part of procedure.
- return parent_offset;
- case kField:
- ReadFieldUntilAnnotation(&unused_nameindex, &unused_tokenposition,
- &unused_tokenposition, &unused_word,
- &parent_offset);
- return parent_offset;
- default:
- UNIMPLEMENTED();
- return -1;
- }
-}
-
-void StreamingFlowGraphBuilder::GetTypeParameterInfoForClass(
- intptr_t class_offset,
- intptr_t* type_paremeter_counts,
- intptr_t* type_paremeter_offset) {
- AlternativeReadingScope alt(reader_, class_offset);
-
- ReadClassUntilTypeParameters();
- *type_paremeter_counts =
- ReadListLength(); // read type_parameters list length.
- *type_paremeter_offset = ReaderOffset();
-}
-
-void StreamingFlowGraphBuilder::ReadClassUntilFields() {
- ReadClassUntilTypeParameters();
- SkipTypeParametersList(); // read type_parameters.
- Tag type_tag = ReadTag(); // read type (part 1).
- if (type_tag == kSomething) {
- SkipDartType(); // read type (part 2).
- }
- type_tag = ReadTag(); // read Mixed-in type (part 1).
- if (type_tag == kSomething) {
- SkipDartType(); // read Mixed-in type (part 2).
- }
- SkipListOfDartTypes(); // read implemented_classes.
-}
-
-void StreamingFlowGraphBuilder::ReadClassUntilTypeParameters() {
- Tag class_tag = ReadTag();
- ASSERT(class_tag == kClass);
- SkipCanonicalNameReference(); // read canonical_name.
- ReadPosition(); // read position.
- ReadBool(); // read is_abstract.
- SkipStringReference(); // read name index.
- ReadUInt(); // read source_uri_index.
- SkipListOfExpressions(); // read annotations.
-}
-
-intptr_t StreamingFlowGraphBuilder::ReadConstructorUntilFunctionNode() {
- Tag tag = ReadTag();
- ASSERT(tag == kConstructor);
- SkipCanonicalNameReference(); // read canonical name reference.
- ReadPosition(); // read position.
- ReadPosition(); // read end position.
- ReadFlags(); // read flags.
- intptr_t parent_offset = ReadUInt(); // parent class binary offset.
- SkipName(); // read name.
- SkipListOfExpressions(); // read annotations.
- return parent_offset;
-}
-
-Tag StreamingFlowGraphBuilder::ReadProcedureUntilFunctionNode(
- word* kind,
- intptr_t* parent_offset) {
- Tag tag = ReadTag(); // read tag.
- ASSERT(tag == kProcedure);
- SkipCanonicalNameReference(); // read canonical name reference.
- ReadPosition(); // read position.
- ReadPosition(); // read end position.
- *kind = ReadByte(); // read kind.
- ReadFlags(); // read flags.
- *parent_offset = ReadUInt(); // read parent class binary offset.
- SkipName(); // read name,
- ReadUInt(); // read source_uri_index.
- SkipListOfExpressions(); // read annotations.
- return ReadTag(); // read tag for optional function node.
-}
-
-void StreamingFlowGraphBuilder::ReadFieldUntilAnnotation(
- NameIndex* canonical_name,
- TokenPosition* position,
- TokenPosition* end_position,
- word* flags,
- intptr_t* parent_offset) {
- Tag tag = ReadTag();
- ASSERT(tag == kField);
-
- *canonical_name = ReadCanonicalNameReference(); // read canonical_name.
- *position = ReadPosition(); // read position.
- *end_position = ReadPosition(); // read end position.
- *flags = ReadFlags(); // read flags.
- *parent_offset = ReadUInt(); // read parent class binary offset.
- SkipName(); // read name.
- ReadUInt(); // source_uri_index.
-}
-
-void StreamingFlowGraphBuilder::GetTypeParameterInfoForPossibleProcedure(
- intptr_t outermost_kernel_offset,
- bool* member_is_procedure,
- bool* is_factory_procedure,
- intptr_t* member_type_parameters,
- intptr_t* member_type_parameters_offset_start) {
- if (outermost_kernel_offset >= 0) {
- AlternativeReadingScope alt(reader_, outermost_kernel_offset);
- Tag tag = PeekTag();
- if (tag == kProcedure) {
- *member_is_procedure = true;
-
- word kind;
- tag = ReadProcedureUntilFunctionNode(
- &kind, &unused_intptr); // read first part of procedure.
- *is_factory_procedure =
- static_cast<Procedure::ProcedureKind>(kind) == Procedure::kFactory;
-
- if (tag == kSomething) {
- ReadFunctionNodeUntilTypeParameters(
- &unused_tokenposition, &unused_tokenposition, &unused_word,
- &unused_word); // read first part of function node.
-
- intptr_t list_length =
- ReadListLength(); // read type_parameters list length.
- if (list_length > 0) {
- *member_type_parameters = list_length;
- *member_type_parameters_offset_start = ReaderOffset();
- }
- }
- }
- }
-}
-
-void StreamingFlowGraphBuilder::ReadFunctionNodeUntilTypeParameters(
- TokenPosition* position,
- TokenPosition* end_position,
- word* async_marker,
- word* dart_async_marker) {
- Tag tag = ReadTag(); // read tag.
- ASSERT(tag == kFunctionNode);
-
- *position = ReadPosition(); // read position.
- *end_position = ReadPosition(); // read end position.
- *async_marker = ReadByte(); // read async marker.
- *dart_async_marker = ReadByte(); // read dart async marker.
-}
-
-intptr_t StreamingFlowGraphBuilder::ReadUntilFunctionNode() {
- const Tag tag = PeekTag();
- if (tag == kProcedure) {
- Tag has_function_node = ReadProcedureUntilFunctionNode(
- &unused_word, &unused_intptr); // read first part of procedure.
- if (has_function_node == kNothing) {
- // Running a procedure without a function node doesn't make sense.
- UNREACHABLE();
- }
- return -1;
- // Now at start of FunctionNode.
- } else if (tag == kConstructor) {
- // read first part of constructor.
- return ReadConstructorUntilFunctionNode();
- // Now at start of FunctionNode.
- // Notice that we also have a list of initializers after that!
- } else if (tag == kFunctionNode) {
- // Already at start of FunctionNode.
- } else {
- UNREACHABLE();
- }
- return -1;
-}
-
-StringIndex StreamingFlowGraphBuilder::GetNameFromVariableDeclaration(
- intptr_t kernel_offset) {
- // Temporarily go to the variable declaration, read the name.
- AlternativeReadingScope alt(reader_, kernel_offset);
- ReadPosition(); // read position.
- ReadPosition(); // read equals position.
- ReadFlags(); // read flags.
- return ReadStringReference(); // read name index.
-}
-
-FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfStaticFieldInitializer() {
- TokenPosition position;
- TokenPosition end_position;
- word flags;
- ReadFieldUntilAnnotation(&unused_nameindex, &position, &end_position, &flags,
- &unused_intptr);
- bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
- bool is_const = (flags & Field::kFlagConst) == Field::kFlagConst;
- ASSERT(is_static);
-
- SkipListOfExpressions(); // read annotations.
- SkipDartType(); // read type.
- Tag initializer_tag = ReadTag(); // read first part of initializer.
- if (initializer_tag != kSomething) {
- UNREACHABLE();
- }
-
- TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
- flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
- *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);
-
- Fragment body(normal_entry);
- body += flow_graph_builder_->CheckStackOverflowInPrologue();
- if (is_const) {
- // this will (potentially) read the initializer, but reset the position.
- body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
- SkipExpression(); // read the initializer.
- } else {
- body += BuildExpression(); // read initializer.
- }
- body += Return(TokenPosition::kNoSource);
-
- return new (Z)
- FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
- flow_graph_builder_->next_block_id_ - 1);
-}
-
-FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldAccessor(
- LocalVariable* setter_value) {
- NameIndex canonical_name;
- ReadFieldUntilAnnotation(&canonical_name, &unused_tokenposition,
- &unused_tokenposition, &unused_word, &unused_intptr);
- SkipListOfExpressions(); // read annotations.
- SkipDartType(); // read type.
- Tag initializer_tag = ReadTag(); // read first part of initializer.
-
- const Function& function = parsed_function()->function();
-
- bool is_setter = function.IsImplicitSetterFunction();
- bool is_method = !function.IsStaticFunction();
- dart::Field& field =
- dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name));
-
- TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
- flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
- *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);
-
- Fragment body(normal_entry);
- if (is_setter) {
- if (is_method) {
- body += LoadLocal(scopes()->this_variable);
- body += LoadLocal(setter_value);
- body += flow_graph_builder_->StoreInstanceFieldGuarded(field, false);
- } else {
- body += LoadLocal(setter_value);
- body += StoreStaticField(TokenPosition::kNoSource, field);
- }
- body += NullConstant();
- } else if (is_method) {
- body += LoadLocal(scopes()->this_variable);
- body += flow_graph_builder_->LoadField(field);
- } else if (field.is_const()) {
- // If the parser needs to know the value of an uninitialized constant field
- // it will set the value to the transition sentinel (used to detect circular
- // initialization) and then call the implicit getter. Thus, the getter
- // cannot contain the InitStaticField instruction that normal static getters
- // contain because it would detect spurious circular initialization when it
- // checks for the transition sentinel.
- ASSERT(initializer_tag == kSomething);
- // this will (potentially) read the initializer, but reset the position.
- body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
- SkipExpression(); // read the initializer.
- } else {
- // The field always has an initializer because static fields without
- // initializers are initialized eagerly and do not have implicit getters.
- ASSERT(field.has_initializer());
- body += Constant(field);
- body += flow_graph_builder_->InitStaticField(field);
- body += Constant(field);
- body += LoadStaticField();
- }
- body += Return(TokenPosition::kNoSource);
-
- return new (Z)
- FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
- flow_graph_builder_->next_block_id_ - 1);
-}
-
-void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
- intptr_t num_optional_parameters =
- parsed_function()->function().NumOptionalParameters();
- if (num_optional_parameters > 0) {
- ZoneGrowableArray<const Instance*>* default_values =
- new ZoneGrowableArray<const Instance*>(Z, num_optional_parameters);
-
- AlternativeReadingScope alt(reader_);
- ReadFunctionNodeUntilTypeParameters(
- &unused_tokenposition, &unused_tokenposition, &unused_word,
- &unused_word); // read first part of function node.
- SkipTypeParametersList(); // read type_parameters.
- ReadUInt(); // read total parameter count.
- intptr_t required = ReadUInt(); // read required_parameter_count.
-
- if (parsed_function()->function().HasOptionalNamedParameters()) {
- // List of positional.
- intptr_t list_length = ReadListLength(); // read list length.
- for (intptr_t i = 0; i < list_length; ++i) {
- SkipVariableDeclaration(); // read ith variable declaration.
- }
-
- // List of named.
- list_length = ReadListLength(); // read list length.
- ASSERT(num_optional_parameters == list_length);
- ASSERT(!parsed_function()->function().HasOptionalPositionalParameters());
- for (intptr_t i = 0; i < list_length; ++i) {
- Instance* default_value;
-
- // Read ith variable declaration
- ReadPosition(); // read position.
- ReadPosition(); // read equals position.
- ReadFlags(); // read flags.
- SkipStringReference(); // read name index.
- SkipDartType(); // read type.
- Tag tag = ReadTag(); // read (first part of) initializer.
- if (tag == kSomething) {
- // this will (potentially) read the initializer,
- // but reset the position.
- default_value =
- &constant_evaluator_.EvaluateExpression(ReaderOffset());
- SkipExpression(); // read (actual) initializer.
- } else {
- default_value = &Instance::ZoneHandle(Z, Instance::null());
- }
- default_values->Add(default_value);
- }
- } else {
- // List of positional.
- intptr_t list_length = ReadListLength(); // read list length.
- ASSERT(list_length == required + num_optional_parameters);
- ASSERT(parsed_function()->function().HasOptionalPositionalParameters());
- for (intptr_t i = 0; i < required; ++i) {
- SkipVariableDeclaration(); // read ith variable declaration.
- }
- for (intptr_t i = 0; i < num_optional_parameters; ++i) {
- Instance* default_value;
-
- // Read ith variable declaration
- ReadPosition(); // read position.
- ReadPosition(); // read equals position.
- ReadFlags(); // read flags.
- SkipStringReference(); // read name index.
- SkipDartType(); // read type.
- Tag tag = ReadTag(); // read (first part of) initializer.
- if (tag == kSomething) {
- // this will (potentially) read the initializer,
- // but reset the position.
- default_value =
- &constant_evaluator_.EvaluateExpression(ReaderOffset());
- SkipExpression(); // read (actual) initializer.
- } else {
- default_value = &Instance::ZoneHandle(Z, Instance::null());
- }
- default_values->Add(default_value);
- }
-
- // List of named.
- list_length = ReadListLength(); // read list length.
- ASSERT(list_length == 0);
- }
- parsed_function()->set_default_parameter_values(default_values);
- }
-}
-
-Fragment StreamingFlowGraphBuilder::BuildFieldInitializer(
- NameIndex canonical_name) {
- dart::Field& field =
- dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name));
- if (PeekTag() == kNullLiteral) {
- SkipExpression(); // read past the null literal.
- field.RecordStore(Object::null_object());
- return Fragment();
- }
-
- Fragment instructions;
- instructions += LoadLocal(scopes()->this_variable);
- instructions += BuildExpression();
- instructions += flow_graph_builder_->StoreInstanceFieldGuarded(field, true);
- return instructions;
-}
-
-Fragment StreamingFlowGraphBuilder::BuildInitializers(
- intptr_t constructor_class_parent_offset) {
- Fragment instructions;
-
- // These come from:
- // class A {
- // var x = (expr);
- // }
- {
- AlternativeReadingScope alt(reader_, constructor_class_parent_offset);
- ReadClassUntilFields(); // read first part of class.
- intptr_t list_length = ReadListLength(); // read fields list length.
-
- for (intptr_t i = 0; i < list_length; ++i) {
- intptr_t field_offset = ReaderOffset();
- NameIndex canonical_name;
- TokenPosition position;
- TokenPosition end_position;
- word flags;
- ReadFieldUntilAnnotation(&canonical_name, &position, &end_position,
- &flags, &unused_intptr);
- bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
- SkipListOfExpressions(); // read annotations.
- SkipDartType(); // read type.
- Tag initializer_tag = ReadTag(); // read first part of initializer.
- if (!is_static && initializer_tag == kSomething) {
- EnterScope(field_offset);
- instructions +=
- BuildFieldInitializer(canonical_name); // read initializer.
- ExitScope(field_offset);
- } else if (initializer_tag == kSomething) {
- SkipExpression(); // read initializer.
- }
- }
- }
-
- // These to come from:
- // class A {
- // var x;
- // var y;
- // A(this.x) : super(expr), y = (expr);
- // }
- {
- AlternativeReadingScope alt(reader_);
- SkipFunctionNode(); // read constructors function node.
-
- intptr_t list_length = ReadListLength(); // read initializers list length.
- for (intptr_t i = 0; i < list_length; ++i) {
- Tag tag = ReadTag();
- switch (tag) {
- case kInvalidInitializer:
- UNIMPLEMENTED();
- return Fragment();
- case kFieldInitializer: {
- NameIndex canonical_name =
- ReadCanonicalNameReference(); // read field_reference.
- instructions += BuildFieldInitializer(canonical_name); // read value.
- break;
- }
- case kSuperInitializer: {
- NameIndex canonical_target =
- ReadCanonicalNameReference(); // read target_reference.
-
- instructions += LoadLocal(scopes()->this_variable);
- instructions += PushArgument();
-
- // TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
- Array& argument_names = Array::ZoneHandle(Z);
- intptr_t argument_count;
- instructions += BuildArguments(&argument_names,
- &argument_count); // read arguments.
- argument_count += 1;
-
- const Function& target = Function::ZoneHandle(
- Z, H.LookupConstructorByKernelConstructor(canonical_target));
- instructions += StaticCall(TokenPosition::kNoSource, target,
- argument_count, argument_names);
- instructions += Drop();
- break;
- }
- case kRedirectingInitializer: {
- NameIndex canonical_target =
- ReadCanonicalNameReference(); // read target_reference.
-
- instructions += LoadLocal(scopes()->this_variable);
- instructions += PushArgument();
-
- // TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
- Array& argument_names = Array::ZoneHandle(Z);
- intptr_t argument_count;
- instructions += BuildArguments(&argument_names,
- &argument_count); // read arguments.
- argument_count += 1;
-
- const Function& target = Function::ZoneHandle(
- Z, H.LookupConstructorByKernelConstructor(canonical_target));
- instructions += StaticCall(TokenPosition::kNoSource, target,
- argument_count, argument_names);
- instructions += Drop();
- break;
- }
- case kLocalInitializer: {
- // The other initializers following this one might read the variable.
- // This is used e.g. for evaluating the arguments to a super call
- // first, run normal field initializers next and then make the actual
- // super call:
- //
- // The frontend converts
- //
- // class A {
- // var x;
- // A(a, b) : super(a + b), x = 2*b {}
- // }
- //
- // to
- //
- // class A {
- // var x;
- // A(a, b) : tmp = a + b, x = 2*b, super(tmp) {}
- // }
- //
- // (This is strictly speaking not what one should do in terms of the
- // specification but that is how it is currently implemented.)
- LocalVariable* variable = LookupVariable(ReaderOffset());
-
- // Variable declaration
- ReadPosition(); // read position.
- ReadPosition(); // read equals position.
- word flags = ReadFlags(); // read flags.
- ASSERT((flags & VariableDeclaration::kFlagConst) !=
- VariableDeclaration::kFlagConst);
- SkipStringReference(); // read name index.
- SkipDartType(); // read type.
- Tag tag = ReadTag(); // read (first part of) initializer.
- if (tag != kSomething) {
- UNREACHABLE();
- }
-
- instructions += BuildExpression(); // read initializer.
- instructions += StoreLocal(TokenPosition::kNoSource, variable);
- instructions += Drop();
- break;
- }
- default:
- UNREACHABLE();
- }
- }
- }
- return instructions;
-}
-
-FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
- const Function& function) {
- const Function& target = Function::ZoneHandle(Z, function.parent_function());
-
- TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
- flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
- *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);
- SetupDefaultParameterValues();
-
- Fragment body(normal_entry);
- body += flow_graph_builder_->CheckStackOverflowInPrologue();
-
- // Load all the arguments.
- if (!target.is_static()) {
- // The context has a fixed shape: a single variable which is the
- // closed-over receiver.
- body += LoadLocal(parsed_function()->current_context_var());
- body += flow_graph_builder_->LoadField(Context::variable_offset(0));
- body += PushArgument();
- }
-
- TokenPosition end_position;
- ReadFunctionNodeUntilTypeParameters(
- &unused_tokenposition, &end_position, &unused_word,
- &unused_word); // read first part of function node.
- SkipTypeParametersList(); // read type parameter list.
- ReadUInt(); // read total parameter count.
- ReadUInt(); // read required_parameter_count.
-
- // Positional.
- intptr_t positional_argument_count = ReadListLength();
- for (intptr_t i = 0; i < positional_argument_count; ++i) {
- body += LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset.
- body += PushArgument();
- SkipVariableDeclaration(); // read ith variable.
- }
-
- // Named.
- intptr_t named_argument_count = ReadListLength();
- Array& argument_names = Array::ZoneHandle(Z);
- if (named_argument_count > 0) {
- argument_names = Array::New(named_argument_count);
- for (intptr_t i = 0; i < named_argument_count; ++i) {
- body +=
- LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset.
- body += PushArgument();
- argument_names.SetAt(
- i, H.DartSymbol(GetNameFromVariableDeclaration(ReaderOffset())));
- SkipVariableDeclaration(); // read ith variable.
- }
- }
-
- // Forward them to the target.
- intptr_t argument_count = positional_argument_count + named_argument_count;
- if (!target.is_static()) ++argument_count;
- body += StaticCall(TokenPosition::kNoSource, target, argument_count,
- argument_names);
-
- // Return the result.
- body += Return(end_position);
-
- return new (Z)
- FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
- flow_graph_builder_->next_block_id_ - 1);
-}
-
-static bool IsGetMainClosure(const String& name) {
- if (name.Length() < 16) return false;
- const char* cstr = "_getMainClosure@";
- for (intptr_t i = 0; i < 16; ++i) {
- if (name.CharAt(i) != cstr[i]) return false;
- }
- return true;
-}
-
-FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction(
- bool is_in_builtin_library_toplevel,
- intptr_t constructor_class_parent_offset) {
- const Function& dart_function = parsed_function()->function();
- TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
- flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
- *parsed_function(), normal_entry, flow_graph_builder_->osr_id_);
-
- SetupDefaultParameterValues();
-
- Fragment body;
- if (!dart_function.is_native())
- body += flow_graph_builder_->CheckStackOverflowInPrologue();
- intptr_t context_size =
- parsed_function()->node_sequence()->scope()->num_context_variables();
- if (context_size > 0) {
- body += flow_graph_builder_->PushContext(context_size);
- LocalVariable* context = MakeTemporary();
-
- // Copy captured parameters from the stack into the context.
- LocalScope* scope = parsed_function()->node_sequence()->scope();
- intptr_t parameter_count = dart_function.NumParameters();
- intptr_t parameter_index = parsed_function()->first_parameter_index();
- for (intptr_t i = 0; i < parameter_count; ++i, --parameter_index) {
- LocalVariable* variable = scope->VariableAt(i);
- if (variable->is_captured()) {
- // There is no LocalVariable describing the on-stack parameter so
- // create one directly and use the same type.
- LocalVariable* parameter = new (Z)
- LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
- Symbols::TempParam(), variable->type());
- parameter->set_index(parameter_index);
- // Mark the stack variable so it will be ignored by the code for
- // try/catch.
- parameter->set_is_captured_parameter(true);
-
- // Copy the parameter from the stack to the context. Overwrite it
- // with a null constant on the stack so the original value is
- // eligible for garbage collection.
- body += LoadLocal(context);
- body += LoadLocal(parameter);
- body += flow_graph_builder_->StoreInstanceField(
- TokenPosition::kNoSource,
- Context::variable_offset(variable->index()));
- body += NullConstant();
- body += StoreLocal(TokenPosition::kNoSource, parameter);
- body += Drop();
- }
- }
- body += Drop(); // The context.
- }
- if (constructor_class_parent_offset > 0) {
- // TODO(27590): Currently the [VariableDeclaration]s from the
- // initializers will be visible inside the entire body of the constructor.
- // We should make a separate scope for them.
- body += BuildInitializers(constructor_class_parent_offset);
- }
-
- TokenPosition position;
- ReadFunctionNodeUntilTypeParameters(
- &position, &unused_tokenposition, &unused_word,
- &unused_word); // read first part of function node.
- SkipTypeParametersList(); // read type parameter list.
- ReadUInt(); // read total parameter count
- ReadUInt(); // read required_parameter_count.
- intptr_t first_parameter_offset = -1;
- {
- AlternativeReadingScope alt(reader_);
- intptr_t list_length = ReadListLength(); // read number of positionals.
- if (list_length > 0) {
- first_parameter_offset = ReaderOffset();
- }
- }
- // Current position: About to read list of positionals.
-
- // The specification defines the result of `a == b` to be:
- //
- // a) if either side is `null` then the result is `identical(a, b)`.
- // b) else the result is `a.operator==(b)`
- //
- // For user-defined implementations of `operator==` we need therefore
- // implement the handling of a).
- //
- // The default `operator==` implementation in `Object` is implemented in terms
- // of identical (which we assume here!) which means that case a) is actually
- // included in b). So we just use the normal implementation in the body.
- if ((dart_function.NumParameters() == 2) &&
- (dart_function.name() == Symbols::EqualOperator().raw()) &&
- (dart_function.Owner() != I->object_store()->object_class())) {
- LocalVariable* parameter = LookupVariable(first_parameter_offset);
-
- TargetEntryInstr* null_entry;
- TargetEntryInstr* non_null_entry;
-
- body += LoadLocal(parameter);
- body += BranchIfNull(&null_entry, &non_null_entry);
-
- // The argument was `null` and the receiver is not the null class (we only
- // go into this branch for user-defined == operators) so we can return
- // false.
- Fragment null_fragment(null_entry);
- null_fragment += Constant(Bool::False());
- null_fragment += Return(dart_function.end_token_pos());
-
- body = Fragment(body.entry, non_null_entry);
- }
-
- // If we run in checked mode, we have to check the type of the passed
- // arguments.
- if (I->type_checks()) {
- // Positional.
- intptr_t list_length = ReadListLength();
- for (intptr_t i = 0; i < list_length; ++i) {
- body +=
- LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset.
- body += CheckVariableTypeInCheckedMode(ReaderOffset());
- body += Drop();
- SkipVariableDeclaration(); // read ith variable.
- }
-
- // Named.
- list_length = ReadListLength();
- for (intptr_t i = 0; i < list_length; ++i) {
- body +=
- LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset.
- body += CheckVariableTypeInCheckedMode(ReaderOffset());
- body += Drop();
- SkipVariableDeclaration(); // read ith variable.
+ instance.SetTypeArguments(
+ TypeArguments::Handle(Z, type_arguments.Canonicalize()));
}
+ arg_values.SetAt(0, instance);
} else {
- // Still skip past the parameters.
- SkipListOfVariableDeclarations(); // read list of positionals.
- SkipListOfVariableDeclarations(); // read list of named.
- }
-
- SkipDartType(); // read return type.
-
- if (FLAG_causal_async_stacks &&
- (dart_function.IsAsyncFunction() || dart_function.IsAsyncGenerator())) {
- LocalScope* scope = parsed_function()->node_sequence()->scope();
- // :async_stack_trace = _asyncStackTraceHelper(:async_op);
- const dart::Library& async_lib =
- dart::Library::Handle(dart::Library::AsyncLibrary());
- const Function& target = Function::ZoneHandle(
- Z,
- async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper()));
- ASSERT(!target.IsNull());
-
- // TODO(johnmccutchan): Why does this have the null value?
- LocalVariable* async_op =
- scope->child()->LookupVariable(Symbols::AsyncOperation(), false);
- ASSERT(async_op != NULL);
- ASSERT(async_op->is_captured());
- body += LoadLocal(async_op);
- body += PushArgument();
- body += StaticCall(TokenPosition::kNoSource, target, 1);
- LocalVariable* async_stack_trace_var =
- scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
- ASSERT(async_stack_trace_var != NULL);
- body += StoreLocal(TokenPosition::kNoSource, async_stack_trace_var);
- body += Drop();
- }
-
- bool has_body = ReadTag() == kSomething; // read first part of body.
-
- if (dart_function.is_native()) {
- body += flow_graph_builder_->NativeFunctionBody(first_parameter_offset,
- dart_function);
- } else if (has_body) {
- if (is_in_builtin_library_toplevel &&
- IsGetMainClosure(dart::String::Handle(Z, dart_function.name()))) {
- body += BuildGetMainClosure();
- } else {
- body += BuildStatement(); // read body.
- }
+ // Prepend type_arguments to list of arguments to factory.
+ ASSERT(type_arguments.IsZoneHandle());
+ arg_values.SetAt(0, type_arguments);
}
- if (body.is_open()) {
- body += NullConstant();
- body += Return(dart_function.end_token_pos());
- }
-
- // If functions body contains any yield points build switch statement that
- // selects a continuation point based on the value of :await_jump_var.
- if (!yield_continuations().is_empty()) {
- // The code we are building will be executed right after we enter
- // the function and before any nested contexts are allocated.
- // Reset current context_depth_ to match this.
- const intptr_t current_context_depth = flow_graph_builder_->context_depth_;
- flow_graph_builder_->context_depth_ =
- scopes()->yield_jump_variable->owner()->context_level();
-
- // Prepend an entry corresponding to normal entry to the function.
- yield_continuations().InsertAt(
- 0, YieldContinuation(new (Z) DropTempsInstr(0, NULL),
- CatchClauseNode::kInvalidTryIndex));
- yield_continuations()[0].entry->LinkTo(body.entry);
-
- // Build a switch statement.
- Fragment dispatch;
-
- // Load :await_jump_var into a temporary.
- dispatch += LoadLocal(scopes()->yield_jump_variable);
- dispatch += StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable);
- dispatch += Drop();
-
- BlockEntryInstr* block = NULL;
- for (intptr_t i = 0; i < yield_continuations().length(); i++) {
- if (i == 1) {
- // This is not a normal entry but a resumption. Restore
- // :current_context_var from :await_ctx_var.
- // Note: after this point context_depth_ does not match current context
- // depth so we should not access any local variables anymore.
- dispatch += LoadLocal(scopes()->yield_context_variable);
- dispatch += StoreLocal(TokenPosition::kNoSource,
- parsed_function()->current_context_var());
- dispatch += Drop();
- }
- if (i == (yield_continuations().length() - 1)) {
- // We reached the last possility, no need to build more ifs.
- // Continue to the last continuation.
- // Note: continuations start with nop DropTemps instruction
- // which acts like an anchor, so we need to skip it.
- block->set_try_index(yield_continuations()[i].try_index);
- dispatch <<= yield_continuations()[i].entry->next();
- break;
- }
-
- // Build comparison:
- //
- // if (:await_ctx_var == i) {
- // -> yield_continuations()[i]
- // } else ...
- //
- TargetEntryInstr* then;
- TargetEntryInstr* otherwise;
- dispatch += LoadLocal(scopes()->switch_variable);
- dispatch += IntConstant(i);
- dispatch += flow_graph_builder_->BranchIfStrictEqual(&then, &otherwise);
-
- // True branch is linked to appropriate continuation point.
- // Note: continuations start with nop DropTemps instruction
- // which acts like an anchor, so we need to skip it.
- then->LinkTo(yield_continuations()[i].entry->next());
- then->set_try_index(yield_continuations()[i].try_index);
- // False branch will contain the next comparison.
- dispatch = Fragment(dispatch.entry, otherwise);
- block = otherwise;
- }
- body = dispatch;
-
- flow_graph_builder_->context_depth_ = current_context_depth;
+ arg_values.SetAt((0 + kNumExtraArgs), argument);
+ const Array& args_descriptor =
+ Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, num_arguments,
+ Object::empty_array()));
+ const Object& result = Object::Handle(
+ Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
+ ASSERT(!result.IsError());
+ if (constructor.IsFactory()) {
+ // The factory method returns the allocated object.
+ instance ^= result.raw();
}
+ return H.Canonicalize(instance);
+}
- if (FLAG_causal_async_stacks &&
- (dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) {
- // The code we are building will be executed right after we enter
- // the function and before any nested contexts are allocated.
- // Reset current context_depth_ to match this.
- const intptr_t current_context_depth = flow_graph_builder_->context_depth_;
- flow_graph_builder_->context_depth_ =
- scopes()->yield_jump_variable->owner()->context_level();
-
- Fragment instructions;
- LocalScope* scope = parsed_function()->node_sequence()->scope();
-
- const Function& target = Function::ZoneHandle(
- Z, I->object_store()->async_set_thread_stack_trace());
- ASSERT(!target.IsNull());
-
- // Fetch and load :async_stack_trace
- LocalVariable* async_stack_trace_var =
- scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
- ASSERT((async_stack_trace_var != NULL) &&
- async_stack_trace_var->is_captured());
- instructions += LoadLocal(async_stack_trace_var);
- instructions += PushArgument();
-
- // Call _asyncSetThreadStackTrace
- instructions += StaticCall(TokenPosition::kNoSource, target, 1);
- instructions += Drop();
+const TypeArguments* StreamingConstantEvaluator::TranslateTypeArguments(
+ const Function& target,
+ dart::Class* target_klass) {
+ intptr_t types_count = builder_->ReadListLength(); // read types count.
- // TODO(29737): This sequence should be generated in order.
- body = instructions + body;
- flow_graph_builder_->context_depth_ = current_context_depth;
- }
-
- if (NeedsDebugStepCheck(dart_function, position)) {
- const intptr_t current_context_depth = flow_graph_builder_->context_depth_;
- flow_graph_builder_->context_depth_ = 0;
-
- // If a switch was added above: Start the switch by injecting a debuggable
- // safepoint so stepping over an await works.
- // If not, still start the body with a debuggable safepoint to ensure
- // breaking on a method always happens, even if there are no
- // assignments/calls/runtimecalls in the first basic block.
- // Place this check at the last parameter to ensure parameters
- // are in scope in the debugger at method entry.
- const int num_params = dart_function.NumParameters();
- TokenPosition check_pos = TokenPosition::kNoSource;
- if (num_params > 0) {
- LocalScope* scope = parsed_function()->node_sequence()->scope();
- const LocalVariable& parameter = *scope->VariableAt(num_params - 1);
- check_pos = parameter.token_pos();
- }
- if (!check_pos.IsDebugPause()) {
- // No parameters or synthetic parameters.
- check_pos = position;
- ASSERT(check_pos.IsDebugPause());
- }
+ const TypeArguments* type_arguments = NULL;
+ if (types_count > 0) {
+ type_arguments = &T.BuildInstantiatedTypeArguments(
+ *target_klass, types_count); // read types.
- // TODO(29737): This sequence should be generated in order.
- body = DebugStepCheck(check_pos) + body;
- flow_graph_builder_->context_depth_ = current_context_depth;
- }
-
- normal_entry->LinkTo(body.entry);
-
- // When compiling for OSR, use a depth first search to prune instructions
- // unreachable from the OSR entry. Catch entries are always considered
- // reachable, even if they become unreachable after OSR.
- if (flow_graph_builder_->osr_id_ != Compiler::kNoOSRDeoptId) {
- BitVector* block_marks =
- new (Z) BitVector(Z, flow_graph_builder_->next_block_id_);
- bool found = flow_graph_builder_->graph_entry_->PruneUnreachable(
- flow_graph_builder_->graph_entry_, NULL, flow_graph_builder_->osr_id_,
- block_marks);
- ASSERT(found);
- }
- return new (Z)
- FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
- flow_graph_builder_->next_block_id_ - 1);
-}
-
-Fragment StreamingFlowGraphBuilder::BuildGetMainClosure() {
- // _getMainClosure in dart:_builtin. Compile that one specially here.
- const dart::Library& builtin =
- dart::Library::Handle(Z, I->object_store()->builtin_library());
- const Object& main =
- Object::Handle(Z, builtin.LookupObjectAllowPrivate(dart::String::Handle(
- Z, dart::String::New("main"))));
- if (main.IsField()) {
- UNIMPLEMENTED();
- } else if (main.IsFunction()) {
- const Function& function = Function::Cast(main);
- if (function.kind() == RawFunction::kRegularFunction) {
- const Function& closure_function =
- Function::Handle(Z, function.ImplicitClosureFunction());
- const Instance& closure =
- Instance::ZoneHandle(Z, closure_function.ImplicitStaticClosure());
- return Constant(closure) + Return(TokenPosition::kNoSource);
- } else {
- UNIMPLEMENTED();
+ if (!(type_arguments->IsNull() || type_arguments->IsInstantiated())) {
+ H.ReportError("Type must be constant in const constructor.");
}
- } else {
- UNIMPLEMENTED();
+ } else if (target.IsFactory() && type_arguments == NULL) {
+ // All factories take a type arguments vector as first argument (independent
+ // of whether the class is generic or not).
+ type_arguments = &TypeArguments::ZoneHandle(Z, TypeArguments::null());
}
- return Fragment();
+ return type_arguments;
}
-FlowGraph* StreamingFlowGraphBuilder::BuildGraph(intptr_t kernel_offset) {
- const Function& function = parsed_function()->function();
+bool StreamingConstantEvaluator::EvaluateBooleanExpressionHere() {
+ EvaluateExpression(builder_->ReaderOffset(), false);
+ AssertBoolInCheckedMode();
+ return result_.raw() == Bool::True().raw();
+}
- // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
- // e.g. for type translation.
- const dart::Class& klass =
- dart::Class::Handle(zone_, parsed_function()->function().Owner());
- bool is_in_builtin_library_toplevel =
- klass.library() == I->object_store()->builtin_library() &&
- klass.IsTopLevel();
+bool StreamingConstantEvaluator::GetCachedConstant(intptr_t kernel_offset,
+ Instance* value) {
+ if (builder_ == NULL) return false;
- Function& outermost_function = Function::Handle(Z);
- intptr_t outermost_kernel_offset = -1;
- intptr_t parent_class_offset = -1;
- DiscoverEnclosingElements(Z, function, &outermost_function,
- &outermost_kernel_offset, &parent_class_offset);
- // Use [klass]/[kernel_class] as active class. Type parameters will get
- // resolved via [kernel_class] unless we are nested inside a static factory
- // in which case we will use [member].
- intptr_t class_type_parameters = 0;
- intptr_t class_type_parameters_offset_start = -1;
- if (parent_class_offset > 0) {
- GetTypeParameterInfoForClass(parent_class_offset, &class_type_parameters,
- &class_type_parameters_offset_start);
+ const Function& function = builder_->parsed_function()->function();
+ if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
+ // Don't cache constants in initializer expressions. They get
+ // evaluated only once.
+ return false;
}
- ActiveClassScope active_class_scope(active_class(), class_type_parameters,
- class_type_parameters_offset_start,
- &klass);
-
- bool member_is_procedure = false;
- bool is_factory_procedure = false;
- intptr_t member_type_parameters = 0;
- intptr_t member_type_parameters_offset_start = -1;
- GetTypeParameterInfoForPossibleProcedure(
- outermost_kernel_offset, &member_is_procedure, &is_factory_procedure,
- &member_type_parameters, &member_type_parameters_offset_start);
+ bool is_present = false;
+ ASSERT(!script_.InVMHeap());
+ if (script_.compile_time_constants() == Array::null()) {
+ return false;
+ }
+ KernelConstantsMap constants(script_.compile_time_constants());
+ *value ^= constants.GetOrNull(kernel_offset, &is_present);
+ // Mutator compiler thread may add constants while background compiler
+ // is running, and thus change the value of 'compile_time_constants';
+ // do not assert that 'compile_time_constants' has not changed.
+ constants.Release();
+ if (FLAG_compiler_stats && is_present) {
+ ++H.thread()->compiler_stats()->num_const_cache_hits;
+ }
+ return is_present;
+}
- ActiveMemberScope active_member(active_class(), member_is_procedure,
- is_factory_procedure, member_type_parameters,
- member_type_parameters_offset_start);
- // The IR builder will create its own local variables and scopes, and it
- // will not need an AST. The code generator will assume that there is a
- // local variable stack slot allocated for the current context and (I
- // think) that the runtime will expect it to be at a fixed offset which
- // requires allocating an unused expression temporary variable.
- set_scopes(parsed_function()->EnsureKernelScopes());
+void StreamingConstantEvaluator::CacheConstantValue(intptr_t kernel_offset,
+ const Instance& value) {
+ ASSERT(Thread::Current()->IsMutatorThread());
- SetOffset(kernel_offset);
+ if (builder_ == NULL) return;
- switch (function.kind()) {
- case RawFunction::kClosureFunction:
- case RawFunction::kRegularFunction:
- case RawFunction::kGetterFunction:
- case RawFunction::kSetterFunction: {
- ReadUntilFunctionNode(); // read until function node.
- return function.IsImplicitClosureFunction()
- ? BuildGraphOfImplicitClosureFunction(function)
- : BuildGraphOfFunction(is_in_builtin_library_toplevel);
- }
- case RawFunction::kConstructor: {
- bool is_factory = function.IsFactory();
- if (is_factory) {
- ReadUntilFunctionNode(); // read until function node.
- return BuildGraphOfFunction(is_in_builtin_library_toplevel);
- } else {
- // Constructor: Pass offset to parent class.
- return BuildGraphOfFunction(
- is_in_builtin_library_toplevel,
- ReadUntilFunctionNode()); // read until function node.
- }
- }
- case RawFunction::kImplicitGetter:
- case RawFunction::kImplicitStaticFinalGetter:
- case RawFunction::kImplicitSetter: {
- return IsStaticInitializer(function, Z)
- ? BuildGraphOfStaticFieldInitializer()
- : BuildGraphOfFieldAccessor(scopes()->setter_value);
- }
- case RawFunction::kMethodExtractor:
- return flow_graph_builder_->BuildGraphOfMethodExtractor(function);
- case RawFunction::kNoSuchMethodDispatcher:
- return flow_graph_builder_->BuildGraphOfNoSuchMethodDispatcher(function);
- case RawFunction::kInvokeFieldDispatcher:
- return flow_graph_builder_->BuildGraphOfInvokeFieldDispatcher(function);
- case RawFunction::kSignatureFunction:
- case RawFunction::kIrregexpFunction:
- break;
+ const Function& function = builder_->parsed_function()->function();
+ if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
+ // Don't cache constants in initializer expressions. They get
+ // evaluated only once.
+ return;
}
- UNREACHABLE();
- return NULL;
+ const intptr_t kInitialConstMapSize = 16;
+ ASSERT(!script_.InVMHeap());
+ if (script_.compile_time_constants() == Array::null()) {
+ const Array& array = Array::Handle(
+ HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew));
+ script_.set_compile_time_constants(array);
+ }
+ KernelConstantsMap constants(script_.compile_time_constants());
+ constants.InsertNewOrGetValue(kernel_offset, value);
+ script_.set_compile_time_constants(constants.Release());
}
+Fragment StreamingFlowGraphBuilder::BuildExpressionAt(intptr_t kernel_offset) {
+ SetOffset(kernel_offset);
+ return BuildExpression(); // read expression.
+}
+
Fragment StreamingFlowGraphBuilder::BuildStatementAt(intptr_t kernel_offset) {
SetOffset(kernel_offset);
return BuildStatement(); // read statement.
@@ -3674,7 +2770,9 @@ Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) {
case kConstMapLiteral:
return BuildMapLiteral(true, position);
case kFunctionExpression:
- return BuildFunctionExpression();
+ // TODO(jensj)
+ UNIMPLEMENTED();
+ return Fragment();
case kLet:
return BuildLet(position);
case kBigIntLiteral:
@@ -3746,7 +2844,9 @@ Fragment StreamingFlowGraphBuilder::BuildStatement() {
case kVariableDeclaration:
return BuildVariableDeclaration();
case kFunctionDeclaration:
- return BuildFunctionDeclaration();
+ // TODO(jensj)
+ UNIMPLEMENTED();
+ return Fragment();
default:
UNREACHABLE();
}
@@ -4261,7 +3361,6 @@ void StreamingFlowGraphBuilder::SkipFunctionNode() {
ReadByte(); // read async marker.
ReadByte(); // read dart async marker.
SkipTypeParametersList(); // read type_parameters.
- ReadUInt(); // read total parameter count.
ReadUInt(); // read required_parameter_count.
SkipListOfVariableDeclarations(); // read list of positionals.
@@ -4386,10 +3485,6 @@ ScopeBuildingResult* StreamingFlowGraphBuilder::scopes() {
return flow_graph_builder_->scopes_;
}
-void StreamingFlowGraphBuilder::set_scopes(ScopeBuildingResult* scope) {
- flow_graph_builder_->scopes_ = scope;
-}
-
ParsedFunction* StreamingFlowGraphBuilder::parsed_function() {
return flow_graph_builder_->parsed_function_;
}
@@ -5773,11 +4868,6 @@ Fragment StreamingFlowGraphBuilder::BuildMapLiteral(bool is_const,
return instructions + StaticCall(position, factory_method, 2);
}
-Fragment StreamingFlowGraphBuilder::BuildFunctionExpression() {
- intptr_t offset = ReaderOffset() - 1; // -1 to include tag byte.
- return BuildFunctionNode(offset, TokenPosition::kNoSource, false, -1);
-}
-
Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition* position) {
if (position != NULL) *position = TokenPosition::kNoSource;
@@ -6785,372 +5875,6 @@ Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
return instructions;
}
-Fragment StreamingFlowGraphBuilder::BuildFunctionDeclaration() {
- intptr_t offset = ReaderOffset() - 1; // -1 to include tag byte.
- TokenPosition position = ReadPosition(); // read position.
- intptr_t variable_offeset = ReaderOffset();
- SkipVariableDeclaration(); // read variable declaration.
-
- Fragment instructions = DebugStepCheck(position);
- instructions += BuildFunctionNode(offset, position, true, variable_offeset);
- instructions += StoreLocal(position, LookupVariable(variable_offeset));
- instructions += Drop();
- return instructions;
-}
-
-Fragment StreamingFlowGraphBuilder::BuildFunctionNode(
- intptr_t parent_kernel_offset,
- TokenPosition parent_position,
- bool declaration,
- intptr_t variable_offeset) {
- intptr_t offset = ReaderOffset();
-
- TokenPosition position;
- TokenPosition end_position;
- word async_marker_word;
- word dart_async_marker_word;
- ReadFunctionNodeUntilTypeParameters(
- &position, &end_position, &async_marker_word,
- &dart_async_marker_word); // read first part of function node.
- FunctionNode::AsyncMarker async_marker =
- static_cast<FunctionNode::AsyncMarker>(async_marker_word);
- FunctionNode::AsyncMarker dart_async_marker =
- static_cast<FunctionNode::AsyncMarker>(dart_async_marker_word);
-
- if (declaration) {
- position = parent_position;
- }
- if (!position.IsReal()) {
- // Positions has to be unique in regards to the parent.
- // A non-real at this point is probably -1, we cannot blindly use that
- // as others might use it too. Create a new dummy non-real TokenPosition.
- position = TokenPosition(offset).ToSynthetic();
- }
-
- SkipTypeParametersList(); // read type parameters.
-
- // The VM has a per-isolate table of functions indexed by the enclosing
- // function and token position.
- Function& function = Function::ZoneHandle(Z);
- bool read_rest_of_function_node = false;
-
- // NOTE: This is not TokenPosition in the general sense!
- function = I->LookupClosureFunction(parsed_function()->function(), position);
- if (function.IsNull()) {
- for (intptr_t i = 0; i < scopes()->function_scopes.length(); ++i) {
- if (scopes()->function_scopes[i].kernel_offset != offset) {
- continue;
- }
-
- const dart::String* name;
- if (!declaration) {
- name = &Symbols::AnonymousClosure();
- } else {
- name = &H.DartSymbol(GetNameFromVariableDeclaration(variable_offeset));
- }
- // NOTE: This is not TokenPosition in the general sense!
- function = Function::NewClosureFunction(
- *name, parsed_function()->function(), position);
-
- function.set_is_debuggable(dart_async_marker == FunctionNode::kSync);
- switch (dart_async_marker) {
- case FunctionNode::kSyncStar:
- function.set_modifier(RawFunction::kSyncGen);
- break;
- case FunctionNode::kAsync:
- function.set_modifier(RawFunction::kAsync);
- function.set_is_inlinable(!FLAG_causal_async_stacks);
- break;
- case FunctionNode::kAsyncStar:
- function.set_modifier(RawFunction::kAsyncGen);
- function.set_is_inlinable(!FLAG_causal_async_stacks);
- break;
- default:
- // no special modifier
- break;
- }
- function.set_is_generated_body(async_marker ==
- FunctionNode::kSyncYielding);
- if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
- function.set_is_inlinable(!FLAG_causal_async_stacks);
- }
-
- function.set_end_token_pos(end_position);
- LocalScope* scope = scopes()->function_scopes[i].scope;
- const ContextScope& context_scope = ContextScope::Handle(
- Z, scope->PreserveOuterScope(flow_graph_builder_->context_depth_));
- function.set_context_scope(context_scope);
- function.set_kernel_offset(offset);
- // Read rest of function node.
- SetupFunctionParameters(dart::Class::Handle(Z), function,
- false, // is_method
- true); // is_closure
- read_rest_of_function_node = true;
- // Finalize function type.
- Type& signature_type = Type::Handle(Z, function.SignatureType());
- signature_type ^=
- ClassFinalizer::FinalizeType(*active_class()->klass, signature_type);
- function.SetSignatureType(signature_type);
-
- I->AddClosureFunction(function);
- break;
- }
- }
-
- if (!read_rest_of_function_node) {
- ReadUInt(); // read total parameter count.
- ReadUInt(); // read required_parameter_count.
- SkipListOfVariableDeclarations(); // read list of positionals.
- SkipListOfVariableDeclarations(); // read list of named.
- SkipDartType(); // read return type.
- if (ReadTag() == kSomething) { // read first part of body.
- SkipStatement(); // read body.
- }
- }
-
- const dart::Class& closure_class =
- dart::Class::ZoneHandle(Z, I->object_store()->closure_class());
- ASSERT(!closure_class.IsNull());
- Fragment instructions =
- flow_graph_builder_->AllocateObject(closure_class, function);
- LocalVariable* closure = MakeTemporary();
-
- // The function signature can have uninstantiated class type parameters.
- //
- // TODO(regis): Also handle the case of a function signature that has
- // uninstantiated function type parameters.
- if (!function.HasInstantiatedSignature(kCurrentClass)) {
- instructions += LoadLocal(closure);
- instructions += LoadInstantiatorTypeArguments();
- instructions += flow_graph_builder_->StoreInstanceField(
- TokenPosition::kNoSource,
- Closure::instantiator_type_arguments_offset());
- }
-
- // Store the function and the context in the closure.
- instructions += LoadLocal(closure);
- instructions += Constant(function);
- instructions += flow_graph_builder_->StoreInstanceField(
- TokenPosition::kNoSource, Closure::function_offset());
-
- instructions += LoadLocal(closure);
- instructions += LoadLocal(parsed_function()->current_context_var());
- instructions += flow_graph_builder_->StoreInstanceField(
- TokenPosition::kNoSource, Closure::context_offset());
-
- return instructions;
-}
-
-
-void StreamingFlowGraphBuilder::SetupFunctionParameters(
- const dart::Class& klass,
- const dart::Function& function,
- bool is_method,
- bool is_closure) {
- ASSERT(!(is_method && is_closure));
- bool is_factory = function.IsFactory();
- intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0;
-
- intptr_t total_parameter_count = ReadUInt(); // read total parameter count.
- intptr_t required_parameter_count =
- ReadUInt(); // read required_parameter_count.
- intptr_t positional_parameters_count = ReadListLength(); // read list length.
- intptr_t named_parameters_count =
- total_parameter_count - positional_parameters_count;
-
- function.set_num_fixed_parameters(extra_parameters +
- required_parameter_count);
- if (named_parameters_count > 0) {
- function.SetNumOptionalParameters(named_parameters_count, false);
- } else {
- function.SetNumOptionalParameters(
- positional_parameters_count - required_parameter_count, true);
- }
- intptr_t num_parameters = extra_parameters + total_parameter_count;
- function.set_parameter_types(
- Array::Handle(Z, Array::New(num_parameters, Heap::kOld)));
- function.set_parameter_names(
- Array::Handle(Z, Array::New(num_parameters, Heap::kOld)));
- intptr_t pos = 0;
- if (is_method) {
- ASSERT(!klass.IsNull());
- function.SetParameterTypeAt(pos, H.GetCanonicalType(klass));
- function.SetParameterNameAt(pos, Symbols::This());
- pos++;
- } else if (is_closure) {
- function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
- function.SetParameterNameAt(pos, Symbols::ClosureParameter());
- pos++;
- } else if (is_factory) {
- function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
- function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter());
- pos++;
- }
-
- for (intptr_t i = 0; i < positional_parameters_count; ++i, ++pos) {
- // Read ith variable declaration.
- ReadPosition(); // read position.
- ReadPosition(); // read equals position.
- ReadFlags(); // read flags.
- StringIndex name = ReadStringReference(); // read name index.
- const AbstractType& type = T.BuildTypeWithoutFinalization(); // read type.
- Tag tag = ReadTag(); // read (first part of) initializer.
- if (tag == kSomething) {
- SkipExpression(); // read (actual) initializer.
- }
-
- function.SetParameterTypeAt(
- pos, type.IsMalformed() ? Type::dynamic_type() : type);
- function.SetParameterNameAt(pos, H.DartSymbol(name));
- }
-
- intptr_t named_parameters_count_check =
- ReadListLength(); // read list length.
- ASSERT(named_parameters_count_check == named_parameters_count);
- for (intptr_t i = 0; i < named_parameters_count; ++i, ++pos) {
- // Read ith variable declaration.
- ReadPosition(); // read position.
- ReadPosition(); // read equals position.
- ReadFlags(); // read flags.
- StringIndex name = ReadStringReference(); // read name index.
- const AbstractType& type = T.BuildTypeWithoutFinalization(); // read type.
- Tag tag = ReadTag(); // read (first part of) initializer.
- if (tag == kSomething) {
- SkipExpression(); // read (actual) initializer.
- }
-
- function.SetParameterTypeAt(
- pos, type.IsMalformed() ? Type::dynamic_type() : type);
- function.SetParameterNameAt(pos, H.DartSymbol(name));
- }
-
- // The result type for generative constructors has already been set.
- if (!function.IsGenerativeConstructor()) {
- const AbstractType& return_type =
- T.BuildTypeWithoutFinalization(); // read return type.
- function.set_result_type(return_type.IsMalformed() ? Type::dynamic_type()
- : return_type);
- } else {
- SkipDartType(); // read return type.
- }
-
- if (ReadTag() == kSomething) { // read first part of body.
- SkipStatement(); // read body.
- }
-}
-
-RawObject* StreamingFlowGraphBuilder::BuildParameterDescriptor(
- intptr_t kernel_offset) {
- SetOffset(kernel_offset);
- ReadUntilFunctionNode(); // read until function node.
- ReadFunctionNodeUntilTypeParameters(
- &unused_tokenposition, &unused_tokenposition, &unused_word,
- &unused_word); // read first part of function node.
- SkipTypeParametersList(); // read type_parameters.
-
- intptr_t param_count = ReadUInt(); // read total parameter count.
- ReadUInt(); // read required_parameter_count.
- intptr_t positional_count = ReadListLength(); // read list length.
- intptr_t named_parameters_count = param_count - positional_count;
-
- const Array& param_descriptor = Array::Handle(
- Array::New(param_count * Parser::kParameterEntrySize, Heap::kOld));
- for (intptr_t i = 0; i < param_count; ++i) {
- const intptr_t entry_start = i * Parser::kParameterEntrySize;
-
- if (i == positional_count) {
- intptr_t named_parameters_count_check =
- ReadListLength(); // read list length.
- ASSERT(named_parameters_count_check == named_parameters_count);
- }
-
- // Read ith variable declaration.
- ReadPosition(); // read position.
- ReadPosition(); // read equals position.
- word flags = ReadFlags(); // read flags.
- bool is_final = (flags & VariableDeclaration::kFlagFinal) ==
- VariableDeclaration::kFlagFinal;
- param_descriptor.SetAt(entry_start + Parser::kParameterIsFinalOffset,
- is_final ? Bool::True() : Bool::False());
-
- SkipStringReference(); // read name index.
- SkipDartType(); // read type.
- Tag tag = ReadTag(); // read (first part of) initializer.
- if (tag == kSomething) {
- // this will (potentially) read the initializer, but reset the position.
- Instance& constant =
- constant_evaluator_.EvaluateExpression(ReaderOffset());
- SkipExpression(); // read (actual) initializer.
- param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
- constant);
- } else {
- param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
- Object::null_instance());
- }
-
- param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
- /* Issue(28434): Missing parameter metadata. */
- Object::null_instance());
- }
- return param_descriptor.raw();
-}
-
-RawObject* StreamingFlowGraphBuilder::EvaluateMetadata(intptr_t kernel_offset) {
- SetOffset(kernel_offset);
- const Tag tag = PeekTag();
-
- if (tag == kClass) {
- Tag tag = ReadTag(); // read tag.
- ASSERT(tag == kClass);
- SkipCanonicalNameReference(); // read canonical name reference.
- ReadPosition(); // read position.
- ReadByte(); // read is_abstract
- SkipStringReference(); // read name_index.
- ReadUInt(); // read source_uri_index.
- // SkipListOfExpressions(); // read annotations.
- } else if (tag == kProcedure) {
- Tag tag = ReadTag(); // read tag.
- ASSERT(tag == kProcedure);
- SkipCanonicalNameReference(); // read canonical name reference.
- ReadPosition(); // read position.
- ReadPosition(); // read end position.
- ReadByte(); // read kind.
- ReadFlags(); // read flags.
- ReadUInt(); // read parent class binary offset.
- SkipName(); // read name,
- ReadUInt(); // read source_uri_index.
- // SkipListOfExpressions(); // read annotations.
- } else if (tag == kField) {
- ReadFieldUntilAnnotation(&unused_nameindex, &unused_tokenposition,
- &unused_tokenposition, &unused_word,
- &unused_intptr);
- // SkipListOfExpressions(); // read annotations.
- } else if (tag == kConstructor) {
- Tag tag = ReadTag();
- ASSERT(tag == kConstructor);
- SkipCanonicalNameReference(); // read canonical name reference.
- ReadPosition(); // read position.
- ReadPosition(); // read end position.
- ReadFlags(); // read flags.
- ReadUInt(); // parent class binary offset.
- SkipName(); // read name.
- // SkipListOfExpressions(); // read annotations.
- } else {
- FATAL("No support for metadata on this type of kernel node\n");
- }
-
- intptr_t list_length = ReadListLength(); // read list length.
- const Array& metadata_values = Array::Handle(Z, Array::New(list_length));
- for (intptr_t i = 0; i < list_length; ++i) {
- // this will (potentially) read the expression, but reset the position.
- Instance& value = constant_evaluator_.EvaluateExpression(ReaderOffset());
- SkipExpression(); // read (actual) initializer.
- metadata_values.SetAt(i, value);
- }
-
- return metadata_values.raw();
-}
-
} // namespace kernel
} // namespace dart
« no previous file with comments | « runtime/vm/kernel_binary_flowgraph.h ('k') | runtime/vm/kernel_reader.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698