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

Unified Diff: runtime/vm/parser.cc

Issue 8271008: Set type argument vector at run time in instantiated closure objects. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 2 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/object.cc ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 415)
+++ runtime/vm/parser.cc (working copy)
@@ -838,10 +838,6 @@
ParseFormalParameterList(no_explicit_default_values, &func_params);
// Change the name of the parameter type to be the signature of the
// function type.
- // Note that the function type signature may involve parameters of a type
- // that is a type parameter of the enclosing class, so we parameterize the
- // signature with the type parameters of the enclosing class, if any.
- // TODO(regis): Revisit if this is not the right thing to do.
const bool is_static =
current_function().IsNull() || current_function().is_static();
const Function& signature_function = Function::Handle(
@@ -1130,6 +1126,15 @@
if (receiver == NULL) {
return new ImplicitStaticClosureNode(token_pos, implicit_closure_function);
} else {
+ // If we create an implicit instance closure from inside a closure of a
+ // parameterized class, make sure that the receiver is captured as
+ // instantiator.
+ if (current_block_->scope->function_level() > 0) {
+ const Class& signature_class = Class::Handle(func.signature_class());
+ if (signature_class.IsParameterized()) {
+ CaptureReceiver();
+ }
+ }
return new ImplicitInstanceClosureNode(token_pos,
implicit_closure_function,
receiver);
@@ -1601,10 +1606,10 @@
ParseInitializers(cls);
}
- if (current_block_->scope->function_level() > 0) {
+ if (FLAG_enable_type_checks &&
+ (current_block_->scope->function_level() > 0)) {
// We are parsing, but not compiling, a local function.
- // The instantiator may be required at run time for generic type checks or
- // allocation of generic types.
+ // The instantiator may be required at run time for generic type checks.
if (current_class().IsParameterized() &&
(!current_function().is_static() ||
current_function().IsInFactoryScope())) {
@@ -1612,9 +1617,7 @@
// (or implicit first parameter of an enclosing factory) is marked as
// captured if type checks are enabled, because they may access the
// receiver to instantiate types.
- if (FLAG_enable_type_checks) {
- CaptureReceiver();
- }
+ CaptureReceiver();
}
}
@@ -3378,22 +3381,28 @@
current_function(),
token_index_));
function.set_result_type(result_type);
+
+ // The function type does not need to be determined at compile time, unless
+ // the closure is assigned to a function variable and type checks are enabled.
+ // At run time, the function type is derived from the signature class of the
+ // closure function and from the type arguments of the instantiator.
+
LocalVariable* function_variable = NULL;
ParameterizedType& function_type = ParameterizedType::ZoneHandle();
if (variable_name != NULL) {
- // Add the function variable to the scope before parsing the function in
- // order to allow self reference from inside the function.
- // The type of the implicitly declared const variable is defined by the
- // local function signature class and the type arguments of the current
- // receiver (if in a non-static scope). However, the signature is not yet
- // known, since the formal parameter list is not parsed yet. Therefore, we
- // set the type to a new parameterized type to be patched after the actual
- // type is known. We temporarily use the class of the Function interface.
+ // Since the function type depends on the signature of the closure function,
+ // it cannot be determined before the formal parameter list of the closure
+ // function is parsed. Therefore, we set the function type to a new
+ // parameterized type to be patched after the actual type is known.
+ // We temporarily use the class of the Function interface.
const Class& unknown_signature_class = Class::Handle(
Type::Handle(Type::FunctionInterface()).type_class());
function_type = ParameterizedType::New(unknown_signature_class,
TypeArguments::Handle());
function_type.set_is_finalized(); // No real finalization needed.
+
+ // Add the function variable to the scope before parsing the function in
+ // order to allow self reference from inside the function.
function_variable = new LocalVariable(ident_pos,
*variable_name,
function_type);
@@ -3431,23 +3440,53 @@
// finalized.
ASSERT(current_class().is_finalized());
- if (function_variable != NULL) {
- ASSERT(function_variable->type().raw() == function_type.raw());
- // Patch the function variable type now that the signature is known.
+ // Make sure that the instantiator is captured.
+ if (signature_class.IsParameterized() &&
+ (current_block_->scope->function_level() > 0)) {
+ CaptureReceiver();
+ }
+
+ if (variable_name != NULL) {
+ // Patch the function type now that the signature is known.
// We need to create a new type for proper finalization, since the existing
// type is already marked as finalized.
- // TODO(regis): Set proper signature_type_arguments if in non-static scope
- // and if the signature involves generic types.
- const TypeArguments& signature_type_arguments = TypeArguments::Handle();
+ TypeArguments& signature_type_arguments = TypeArguments::Handle();
+ if (signature_class.IsParameterized()) {
+ const intptr_t num_type_params = signature_class.NumTypeParameters();
+ const Array& type_params = Array::Handle(
+ signature_class.type_parameters());
+ signature_type_arguments = TypeArguments::NewTypeArray(num_type_params);
+ String& type_param_name = String::Handle();
+ Type& type_param = Type::Handle();
+ for (int i = 0; i < num_type_params; i++) {
+ type_param_name ^= type_params.At(i);
+ type_param = Type::NewTypeParameter(i, type_param_name);
+ signature_type_arguments.SetTypeAt(i, type_param);
+ }
+ }
+ const ParameterizedType& actual_function_type = ParameterizedType::Handle(
+ ParameterizedType::New(signature_class, signature_type_arguments));
const String& errmsg = String::Handle(
- ClassFinalizer::FinalizeTypeWhileParsing(ParameterizedType::Handle(
- ParameterizedType::New(signature_class,
- signature_type_arguments))));
+ ClassFinalizer::FinalizeTypeWhileParsing(actual_function_type));
if (!errmsg.IsNull()) {
ErrorMsg(errmsg.ToCString());
}
+ // The call to ClassFinalizer::FinalizeTypeWhileParsing may have extended
+ // the vector of type arguments.
+ signature_type_arguments = actual_function_type.arguments();
+ ASSERT(signature_type_arguments.IsNull() ||
+ (signature_type_arguments.Length() ==
+ signature_class.NumTypeArguments()));
+ // The signature_class should not have changed.
+ ASSERT(actual_function_type.type_class() == signature_class.raw());
+
+ // Now patch the function type of the variable.
function_type.set_type_class(signature_class);
function_type.set_arguments(signature_type_arguments);
+
+ // The function variable type should have been patched above.
+ ASSERT((function_variable == NULL) ||
+ (function_variable->type().raw() == function_type.raw()));
}
// The code generator does not compile the closure function when visiting
« no previous file with comments | « runtime/vm/object.cc ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698