| 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 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1048 node->value()->Visit(&for_value); | 1048 node->value()->Visit(&for_value); |
| 1049 Append(for_value); | 1049 Append(for_value); |
| 1050 Value* return_value = for_value.value(); | 1050 Value* return_value = for_value.value(); |
| 1051 | 1051 |
| 1052 // Call to stub that checks whether the debugger is in single | 1052 // Call to stub that checks whether the debugger is in single |
| 1053 // step mode. This call must happen before the contexts are | 1053 // step mode. This call must happen before the contexts are |
| 1054 // unchained so that captured variables can be inspected. | 1054 // unchained so that captured variables can be inspected. |
| 1055 // No debugger check is done in native functions or for return | 1055 // No debugger check is done in native functions or for return |
| 1056 // statements for which there is no associated source position. | 1056 // statements for which there is no associated source position. |
| 1057 const Function& function = owner()->function(); | 1057 const Function& function = owner()->function(); |
| 1058 if (FLAG_support_debugger && node->token_pos().IsDebugPause() && | 1058 #if !defined(PRODUCT) |
| 1059 !function.is_native()) { | 1059 if (node->token_pos().IsDebugPause() && !function.is_native()) { |
| 1060 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), | 1060 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), |
| 1061 RawPcDescriptors::kRuntimeCall, | 1061 RawPcDescriptors::kRuntimeCall, |
| 1062 owner()->GetNextDeoptId())); | 1062 owner()->GetNextDeoptId())); |
| 1063 } | 1063 } |
| 1064 #endif |
| 1064 | 1065 |
| 1065 NestedContextAdjustment context_adjustment(owner(), owner()->context_level()); | 1066 NestedContextAdjustment context_adjustment(owner(), owner()->context_level()); |
| 1066 | 1067 |
| 1067 if (node->inlined_finally_list_length() > 0) { | 1068 if (node->inlined_finally_list_length() > 0) { |
| 1068 LocalVariable* temp = owner()->parsed_function().finally_return_temp_var(); | 1069 LocalVariable* temp = owner()->parsed_function().finally_return_temp_var(); |
| 1069 ASSERT(temp != NULL); | 1070 ASSERT(temp != NULL); |
| 1070 Do(BuildStoreLocal(*temp, return_value, node->token_pos())); | 1071 Do(BuildStoreLocal(*temp, return_value, node->token_pos())); |
| 1071 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 1072 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
| 1072 InlineBailout("EffectGraphVisitor::VisitReturnNode (exception)"); | 1073 InlineBailout("EffectGraphVisitor::VisitReturnNode (exception)"); |
| 1073 EffectGraphVisitor for_effect(owner()); | 1074 EffectGraphVisitor for_effect(owner()); |
| (...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2030 if (nested_loop.break_target() == NULL) { | 2031 if (nested_loop.break_target() == NULL) { |
| 2031 exit_ = for_test.CreateFalseSuccessor(); | 2032 exit_ = for_test.CreateFalseSuccessor(); |
| 2032 } else { | 2033 } else { |
| 2033 for_test.IfFalseGoto(nested_loop.break_target()); | 2034 for_test.IfFalseGoto(nested_loop.break_target()); |
| 2034 exit_ = nested_loop.break_target(); | 2035 exit_ = nested_loop.break_target(); |
| 2035 } | 2036 } |
| 2036 } | 2037 } |
| 2037 } | 2038 } |
| 2038 | 2039 |
| 2039 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { | 2040 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { |
| 2040 if (FLAG_support_debugger && owner()->function().is_debuggable()) { | 2041 #if !defined(PRODUCT) |
| 2042 if (owner()->function().is_debuggable()) { |
| 2041 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), | 2043 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), |
| 2042 RawPcDescriptors::kRuntimeCall, | 2044 RawPcDescriptors::kRuntimeCall, |
| 2043 owner()->GetNextDeoptId())); | 2045 owner()->GetNextDeoptId())); |
| 2044 } | 2046 } |
| 2047 #endif |
| 2045 | 2048 |
| 2046 NestedContextAdjustment context_adjustment(owner(), owner()->context_level()); | 2049 NestedContextAdjustment context_adjustment(owner(), owner()->context_level()); |
| 2047 | 2050 |
| 2048 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 2051 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
| 2049 EffectGraphVisitor for_effect(owner()); | 2052 EffectGraphVisitor for_effect(owner()); |
| 2050 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); | 2053 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); |
| 2051 Append(for_effect); | 2054 Append(for_effect); |
| 2052 if (!is_open()) return; | 2055 if (!is_open()) return; |
| 2053 } | 2056 } |
| 2054 | 2057 |
| (...skipping 1265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3320 } | 3323 } |
| 3321 | 3324 |
| 3322 void ValueGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) { | 3325 void ValueGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) { |
| 3323 Definition* load = BuildLoadLocal(node->local(), node->token_pos()); | 3326 Definition* load = BuildLoadLocal(node->local(), node->token_pos()); |
| 3324 ReturnDefinition(load); | 3327 ReturnDefinition(load); |
| 3325 } | 3328 } |
| 3326 | 3329 |
| 3327 // <Expression> ::= StoreLocal { local: LocalVariable | 3330 // <Expression> ::= StoreLocal { local: LocalVariable |
| 3328 // value: <Expression> } | 3331 // value: <Expression> } |
| 3329 void EffectGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) { | 3332 void EffectGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) { |
| 3333 #if !defined(PRODUCT) |
| 3330 // If the right hand side is an expression that does not contain | 3334 // If the right hand side is an expression that does not contain |
| 3331 // a safe point for the debugger to stop, add an explicit stub | 3335 // a safe point for the debugger to stop, add an explicit stub |
| 3332 // call. Exception: don't do this when assigning to or from internal | 3336 // call. Exception: don't do this when assigning to or from internal |
| 3333 // variables, or for generated code that has no source position. | 3337 // variables, or for generated code that has no source position. |
| 3334 if (FLAG_support_debugger) { | 3338 AstNode* rhs = node->value(); |
| 3335 AstNode* rhs = node->value(); | 3339 if (rhs->IsAssignableNode()) { |
| 3336 if (rhs->IsAssignableNode()) { | 3340 rhs = rhs->AsAssignableNode()->expr(); |
| 3337 rhs = rhs->AsAssignableNode()->expr(); | |
| 3338 } | |
| 3339 if ((rhs->IsLiteralNode() || rhs->IsLoadStaticFieldNode() || | |
| 3340 (rhs->IsLoadLocalNode() && | |
| 3341 !rhs->AsLoadLocalNode()->local().IsInternal()) || | |
| 3342 rhs->IsClosureNode()) && | |
| 3343 !node->local().IsInternal() && node->token_pos().IsDebugPause()) { | |
| 3344 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), | |
| 3345 RawPcDescriptors::kRuntimeCall, | |
| 3346 owner()->GetNextDeoptId())); | |
| 3347 } | |
| 3348 } | 3341 } |
| 3342 if ((rhs->IsLiteralNode() || rhs->IsLoadStaticFieldNode() || |
| 3343 (rhs->IsLoadLocalNode() && |
| 3344 !rhs->AsLoadLocalNode()->local().IsInternal()) || |
| 3345 rhs->IsClosureNode()) && |
| 3346 !node->local().IsInternal() && node->token_pos().IsDebugPause()) { |
| 3347 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), |
| 3348 RawPcDescriptors::kRuntimeCall, |
| 3349 owner()->GetNextDeoptId())); |
| 3350 } |
| 3351 #endif |
| 3349 | 3352 |
| 3350 ValueGraphVisitor for_value(owner()); | 3353 ValueGraphVisitor for_value(owner()); |
| 3351 node->value()->Visit(&for_value); | 3354 node->value()->Visit(&for_value); |
| 3352 Append(for_value); | 3355 Append(for_value); |
| 3353 Value* store_value = for_value.value(); | 3356 Value* store_value = for_value.value(); |
| 3354 if (Isolate::Current()->type_checks()) { | 3357 if (Isolate::Current()->type_checks()) { |
| 3355 store_value = | 3358 store_value = |
| 3356 BuildAssignableValue(node->value()->token_pos(), store_value, | 3359 BuildAssignableValue(node->value()->token_pos(), store_value, |
| 3357 node->local().type(), node->local().name()); | 3360 node->local().type(), node->local().name()); |
| 3358 } | 3361 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3423 Field::ZoneHandle(Z, node->field().Original()), token_pos)); | 3426 Field::ZoneHandle(Z, node->field().Original()), token_pos)); |
| 3424 LoadStaticFieldInstr* load = | 3427 LoadStaticFieldInstr* load = |
| 3425 new (Z) LoadStaticFieldInstr(field_value, token_pos); | 3428 new (Z) LoadStaticFieldInstr(field_value, token_pos); |
| 3426 ReturnDefinition(load); | 3429 ReturnDefinition(load); |
| 3427 } | 3430 } |
| 3428 | 3431 |
| 3429 Definition* EffectGraphVisitor::BuildStoreStaticField( | 3432 Definition* EffectGraphVisitor::BuildStoreStaticField( |
| 3430 StoreStaticFieldNode* node, | 3433 StoreStaticFieldNode* node, |
| 3431 bool result_is_needed, | 3434 bool result_is_needed, |
| 3432 TokenPosition token_pos) { | 3435 TokenPosition token_pos) { |
| 3433 if (FLAG_support_debugger) { | 3436 #if !defined(PRODUCT) |
| 3434 // If the right hand side is an expression that does not contain | 3437 // If the right hand side is an expression that does not contain |
| 3435 // a safe point for the debugger to stop, add an explicit stub | 3438 // a safe point for the debugger to stop, add an explicit stub |
| 3436 // call. | 3439 // call. |
| 3437 AstNode* rhs = node->value(); | 3440 AstNode* rhs = node->value(); |
| 3438 if (rhs->IsAssignableNode()) { | 3441 if (rhs->IsAssignableNode()) { |
| 3439 rhs = rhs->AsAssignableNode()->expr(); | 3442 rhs = rhs->AsAssignableNode()->expr(); |
| 3440 } | |
| 3441 if ((rhs->IsLiteralNode() || rhs->IsLoadLocalNode() || | |
| 3442 rhs->IsLoadStaticFieldNode() || rhs->IsClosureNode()) && | |
| 3443 node->token_pos().IsDebugPause()) { | |
| 3444 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), | |
| 3445 RawPcDescriptors::kRuntimeCall, | |
| 3446 owner()->GetNextDeoptId())); | |
| 3447 } | |
| 3448 } | 3443 } |
| 3444 if ((rhs->IsLiteralNode() || rhs->IsLoadLocalNode() || |
| 3445 rhs->IsLoadStaticFieldNode() || rhs->IsClosureNode()) && |
| 3446 node->token_pos().IsDebugPause()) { |
| 3447 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), |
| 3448 RawPcDescriptors::kRuntimeCall, |
| 3449 owner()->GetNextDeoptId())); |
| 3450 } |
| 3451 #endif |
| 3449 | 3452 |
| 3450 ValueGraphVisitor for_value(owner()); | 3453 ValueGraphVisitor for_value(owner()); |
| 3451 node->value()->Visit(&for_value); | 3454 node->value()->Visit(&for_value); |
| 3452 Append(for_value); | 3455 Append(for_value); |
| 3453 Value* store_value = NULL; | 3456 Value* store_value = NULL; |
| 3454 if (result_is_needed) { | 3457 if (result_is_needed) { |
| 3455 store_value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); | 3458 store_value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); |
| 3456 } else { | 3459 } else { |
| 3457 store_value = for_value.value(); | 3460 store_value = for_value.value(); |
| 3458 } | 3461 } |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3839 // Call _asyncSetThreadStackTrace | 3842 // Call _asyncSetThreadStackTrace |
| 3840 const intptr_t kTypeArgsLen = 0; | 3843 const intptr_t kTypeArgsLen = 0; |
| 3841 StaticCallInstr* call_async_set_thread_stack_trace = new (Z) | 3844 StaticCallInstr* call_async_set_thread_stack_trace = new (Z) |
| 3842 StaticCallInstr(node->token_pos().ToSynthetic(), | 3845 StaticCallInstr(node->token_pos().ToSynthetic(), |
| 3843 async_set_thread_stack_trace, kTypeArgsLen, | 3846 async_set_thread_stack_trace, kTypeArgsLen, |
| 3844 Object::null_array(), arguments, | 3847 Object::null_array(), arguments, |
| 3845 owner()->ic_data_array(), owner()->GetNextDeoptId()); | 3848 owner()->ic_data_array(), owner()->GetNextDeoptId()); |
| 3846 Do(call_async_set_thread_stack_trace); | 3849 Do(call_async_set_thread_stack_trace); |
| 3847 } | 3850 } |
| 3848 | 3851 |
| 3849 if (FLAG_support_debugger && is_top_level_sequence && | 3852 #if !defined(PRODUCT) |
| 3850 function.is_debuggable()) { | 3853 if (is_top_level_sequence && function.is_debuggable()) { |
| 3851 // Place a debug check at method entry to ensure breaking on a method always | 3854 // Place a debug check at method entry to ensure breaking on a method always |
| 3852 // happens, even if there are no assignments/calls/runtimecalls in the first | 3855 // happens, even if there are no assignments/calls/runtimecalls in the first |
| 3853 // basic block. Place this check at the last parameter to ensure parameters | 3856 // basic block. Place this check at the last parameter to ensure parameters |
| 3854 // are in scope in the debugger at method entry. | 3857 // are in scope in the debugger at method entry. |
| 3855 const int num_params = function.NumParameters(); | 3858 const int num_params = function.NumParameters(); |
| 3856 TokenPosition check_pos = TokenPosition::kNoSource; | 3859 TokenPosition check_pos = TokenPosition::kNoSource; |
| 3857 if (num_params > 0) { | 3860 if (num_params > 0) { |
| 3858 const LocalVariable& parameter = *scope->VariableAt(num_params - 1); | 3861 const LocalVariable& parameter = *scope->VariableAt(num_params - 1); |
| 3859 check_pos = parameter.token_pos(); | 3862 check_pos = parameter.token_pos(); |
| 3860 } | 3863 } |
| 3861 | 3864 |
| 3862 if (check_pos.IsNoSource() || (check_pos.Pos() < node->token_pos().Pos())) { | 3865 if (check_pos.IsNoSource() || (check_pos.Pos() < node->token_pos().Pos())) { |
| 3863 // No parameters or synthetic parameters, e.g. 'this'. | 3866 // No parameters or synthetic parameters, e.g. 'this'. |
| 3864 check_pos = node->token_pos(); | 3867 check_pos = node->token_pos(); |
| 3865 ASSERT(check_pos.IsDebugPause()); | 3868 ASSERT(check_pos.IsDebugPause()); |
| 3866 } | 3869 } |
| 3867 AddInstruction(new (Z) DebugStepCheckInstr( | 3870 AddInstruction(new (Z) DebugStepCheckInstr( |
| 3868 check_pos, RawPcDescriptors::kRuntimeCall, owner()->GetNextDeoptId())); | 3871 check_pos, RawPcDescriptors::kRuntimeCall, owner()->GetNextDeoptId())); |
| 3869 } | 3872 } |
| 3873 #endif |
| 3870 | 3874 |
| 3871 // This check may be deleted if the generated code is leaf. | 3875 // This check may be deleted if the generated code is leaf. |
| 3872 // Native functions don't need a stack check at entry. | 3876 // Native functions don't need a stack check at entry. |
| 3873 if (is_top_level_sequence && !function.is_native()) { | 3877 if (is_top_level_sequence && !function.is_native()) { |
| 3874 // Always allocate CheckOverflowInstr so that deopt-ids match regardless | 3878 // Always allocate CheckOverflowInstr so that deopt-ids match regardless |
| 3875 // if we inline or not. | 3879 // if we inline or not. |
| 3876 if (!function.IsImplicitGetterFunction() && | 3880 if (!function.IsImplicitGetterFunction() && |
| 3877 !function.IsImplicitSetterFunction()) { | 3881 !function.IsImplicitSetterFunction()) { |
| 3878 CheckStackOverflowInstr* check = new (Z) CheckStackOverflowInstr( | 3882 CheckStackOverflowInstr* check = new (Z) CheckStackOverflowInstr( |
| 3879 node->token_pos(), 0, owner()->GetNextDeoptId()); | 3883 node->token_pos(), 0, owner()->GetNextDeoptId()); |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4259 cls, Library::PrivateCoreLibName(Symbols::ThrowNew()), | 4263 cls, Library::PrivateCoreLibName(Symbols::ThrowNew()), |
| 4260 kTypeArgsLen, arguments->length(), Object::null_array())); | 4264 kTypeArgsLen, arguments->length(), Object::null_array())); |
| 4261 ASSERT(!func.IsNull()); | 4265 ASSERT(!func.IsNull()); |
| 4262 return new (Z) StaticCallInstr(token_pos, func, kTypeArgsLen, | 4266 return new (Z) StaticCallInstr(token_pos, func, kTypeArgsLen, |
| 4263 Object::null_array(), // No names. | 4267 Object::null_array(), // No names. |
| 4264 arguments, owner()->ic_data_array(), | 4268 arguments, owner()->ic_data_array(), |
| 4265 owner()->GetNextDeoptId()); | 4269 owner()->GetNextDeoptId()); |
| 4266 } | 4270 } |
| 4267 | 4271 |
| 4268 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { | 4272 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { |
| 4269 if (FLAG_support_debugger) { | 4273 #if !defined(PRODUCT) |
| 4270 if (node->exception()->IsLiteralNode() || | 4274 if (node->exception()->IsLiteralNode() || |
| 4271 node->exception()->IsLoadLocalNode() || | 4275 node->exception()->IsLoadLocalNode() || |
| 4272 node->exception()->IsLoadStaticFieldNode() || | 4276 node->exception()->IsLoadStaticFieldNode() || |
| 4273 node->exception()->IsClosureNode()) { | 4277 node->exception()->IsClosureNode()) { |
| 4274 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), | 4278 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), |
| 4275 RawPcDescriptors::kRuntimeCall, | 4279 RawPcDescriptors::kRuntimeCall, |
| 4276 owner()->GetNextDeoptId())); | 4280 owner()->GetNextDeoptId())); |
| 4277 } | |
| 4278 } | 4281 } |
| 4282 #endif |
| 4279 ValueGraphVisitor for_exception(owner()); | 4283 ValueGraphVisitor for_exception(owner()); |
| 4280 node->exception()->Visit(&for_exception); | 4284 node->exception()->Visit(&for_exception); |
| 4281 Append(for_exception); | 4285 Append(for_exception); |
| 4282 PushArgument(for_exception.value()); | 4286 PushArgument(for_exception.value()); |
| 4283 Instruction* instr = NULL; | 4287 Instruction* instr = NULL; |
| 4284 if (node->stacktrace() == NULL) { | 4288 if (node->stacktrace() == NULL) { |
| 4285 instr = new (Z) ThrowInstr(node->token_pos(), owner()->GetNextDeoptId()); | 4289 instr = new (Z) ThrowInstr(node->token_pos(), owner()->GetNextDeoptId()); |
| 4286 } else { | 4290 } else { |
| 4287 ValueGraphVisitor for_stack_trace(owner()); | 4291 ValueGraphVisitor for_stack_trace(owner()); |
| 4288 node->stacktrace()->Visit(&for_stack_trace); | 4292 node->stacktrace()->Visit(&for_stack_trace); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4409 ASSERT(type.HasResolvedTypeClass()); | 4413 ASSERT(type.HasResolvedTypeClass()); |
| 4410 const Class& type_class = Class::Handle(type.type_class()); | 4414 const Class& type_class = Class::Handle(type.type_class()); |
| 4411 // Bail if the type has any type parameters. | 4415 // Bail if the type has any type parameters. |
| 4412 if (type_class.IsGeneric()) return false; | 4416 if (type_class.IsGeneric()) return false; |
| 4413 | 4417 |
| 4414 // Finally a simple class for instance of checking. | 4418 // Finally a simple class for instance of checking. |
| 4415 return true; | 4419 return true; |
| 4416 } | 4420 } |
| 4417 | 4421 |
| 4418 } // namespace dart | 4422 } // namespace dart |
| OLD | NEW |