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

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 2207 matching lines...) Expand 10 before | Expand all | Expand 10 after
2218 2218
2219 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { 2219 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
2220 const Function& function = node->function(); 2220 const Function& function = node->function();
2221 2221
2222 if (function.IsImplicitStaticClosureFunction()) { 2222 if (function.IsImplicitStaticClosureFunction()) {
2223 const Instance& closure = 2223 const Instance& closure =
2224 Instance::ZoneHandle(function.ImplicitStaticClosure()); 2224 Instance::ZoneHandle(function.ImplicitStaticClosure());
2225 ReturnDefinition(new ConstantInstr(closure)); 2225 ReturnDefinition(new ConstantInstr(closure));
2226 return; 2226 return;
2227 } 2227 }
2228 if (function.IsNonImplicitClosureFunction()) { 2228 const bool is_implicit = function.IsImplicitInstanceClosureFunction();
2229 // The context scope may have already been set by the non-optimizing 2229 ASSERT(is_implicit || function.IsNonImplicitClosureFunction());
2230 // compiler. If it was not, set it here. 2230 // The context scope may have already been set by the non-optimizing
2231 if (function.context_scope() == ContextScope::null()) { 2231 // compiler. If it was not, set it here.
2232 const ContextScope& context_scope = ContextScope::ZoneHandle( 2232 if (function.context_scope() == ContextScope::null()) {
2233 node->scope()->PreserveOuterScope(owner()->context_level())); 2233 ASSERT(!is_implicit);
2234 ASSERT(!function.HasCode()); 2234 const ContextScope& context_scope = ContextScope::ZoneHandle(
2235 ASSERT(function.context_scope() == ContextScope::null()); 2235 node->scope()->PreserveOuterScope(owner()->context_level()));
2236 function.set_context_scope(context_scope); 2236 ASSERT(!function.HasCode());
2237 const Class& cls = Class::Handle( 2237 ASSERT(function.context_scope() == ContextScope::null());
2238 owner()->parsed_function()->function().Owner()); 2238 function.set_context_scope(context_scope);
2239 // The closure is now properly setup, add it to the lookup table. 2239 const Class& cls = Class::Handle(
2240 owner()->parsed_function()->function().Owner());
2241 // The closure is now properly setup, add it to the lookup table.
2240 #if DEBUG 2242 #if DEBUG
2241 const Function& found_func = Function::Handle( 2243 const Function& found_func = Function::Handle(
2242 cls.LookupClosureFunction(function.token_pos())); 2244 cls.LookupClosureFunction(function.token_pos()));
2243 ASSERT(found_func.IsNull() || 2245 ASSERT(found_func.IsNull() ||
2244 (found_func.token_pos() != function.token_pos()) || 2246 (found_func.token_pos() != function.token_pos()) ||
2245 // TODO(hausner): The following check should not be necessary. 2247 // TODO(hausner): The following check should not be necessary.
2246 // Since we only lookup based on the token_pos we can get 2248 // Since we only lookup based on the token_pos we can get
2247 // duplicate entries due to closurized and non-closurized parent 2249 // duplicate entries due to closurized and non-closurized parent
2248 // functions (see Parser::ParseFunctionStatement). 2250 // functions (see Parser::ParseFunctionStatement).
2249 // We need two ways to lookup in this cache: One way to cache the 2251 // We need two ways to lookup in this cache: One way to cache the
2250 // appropriate closure function and one way to find the functions 2252 // appropriate closure function and one way to find the functions
2251 // while debugging (we might need to set breakpoints in multiple 2253 // while debugging (we might need to set breakpoints in multiple
2252 // different function for a single token index.) 2254 // different function for a single token index.)
2253 (found_func.parent_function() != function.parent_function())); 2255 (found_func.parent_function() != function.parent_function()));
2254 #endif // DEBUG 2256 #endif // DEBUG
2255 cls.AddClosureFunction(function); 2257 cls.AddClosureFunction(function);
2256 } 2258 }
2257 ZoneGrowableArray<PushArgumentInstr*>* arguments = 2259 ZoneGrowableArray<PushArgumentInstr*>* arguments =
2258 new ZoneGrowableArray<PushArgumentInstr*>(2); 2260 new ZoneGrowableArray<PushArgumentInstr*>(1);
2259 ASSERT(function.context_scope() != ContextScope::null()); 2261 ASSERT(function.context_scope() != ContextScope::null());
2260 2262
2261 // The function type of a closure may have type arguments. In that case, 2263 // The function type of a closure may have type arguments. In that case,
2262 // pass the type arguments of the instantiator. 2264 // pass the type arguments of the instantiator.
2263 const Class& cls = Class::ZoneHandle(function.signature_class()); 2265 const Class& cls = Class::ZoneHandle(function.signature_class());
2264 ASSERT(!cls.IsNull()); 2266 ASSERT(!cls.IsNull());
2265 const bool requires_type_arguments = cls.NumTypeArguments() > 0; 2267 const bool requires_type_arguments = cls.NumTypeArguments() > 0;
2266 Value* type_arguments = NULL; 2268 Value* type_arguments = NULL;
2267 if (requires_type_arguments) { 2269 if (requires_type_arguments) {
2268 ASSERT(cls.type_arguments_field_offset() == 2270 ASSERT(cls.type_arguments_field_offset() ==
2269 Closure::type_arguments_offset()); 2271 Closure::type_arguments_offset());
2270 const Class& instantiator_class = Class::Handle( 2272 ASSERT(cls.instance_size() == Closure::InstanceSize());
2271 owner()->parsed_function()->function().Owner()); 2273 const Class& instantiator_class = Class::Handle(
2272 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), 2274 owner()->parsed_function()->function().Owner());
2273 instantiator_class, 2275 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
2274 NULL); 2276 instantiator_class,
2275 arguments->Add(PushArgument(type_arguments)); 2277 NULL);
2276 } 2278 arguments->Add(PushArgument(type_arguments));
2277 AllocateObjectInstr* alloc = new AllocateObjectInstr(node->token_pos(), 2279 }
2278 cls, 2280 AllocateObjectInstr* alloc = new AllocateObjectInstr(node->token_pos(),
2279 arguments); 2281 cls,
2280 alloc->set_closure_function(function); 2282 arguments);
2283 alloc->set_closure_function(function);
2281 2284
2282 // Create fake fields for function and context. Only the context field is 2285 // Create fake fields for function and context. Only the context field is
2283 // stored at the allocation to be used later when inlining a closure call. 2286 // stored at the allocation to be used later when inlining a closure call.
2284 const Field& function_field = 2287 const Field& function_field =
Ivan Posva 2014/02/26 05:16:02 In a separate CL we should make these singletons i
Florian Schneider 2014/02/26 11:46:07 I would just allocate one instance per compilation
Ivan Posva 2014/02/27 18:12:34 Florian, the code below is technically wrong. The
2285 Field::ZoneHandle( 2288 Field::ZoneHandle(
2286 Field::New(Symbols::ClosureFunctionField(), 2289 Field::New(Symbols::ClosureFunctionField(),
2287 false, // !static 2290 false, // !static
2288 false, // !final 2291 false, // !final
2289 false, // !const 2292 false, // !const
2290 alloc->cls(), 2293 alloc->cls(),
2291 0)); // No token position. 2294 0)); // No token position.
2292 function_field.SetOffset(Closure::function_offset()); 2295 function_field.SetOffset(Closure::function_offset());
2293 const Field& context_field = 2296 const Field& context_field =
2294 Field::ZoneHandle(Field::New( 2297 Field::ZoneHandle(Field::New(
2295 Symbols::ClosureContextField(), 2298 Symbols::ClosureContextField(),
2296 false, // !static 2299 false, // !static
2297 false, // !final 2300 false, // !final
2298 false, // !const 2301 false, // !const
2299 alloc->cls(), 2302 alloc->cls(),
2300 0)); // No token position. 2303 0)); // No token position.
2301 context_field.SetOffset(Closure::context_offset()); 2304 context_field.SetOffset(Closure::context_offset());
2302 alloc->set_context_field(context_field); 2305 alloc->set_context_field(context_field);
2303 2306
2304 Value* closure_val = Bind(alloc); 2307 Value* closure_val = Bind(alloc);
2305 { LocalVariable* tmp_var = EnterTempLocalScope(closure_val); 2308 { LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val);
2306 // Store function. 2309 // Store function.
2307 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var)); 2310 Value* closure_tmp_val = Bind(new LoadLocalInstr(*closure_tmp_var));
2308 Value* func_val = 2311 Value* func_val =
2309 Bind(new ConstantInstr(Function::ZoneHandle(function.raw()))); 2312 Bind(new ConstantInstr(Function::ZoneHandle(function.raw())));
2310 Do(new StoreInstanceFieldInstr(function_field, 2313 Do(new StoreInstanceFieldInstr(function_field,
2311 tmp_val, 2314 closure_tmp_val,
2312 func_val, 2315 func_val,
2313 kEmitStoreBarrier)); 2316 kEmitStoreBarrier));
2314 // Store current context. 2317 if (is_implicit) {
2315 tmp_val = Bind(new LoadLocalInstr(*tmp_var)); 2318 // Create new context containing the receiver.
2319 const intptr_t kNumContextVariables = 1; // The receiver.
2320 Value* allocated_context =
2321 Bind(new AllocateContextInstr(node->token_pos(),
2322 kNumContextVariables));
2323 { LocalVariable* context_tmp_var = EnterTempLocalScope(allocated_context);
2324 // First operand (receiver).
2325 ValueGraphVisitor for_receiver(owner());
2326 node->receiver()->Visit(&for_receiver);
2327 Append(for_receiver);
2328 Value* receiver = for_receiver.value();
2329
2330 // Second operand (context).
2331 Value* context_tmp_val = Bind(new LoadLocalInstr(*context_tmp_var));
2332
2333 // Store receiver in context.
2334 Do(new StoreVMFieldInstr(context_tmp_val,
2335 Context::variable_offset(0),
2336 receiver,
2337 Type::ZoneHandle()));
2338 // Store new context in closure.
2339 closure_tmp_val = Bind(new LoadLocalInstr(*closure_tmp_var));
2340 context_tmp_val = Bind(new LoadLocalInstr(*context_tmp_var));
2341 Do(new StoreInstanceFieldInstr(context_field,
2342 closure_tmp_val,
2343 context_tmp_val,
2344 kEmitStoreBarrier));
2345 Do(ExitTempLocalScope(context_tmp_var));
2346 }
2347 } else {
2348 // Store current context in closure.
2349 closure_tmp_val = Bind(new LoadLocalInstr(*closure_tmp_var));
2316 Value* context = Bind(new CurrentContextInstr()); 2350 Value* context = Bind(new CurrentContextInstr());
2317 Do(new StoreInstanceFieldInstr(context_field, 2351 Do(new StoreInstanceFieldInstr(context_field,
2318 tmp_val, 2352 closure_tmp_val,
2319 context, 2353 context,
2320 kEmitStoreBarrier)); 2354 kEmitStoreBarrier));
2321 ReturnDefinition(ExitTempLocalScope(tmp_var));
2322 } 2355 }
2323 } else { 2356 ReturnDefinition(ExitTempLocalScope(closure_tmp_var));
2324 ASSERT(function.IsImplicitInstanceClosureFunction());
2325 ValueGraphVisitor for_receiver(owner());
2326 node->receiver()->Visit(&for_receiver);
2327 Append(for_receiver);
2328 Value* receiver = for_receiver.value();
2329
2330 PushArgumentInstr* push_receiver = PushArgument(receiver);
2331 ZoneGrowableArray<PushArgumentInstr*>* arguments =
2332 new ZoneGrowableArray<PushArgumentInstr*>(2);
2333 arguments->Add(push_receiver);
2334 ASSERT(function.context_scope() != ContextScope::null());
2335
2336 // The function type of a closure may have type arguments. In that case,
2337 // pass the type arguments of the instantiator. Otherwise, pass null object.
2338 const Class& cls = Class::Handle(function.signature_class());
2339 ASSERT(!cls.IsNull());
2340 const bool requires_type_arguments = cls.NumTypeArguments() > 0;
2341 Value* type_arguments = NULL;
2342 if (requires_type_arguments) {
2343 const Class& instantiator_class = Class::Handle(
2344 owner()->parsed_function()->function().Owner());
2345 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
2346 instantiator_class,
2347 NULL);
2348 } else {
2349 type_arguments = BuildNullValue();
2350 }
2351 PushArgumentInstr* push_type_arguments = PushArgument(type_arguments);
2352 arguments->Add(push_type_arguments);
2353 ReturnDefinition(
2354 new CreateClosureInstr(node->function(), arguments, node->token_pos()));
2355 } 2357 }
2356 } 2358 }
2357 2359
2358 2360
2359 void EffectGraphVisitor::BuildPushArguments( 2361 void EffectGraphVisitor::BuildPushArguments(
2360 const ArgumentListNode& node, 2362 const ArgumentListNode& node,
2361 ZoneGrowableArray<PushArgumentInstr*>* values) { 2363 ZoneGrowableArray<PushArgumentInstr*>* values) {
2362 for (intptr_t i = 0; i < node.length(); ++i) { 2364 for (intptr_t i = 0; i < node.length(); ++i) {
2363 ValueGraphVisitor for_argument(owner()); 2365 ValueGraphVisitor for_argument(owner());
2364 node.NodeAt(i)->Visit(&for_argument); 2366 node.NodeAt(i)->Visit(&for_argument);
(...skipping 1576 matching lines...) Expand 10 before | Expand all | Expand 10 after
3941 LanguageError::kError, 3943 LanguageError::kError,
3942 Heap::kNew, 3944 Heap::kNew,
3943 "FlowGraphBuilder Bailout: %s %s", 3945 "FlowGraphBuilder Bailout: %s %s",
3944 String::Handle(function.name()).ToCString(), 3946 String::Handle(function.name()).ToCString(),
3945 reason)); 3947 reason));
3946 Isolate::Current()->long_jump_base()->Jump(1, error); 3948 Isolate::Current()->long_jump_base()->Jump(1, error);
3947 } 3949 }
3948 3950
3949 3951
3950 } // namespace dart 3952 } // 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