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

Unified Diff: runtime/vm/flow_graph_builder.cc

Issue 2941643002: Check for a passed-in type argument vector in the prolog of generic functions. (Closed)
Patch Set: address review comments 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/dart_entry.cc ('k') | runtime/vm/flow_graph_compiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_builder.cc
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index e0e279513ee5fb8b9c5235ee4263df3145460bbe..aed1f6bb3b1d931840592d9edee0d83488cf30aa 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2482,7 +2482,7 @@ void EffectGraphVisitor::BuildPushTypeArguments(
Bind(new (Z) LoadLocalInstr(*node.type_args_var(), node.token_pos()));
} else {
const TypeArguments& type_args = node.type_arguments();
- ASSERT(!type_args.IsNull() &&
+ ASSERT(!type_args.IsNull() && type_args.IsCanonical() &&
(type_args.Length() == node.type_args_len()));
type_args_val =
BuildInstantiatedTypeArguments(node.token_pos(), type_args);
@@ -2551,6 +2551,7 @@ void ValueGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
if (node->is_conditional()) {
+ ASSERT(node->arguments()->type_args_len() == 0);
ValueGraphVisitor for_receiver(owner());
node->receiver()->Visit(&for_receiver);
Append(for_receiver);
@@ -2600,7 +2601,6 @@ void EffectGraphVisitor::BuildClosureCall(ClosureCallNode* node,
ZoneGrowableArray<PushArgumentInstr*>* arguments =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(
node->arguments()->LengthWithTypeArgs() + 1);
- BuildPushTypeArguments(*node->arguments(), arguments);
ValueGraphVisitor for_closure(owner());
node->closure()->Visit(&for_closure);
@@ -2608,6 +2608,7 @@ void EffectGraphVisitor::BuildClosureCall(ClosureCallNode* node,
Value* closure_value = for_closure.value();
LocalVariable* tmp_var = EnterTempLocalScope(closure_value);
+ BuildPushTypeArguments(*node->arguments(), arguments);
Value* closure_val =
Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos()));
PushArgumentInstr* push_closure = PushArgument(closure_val);
@@ -3896,6 +3897,78 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
}
}
+ // Load the passed-in type argument vector from the temporary stack slot,
+ // prepend the function type arguments of the generic parent function, and
+ // store it to the final location, possibly in the context.
+ if (FLAG_reify_generic_functions && is_top_level_sequence &&
+ function.IsGeneric()) {
+ const ParsedFunction& parsed_function = owner()->parsed_function();
+ LocalVariable* type_args_var = parsed_function.function_type_arguments();
+ ASSERT(type_args_var->owner() == scope);
+ LocalVariable* parent_type_args_var =
+ parsed_function.parent_type_arguments();
+ if (type_args_var->is_captured() || (parent_type_args_var != NULL)) {
+ // Create a temporary local describing the original position.
+ const String& temp_name = Symbols::TempParam();
+ LocalVariable* temp_local =
+ new (Z) LocalVariable(TokenPosition::kNoSource, // Token index.
+ TokenPosition::kNoSource, // Token index.
+ temp_name,
+ Object::dynamic_type()); // Type.
+ temp_local->set_index(parsed_function.first_stack_local_index());
+
+ // Mark this local as captured parameter so that the optimizer
+ // correctly handles these when compiling try-catch: Captured
+ // parameters are not in the stack environment, therefore they
+ // must be skipped when emitting sync-code in try-blocks.
+ temp_local->set_is_captured_parameter(true); // TODO(regis): Correct?
+
+ Value* type_args_val =
+ Bind(BuildLoadLocal(*temp_local, node->token_pos()));
+ if (parent_type_args_var != NULL) {
+ ASSERT(parent_type_args_var->owner() != scope);
+ // Call the runtime to concatenate both vectors.
+ ZoneGrowableArray<PushArgumentInstr*>* arguments =
+ new (Z) ZoneGrowableArray<PushArgumentInstr*>(3);
+ arguments->Add(PushArgument(type_args_val));
+ Value* parent_type_args_val =
+ Bind(BuildLoadLocal(*parent_type_args_var, node->token_pos()));
+ arguments->Add(PushArgument(parent_type_args_val));
+ Value* len_const = Bind(new (Z) ConstantInstr(
+ Smi::ZoneHandle(Z, Smi::New(function.NumTypeParameters() +
+ function.NumParentTypeParameters()))));
+ arguments->Add(PushArgument(len_const));
+ const Library& dart_internal =
+ Library::Handle(Z, Library::InternalLibrary());
+ const Function& prepend_function =
+ Function::ZoneHandle(Z, dart_internal.LookupFunctionAllowPrivate(
+ Symbols::PrependTypeArguments()));
+ ASSERT(!prepend_function.IsNull());
+ const intptr_t kTypeArgsLen = 0;
+ type_args_val = Bind(new (Z) StaticCallInstr(
+ node->token_pos(), prepend_function, kTypeArgsLen,
+ Object::null_array(), // No names.
+ arguments, owner()->ic_data_array(), owner()->GetNextDeoptId()));
+ }
+ Do(BuildStoreLocal(*type_args_var, type_args_val, ST(node->token_pos())));
+ if (type_args_var->is_captured()) {
+ // Write NULL to the source location to detect buggy accesses and
+ // allow GC of passed value if it gets overwritten by a new value in
+ // the function.
+ Value* null_constant =
+ Bind(new (Z) ConstantInstr(Object::ZoneHandle(Z, Object::null())));
+ Do(BuildStoreLocal(*temp_local, null_constant, ST(node->token_pos())));
+ } else {
+ // Do not write NULL, since the temp is also the final location.
+ ASSERT(temp_local->index() == type_args_var->index());
+ }
+ } else {
+ // The type args slot is the final location. No copy needed.
+ ASSERT(type_args_var->index() ==
+ parsed_function.first_stack_local_index());
+ }
+ }
+
if (FLAG_causal_async_stacks && is_top_level_sequence &&
(function.IsAsyncClosure() || function.IsAsyncGenClosure())) {
LocalScope* top_scope = node->scope();
« no previous file with comments | « runtime/vm/dart_entry.cc ('k') | runtime/vm/flow_graph_compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698