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

Unified Diff: runtime/vm/kernel_to_il.cc

Issue 2891053003: Add support for converted closures with explicit contexts to VM (Closed)
Patch Set: Created 3 years, 7 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
Index: runtime/vm/kernel_to_il.cc
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc
index 1130320dcf1afbdfa98ba157d685267494722cf6..63e590a1624d7d3e10586680aec4f44247192679 100644
--- a/runtime/vm/kernel_to_il.cc
+++ b/runtime/vm/kernel_to_il.cc
@@ -329,6 +329,7 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
switch (function.kind()) {
case RawFunction::kClosureFunction:
+ case RawFunction::kConvertedClosureFunction:
case RawFunction::kRegularFunction:
case RawFunction::kGetterFunction:
case RawFunction::kSetterFunction:
@@ -350,6 +351,9 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
Symbols::ClosureParameter(), AbstractType::dynamic_type());
variable->set_is_forced_stack();
scope_->InsertParameterAt(pos++, variable);
+ } else if (function.IsConvertedClosureFunction()) {
+ // Do nothing. The explicit context parameter is already included into
+ // the parameter list of the parent function.
} else if (!function.is_static()) {
// We use [is_static] instead of [IsStaticFunction] because the latter
// returns `false` for constructors.
@@ -384,10 +388,14 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
}
AddParameters(node, pos);
- // We generate a syntethic body for implicit closure functions - which
- // will forward the call to the real function.
+ // We generate a syntethic body for implicit closure functions and
+ // converted
+ // closure functions - which will forward the call to the real function.
// -> see BuildGraphOfImplicitClosureFunction
- if (!function.IsImplicitClosureFunction()) {
+ // -> see BuildGraphOfConvertedClosureFunction
+
+ if (!function.IsImplicitClosureFunction() &&
+ !function.IsConvertedClosureFunction()) {
// TODO(jensj): HACK: Push the begin token to after any parameters to
// avoid crash when breaking on definition line of async method in
// debugger. It seems that another scope needs to be added
@@ -3201,6 +3209,7 @@ FlowGraph* FlowGraphBuilder::BuildGraph() {
switch (function.kind()) {
case RawFunction::kClosureFunction:
+ case RawFunction::kConvertedClosureFunction:
case RawFunction::kRegularFunction:
case RawFunction::kGetterFunction:
case RawFunction::kSetterFunction: {
@@ -3209,10 +3218,13 @@ FlowGraph* FlowGraphBuilder::BuildGraph() {
: FunctionNode::Cast(node_);
ActiveFunctionScope active_function_scope(&active_class_,
kernel_function);
- return function.IsImplicitClosureFunction()
- ? BuildGraphOfImplicitClosureFunction(kernel_function,
- function)
- : BuildGraphOfFunction(kernel_function);
+ if (function.IsImplicitClosureFunction()) {
+ return BuildGraphOfImplicitClosureFunction(kernel_function, function);
+ } else if (function.IsConvertedClosureFunction()) {
+ return BuildGraphOfConvertedClosureFunction(kernel_function, function);
+ } else {
+ return BuildGraphOfFunction(kernel_function);
+ }
}
case RawFunction::kConstructor: {
bool is_factory = function.IsFactory();
@@ -4028,6 +4040,64 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
}
+// This method follows the logic similar to that of
+// FlowGraphBuilder::BuildGraphOfImplicitClosureFunction. For additional
+// details on converted closure functions, please, see the comment on the method
+// Function::ConvertedClosureFunction.
+FlowGraph* FlowGraphBuilder::BuildGraphOfConvertedClosureFunction(
+ FunctionNode* kernel_function,
+ const Function& function) {
+ const Function& target = Function::ZoneHandle(Z, function.parent_function());
+
+ TargetEntryInstr* normal_entry = BuildTargetEntry();
+ graph_entry_ = new (Z)
+ GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId);
+ SetupDefaultParameterValues(kernel_function);
+
+ Fragment body(normal_entry);
+ body += CheckStackOverflowInPrologue();
+
+ // Load all the arguments.
+ ASSERT(target.is_static());
+ // The first argument is the value that the target function is converted over.
+ // It is stored in the context field of the Closure class instance. The
+ // instance is passed as the first argument to the call.
+ body += LoadLocal(parsed_function_->node_sequence()->scope()->VariableAt(0));
+ body += LoadField(Closure::context_offset());
+ body += PushArgument();
+
+ // The rest of the parameters are the same for the method of the Closure class
+ // being invoked and the top-level target function.
+ intptr_t positional_argument_count =
+ kernel_function->positional_parameters().length();
+ for (intptr_t i = 1; i < positional_argument_count; i++) {
+ body +=
+ LoadLocal(LookupVariable(kernel_function->positional_parameters()[i]));
+ body += PushArgument();
+ }
+ intptr_t named_argument_count = kernel_function->named_parameters().length();
+ 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++) {
+ VariableDeclaration* variable = kernel_function->named_parameters()[i];
+ body += LoadLocal(LookupVariable(variable));
+ body += PushArgument();
+ argument_names.SetAt(i, H.DartSymbol(variable->name()));
+ }
+ }
+ // Forward them to the target.
+ intptr_t argument_count = positional_argument_count + named_argument_count;
+ body += StaticCall(TokenPosition::kNoSource, target, argument_count,
+ argument_names);
+
+ // Return the result.
+ body += Return(kernel_function->end_position());
+
+ return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
+}
+
+
FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher(
const Function& function) {
// This function is specialized for a receiver class, a method name, and
@@ -4731,6 +4801,11 @@ void DartTypeTranslator::VisitVoidType(VoidType* node) {
}
+void DartTypeTranslator::VisitVectorType(VectorType* node) {
+ result_ = Object::vector_type().raw();
+}
+
+
void DartTypeTranslator::VisitBottomType(BottomType* node) {
result_ =
dart::Class::Handle(Z, I->object_store()->null_class()).CanonicalType();
@@ -5659,6 +5734,89 @@ void FlowGraphBuilder::VisitRethrow(Rethrow* node) {
}
+void FlowGraphBuilder::VisitVectorCreation(VectorCreation* node) {
+ ASSERT(node->value() > 0);
jensj 2017/05/18 11:19:06 STREAM_EXPRESSION_IF_POSSIBLE(node); ? (the same f
Dmitry Stefantsov 2017/05/18 12:18:53 Yep, that explains why the code worked without the
+ Fragment instructions = AllocateContext(node->value());
+ fragment_ = instructions;
+}
+
+
+void FlowGraphBuilder::VisitVectorGet(VectorGet* node) {
+ Fragment instructions;
+
+ instructions += TranslateExpression(node->vector_expression());
+ instructions += LoadField(Context::variable_offset(node->index()));
+
+ fragment_ = instructions;
+}
+
+
+void FlowGraphBuilder::VisitVectorSet(VectorSet* node) {
+ Fragment instructions;
+
+ instructions += TranslateExpression(node->vector_expression());
+ instructions += TranslateExpression(node->value());
+ LocalVariable* result = MakeTemporary();
+
+ Value* value = Pop();
+ StoreInstanceFieldInstr* store = new (Z)
+ StoreInstanceFieldInstr(Context::variable_offset(node->index()), Pop(),
+ value, kNoStoreBarrier, TokenPosition::kNoSource);
+ instructions <<= store;
+
+ // Result of a vector-set operation is its rhs. It is useful, especially for
+ // assignment chains.
+ instructions += LoadLocal(result);
+
+ fragment_ = instructions;
+}
+
+
+void FlowGraphBuilder::VisitVectorCopy(VectorCopy* node) {
+ Fragment instructions;
+
+ instructions += TranslateExpression(node->vector_expression());
+ CloneContextInstr* clone_instruction =
+ new (Z) CloneContextInstr(TokenPosition::kNoSource, Pop());
+ instructions <<= clone_instruction;
+ Push(clone_instruction);
+
+ fragment_ = instructions;
+}
+
+
+void FlowGraphBuilder::VisitClosureCreation(ClosureCreation* node) {
+ Fragment instructions;
+
+ Function& function = Function::ZoneHandle(
+ Z, H.LookupStaticMethodByKernelProcedure(node->top_level_function()));
+ function = function.ConvertedClosureFunction();
+ ASSERT(!function.IsNull());
+
+ const dart::Class& closure_class =
+ dart::Class::ZoneHandle(Z, I->object_store()->closure_class());
+ instructions += AllocateObject(closure_class, function);
+ LocalVariable* closure = MakeTemporary();
+
+ instructions += TranslateExpression(node->context_vector());
+ LocalVariable* context = MakeTemporary();
+
+ instructions += LoadLocal(closure);
+ instructions += Constant(function);
+ instructions +=
+ StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
+
+ instructions += LoadLocal(closure);
+ instructions += LoadLocal(context);
+ instructions +=
+ StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
+
+ instructions += Drop();
+
+ fragment_ = instructions;
+}
+
+
Fragment FlowGraphBuilder::TranslateArguments(Arguments* node,
Array* argument_names) {
Fragment instructions;

Powered by Google App Engine
This is Rietveld 408576698