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

Side by Side Diff: runtime/vm/flow_graph_builder.cc

Issue 178233003: Allocate instance closures similarly to regular closures, i.e. without a (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 10 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/code_generator.cc ('k') | runtime/vm/flow_graph_inliner.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/ast_printer.h" 8 #include "vm/ast_printer.h"
9 #include "vm/bit_vector.h" 9 #include "vm/bit_vector.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 2200 matching lines...) Expand 10 before | Expand all | Expand 10 after
2211 2211
2212 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { 2212 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
2213 const Function& function = node->function(); 2213 const Function& function = node->function();
2214 2214
2215 if (function.IsImplicitStaticClosureFunction()) { 2215 if (function.IsImplicitStaticClosureFunction()) {
2216 const Instance& closure = 2216 const Instance& closure =
2217 Instance::ZoneHandle(function.ImplicitStaticClosure()); 2217 Instance::ZoneHandle(function.ImplicitStaticClosure());
2218 ReturnDefinition(new ConstantInstr(closure)); 2218 ReturnDefinition(new ConstantInstr(closure));
2219 return; 2219 return;
2220 } 2220 }
2221 if (function.IsNonImplicitClosureFunction()) { 2221 const bool is_implicit = function.IsImplicitInstanceClosureFunction();
2222 // The context scope may have already been set by the non-optimizing 2222 ASSERT(is_implicit || function.IsNonImplicitClosureFunction());
2223 // compiler. If it was not, set it here. 2223 // The context scope may have already been set by the non-optimizing
2224 if (function.context_scope() == ContextScope::null()) { 2224 // compiler. If it was not, set it here.
2225 const ContextScope& context_scope = ContextScope::ZoneHandle( 2225 if (function.context_scope() == ContextScope::null()) {
2226 node->scope()->PreserveOuterScope(owner()->context_level())); 2226 ASSERT(!is_implicit);
2227 ASSERT(!function.HasCode()); 2227 const ContextScope& context_scope = ContextScope::ZoneHandle(
2228 ASSERT(function.context_scope() == ContextScope::null()); 2228 node->scope()->PreserveOuterScope(owner()->context_level()));
2229 function.set_context_scope(context_scope); 2229 ASSERT(!function.HasCode());
2230 const Class& cls = Class::Handle( 2230 ASSERT(function.context_scope() == ContextScope::null());
2231 owner()->parsed_function()->function().Owner()); 2231 function.set_context_scope(context_scope);
2232 // The closure is now properly setup, add it to the lookup table. 2232 const Class& cls = Class::Handle(
2233 owner()->parsed_function()->function().Owner());
2234 // The closure is now properly setup, add it to the lookup table.
2233 #if DEBUG 2235 #if DEBUG
2234 const Function& found_func = Function::Handle( 2236 const Function& found_func = Function::Handle(
2235 cls.LookupClosureFunction(function.token_pos())); 2237 cls.LookupClosureFunction(function.token_pos()));
2236 ASSERT(found_func.IsNull() || 2238 ASSERT(found_func.IsNull() ||
2237 (found_func.token_pos() != function.token_pos()) || 2239 (found_func.token_pos() != function.token_pos()) ||
2238 // TODO(hausner): The following check should not be necessary. 2240 // TODO(hausner): The following check should not be necessary.
2239 // Since we only lookup based on the token_pos we can get 2241 // Since we only lookup based on the token_pos we can get
2240 // duplicate entries due to closurized and non-closurized parent 2242 // duplicate entries due to closurized and non-closurized parent
2241 // functions (see Parser::ParseFunctionStatement). 2243 // functions (see Parser::ParseFunctionStatement).
2242 // We need two ways to lookup in this cache: One way to cache the 2244 // We need two ways to lookup in this cache: One way to cache the
2243 // appropriate closure function and one way to find the functions 2245 // appropriate closure function and one way to find the functions
2244 // while debugging (we might need to set breakpoints in multiple 2246 // while debugging (we might need to set breakpoints in multiple
2245 // different function for a single token index.) 2247 // different function for a single token index.)
2246 (found_func.parent_function() != function.parent_function())); 2248 (found_func.parent_function() != function.parent_function()));
2247 #endif // DEBUG 2249 #endif // DEBUG
2248 cls.AddClosureFunction(function); 2250 cls.AddClosureFunction(function);
2249 } 2251 }
2250 ZoneGrowableArray<PushArgumentInstr*>* arguments = 2252 ZoneGrowableArray<PushArgumentInstr*>* arguments =
2251 new ZoneGrowableArray<PushArgumentInstr*>(2); 2253 new ZoneGrowableArray<PushArgumentInstr*>(1);
2252 ASSERT(function.context_scope() != ContextScope::null()); 2254 ASSERT(function.context_scope() != ContextScope::null());
2253 2255
2254 // The function type of a closure may have type arguments. In that case, 2256 // The function type of a closure may have type arguments. In that case,
2255 // pass the type arguments of the instantiator. 2257 // pass the type arguments of the instantiator.
2256 const Class& cls = Class::ZoneHandle(function.signature_class()); 2258 const Class& cls = Class::ZoneHandle(function.signature_class());
2257 ASSERT(!cls.IsNull()); 2259 ASSERT(!cls.IsNull());
2258 const bool requires_type_arguments = cls.NumTypeArguments() > 0; 2260 const bool requires_type_arguments = cls.NumTypeArguments() > 0;
2259 Value* type_arguments = NULL; 2261 Value* type_arguments = NULL;
2260 if (requires_type_arguments) { 2262 if (requires_type_arguments) {
2261 ASSERT(cls.type_arguments_field_offset() == 2263 ASSERT(cls.type_arguments_field_offset() ==
2262 Closure::type_arguments_offset()); 2264 Closure::type_arguments_offset());
2263 const Class& instantiator_class = Class::Handle( 2265 ASSERT(cls.instance_size() == Closure::InstanceSize());
2264 owner()->parsed_function()->function().Owner()); 2266 const Class& instantiator_class = Class::Handle(
2265 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), 2267 owner()->parsed_function()->function().Owner());
2266 instantiator_class, 2268 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
2267 NULL); 2269 instantiator_class,
2268 arguments->Add(PushArgument(type_arguments)); 2270 NULL);
2269 } 2271 arguments->Add(PushArgument(type_arguments));
2270 AllocateObjectInstr* alloc = new AllocateObjectInstr(node->token_pos(), 2272 }
2271 cls, 2273 AllocateObjectInstr* alloc = new AllocateObjectInstr(node->token_pos(),
2272 arguments); 2274 cls,
2273 alloc->set_closure_function(function); 2275 arguments);
2276 alloc->set_closure_function(function);
2274 2277
2275 // Create fake fields for function and context. Only the context field is 2278 // Create fake fields for function and context. Only the context field is
2276 // stored at the allocation to be used later when inlining a closure call. 2279 // stored at the allocation to be used later when inlining a closure call.
2277 const Field& function_field = 2280 const Field& function_field =
2278 Field::ZoneHandle( 2281 Field::ZoneHandle(
2279 Field::New(Symbols::ClosureFunctionField(), 2282 Field::New(Symbols::ClosureFunctionField(),
2280 false, // !static 2283 false, // !static
2281 false, // !final 2284 false, // !final
2282 false, // !const 2285 false, // !const
2283 alloc->cls(), 2286 alloc->cls(),
2284 0)); // No token position. 2287 0)); // No token position.
2285 function_field.SetOffset(Closure::function_offset()); 2288 function_field.SetOffset(Closure::function_offset());
2286 const Field& context_field = 2289 const Field& context_field =
2287 Field::ZoneHandle(Field::New( 2290 Field::ZoneHandle(Field::New(
2288 Symbols::ClosureContextField(), 2291 Symbols::ClosureContextField(),
2289 false, // !static 2292 false, // !static
2290 false, // !final 2293 false, // !final
2291 false, // !const 2294 false, // !const
2292 alloc->cls(), 2295 alloc->cls(),
2293 0)); // No token position. 2296 0)); // No token position.
2294 context_field.SetOffset(Closure::context_offset()); 2297 context_field.SetOffset(Closure::context_offset());
2295 alloc->set_context_field(context_field); 2298 alloc->set_context_field(context_field);
2296 2299
2297 Value* closure_val = Bind(alloc); 2300 Value* closure_val = Bind(alloc);
2298 { LocalVariable* tmp_var = EnterTempLocalScope(closure_val); 2301 { LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val);
2299 // Store function. 2302 // Store function.
2300 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var)); 2303 Value* closure_tmp_val = Bind(new LoadLocalInstr(*closure_tmp_var));
2301 Value* func_val = 2304 Value* func_val =
2302 Bind(new ConstantInstr(Function::ZoneHandle(function.raw()))); 2305 Bind(new ConstantInstr(Function::ZoneHandle(function.raw())));
2303 Do(new StoreInstanceFieldInstr(function_field, 2306 Do(new StoreInstanceFieldInstr(function_field,
2304 tmp_val, 2307 closure_tmp_val,
2305 func_val, 2308 func_val,
2306 kEmitStoreBarrier)); 2309 kEmitStoreBarrier));
2307 // Store current context. 2310 if (is_implicit) {
2308 tmp_val = Bind(new LoadLocalInstr(*tmp_var)); 2311 // Create new context containing the receiver.
2312 const intptr_t kNumContextVariables = 1; // The receiver.
2313 Value* allocated_context =
2314 Bind(new AllocateContextInstr(node->token_pos(),
2315 kNumContextVariables));
2316 { LocalVariable* context_tmp_var = EnterTempLocalScope(allocated_context);
2317 // Store receiver in context.
2318 Value* context_tmp_val = Bind(new LoadLocalInstr(*context_tmp_var));
2319 ValueGraphVisitor for_receiver(owner());
2320 node->receiver()->Visit(&for_receiver);
2321 Append(for_receiver);
2322 Value* receiver = for_receiver.value();
2323 Do(new StoreInstanceFieldInstr(Context::variable_offset(0),
2324 context_tmp_val,
2325 receiver,
2326 kEmitStoreBarrier));
2327 // Store new context in closure.
2328 closure_tmp_val = Bind(new LoadLocalInstr(*closure_tmp_var));
2329 context_tmp_val = Bind(new LoadLocalInstr(*context_tmp_var));
2330 Do(new StoreInstanceFieldInstr(context_field,
2331 closure_tmp_val,
2332 context_tmp_val,
2333 kEmitStoreBarrier));
2334 Do(ExitTempLocalScope(context_tmp_var));
2335 }
2336 } else {
2337 // Store current context in closure.
2338 closure_tmp_val = Bind(new LoadLocalInstr(*closure_tmp_var));
2309 Value* context = Bind(new CurrentContextInstr()); 2339 Value* context = Bind(new CurrentContextInstr());
2310 Do(new StoreInstanceFieldInstr(context_field, 2340 Do(new StoreInstanceFieldInstr(context_field,
2311 tmp_val, 2341 closure_tmp_val,
2312 context, 2342 context,
2313 kEmitStoreBarrier)); 2343 kEmitStoreBarrier));
2314 ReturnDefinition(ExitTempLocalScope(tmp_var));
2315 } 2344 }
2316 } else { 2345 ReturnDefinition(ExitTempLocalScope(closure_tmp_var));
2317 ASSERT(function.IsImplicitInstanceClosureFunction());
2318 ValueGraphVisitor for_receiver(owner());
2319 node->receiver()->Visit(&for_receiver);
2320 Append(for_receiver);
2321 Value* receiver = for_receiver.value();
2322
2323 PushArgumentInstr* push_receiver = PushArgument(receiver);
2324 ZoneGrowableArray<PushArgumentInstr*>* arguments =
2325 new ZoneGrowableArray<PushArgumentInstr*>(2);
2326 arguments->Add(push_receiver);
2327 ASSERT(function.context_scope() != ContextScope::null());
2328
2329 // The function type of a closure may have type arguments. In that case,
2330 // pass the type arguments of the instantiator. Otherwise, pass null object.
2331 const Class& cls = Class::Handle(function.signature_class());
2332 ASSERT(!cls.IsNull());
2333 const bool requires_type_arguments = cls.NumTypeArguments() > 0;
2334 Value* type_arguments = NULL;
2335 if (requires_type_arguments) {
2336 const Class& instantiator_class = Class::Handle(
2337 owner()->parsed_function()->function().Owner());
2338 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
2339 instantiator_class,
2340 NULL);
2341 } else {
2342 type_arguments = BuildNullValue();
2343 }
2344 PushArgumentInstr* push_type_arguments = PushArgument(type_arguments);
2345 arguments->Add(push_type_arguments);
2346 ReturnDefinition(
2347 new CreateClosureInstr(node->function(), arguments, node->token_pos()));
2348 } 2346 }
2349 } 2347 }
2350 2348
2351 2349
2352 void EffectGraphVisitor::BuildPushArguments( 2350 void EffectGraphVisitor::BuildPushArguments(
2353 const ArgumentListNode& node, 2351 const ArgumentListNode& node,
2354 ZoneGrowableArray<PushArgumentInstr*>* values) { 2352 ZoneGrowableArray<PushArgumentInstr*>* values) {
2355 for (intptr_t i = 0; i < node.length(); ++i) { 2353 for (intptr_t i = 0; i < node.length(); ++i) {
2356 ValueGraphVisitor for_argument(owner()); 2354 ValueGraphVisitor for_argument(owner());
2357 node.NodeAt(i)->Visit(&for_argument); 2355 node.NodeAt(i)->Visit(&for_argument);
(...skipping 1563 matching lines...) Expand 10 before | Expand all | Expand 10 after
3921 LanguageError::kError, 3919 LanguageError::kError,
3922 Heap::kNew, 3920 Heap::kNew,
3923 "FlowGraphBuilder Bailout: %s %s", 3921 "FlowGraphBuilder Bailout: %s %s",
3924 String::Handle(function.name()).ToCString(), 3922 String::Handle(function.name()).ToCString(),
3925 reason)); 3923 reason));
3926 Isolate::Current()->long_jump_base()->Jump(1, error); 3924 Isolate::Current()->long_jump_base()->Jump(1, error);
3927 } 3925 }
3928 3926
3929 3927
3930 } // namespace dart 3928 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/code_generator.cc ('k') | runtime/vm/flow_graph_inliner.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698