OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |