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 |