| 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/parser.h" | 5 #include "vm/parser.h" |
| 6 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
| 9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 // Parameter i will be at fp[kFirstLocalSlotFromFp - i] and local variable | 160 // Parameter i will be at fp[kFirstLocalSlotFromFp - i] and local variable |
| 161 // j will be at fp[kFirstLocalSlotFromFp - num_params - j]. | 161 // j will be at fp[kFirstLocalSlotFromFp - num_params - j]. |
| 162 first_parameter_index_ = kFirstLocalSlotFromFp; | 162 first_parameter_index_ = kFirstLocalSlotFromFp; |
| 163 first_stack_local_index_ = first_parameter_index_ - num_params; | 163 first_stack_local_index_ = first_parameter_index_ - num_params; |
| 164 num_copied_params_ = num_params; | 164 num_copied_params_ = num_params; |
| 165 } | 165 } |
| 166 | 166 |
| 167 // Allocate parameters and local variables, either in the local frame or | 167 // Allocate parameters and local variables, either in the local frame or |
| 168 // in the context(s). | 168 // in the context(s). |
| 169 LocalScope* context_owner = NULL; // No context needed yet. | 169 LocalScope* context_owner = NULL; // No context needed yet. |
| 170 bool found_captured_variables = false; |
| 170 int next_free_frame_index = | 171 int next_free_frame_index = |
| 171 scope->AllocateVariables(first_parameter_index_, | 172 scope->AllocateVariables(first_parameter_index_, |
| 172 num_params, | 173 num_params, |
| 173 first_stack_local_index_, | 174 first_stack_local_index_, |
| 174 scope, | 175 scope, |
| 175 &context_owner); | 176 &context_owner, |
| 177 &found_captured_variables); |
| 176 | 178 |
| 177 // If this function allocates context variables, but none of its enclosing | 179 // We save the entry context for a function when... |
| 178 // functions do, the context on entry is not linked as parent of the allocated | 180 // |
| 179 // context but saved on entry and restored on exit as to prevent memory leaks. | 181 // - some variable in the function is captured by nested functions, and |
| 180 // Add and allocate a local variable to this purpose. | 182 // - the function does not capture any variables from parent functions. |
| 181 if (context_owner != NULL) { | 183 // |
| 184 // We used to link to the parent context in these cases, but this |
| 185 // had the effect of unintentionally retaining parent contexts which |
| 186 // would never be accessed. By breaking the context chain at this |
| 187 // point, we allow these outer contexts to be collected. |
| 188 if (found_captured_variables) { |
| 182 const ContextScope& context_scope = | 189 const ContextScope& context_scope = |
| 183 ContextScope::Handle(function().context_scope()); | 190 ContextScope::Handle(function().context_scope()); |
| 184 if (context_scope.IsNull() || (context_scope.num_variables() == 0)) { | 191 if (context_scope.IsNull() || (context_scope.num_variables() == 0)) { |
| 192 // Allocate a local variable for saving the entry context. |
| 185 LocalVariable* context_var = | 193 LocalVariable* context_var = |
| 186 new LocalVariable(function().token_pos(), | 194 new LocalVariable(function().token_pos(), |
| 187 Symbols::SavedEntryContextVar(), | 195 Symbols::SavedEntryContextVar(), |
| 188 Type::ZoneHandle(Type::DynamicType())); | 196 Type::ZoneHandle(Type::DynamicType())); |
| 189 context_var->set_index(next_free_frame_index--); | 197 context_var->set_index(next_free_frame_index--); |
| 190 scope->AddVariable(context_var); | 198 scope->AddVariable(context_var); |
| 191 set_saved_entry_context_var(context_var); | 199 set_saved_entry_context_var(context_var); |
| 192 } | 200 } |
| 193 } | 201 } |
| 194 | 202 |
| (...skipping 10752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10947 void Parser::SkipQualIdent() { | 10955 void Parser::SkipQualIdent() { |
| 10948 ASSERT(IsIdentifier()); | 10956 ASSERT(IsIdentifier()); |
| 10949 ConsumeToken(); | 10957 ConsumeToken(); |
| 10950 if (CurrentToken() == Token::kPERIOD) { | 10958 if (CurrentToken() == Token::kPERIOD) { |
| 10951 ConsumeToken(); // Consume the kPERIOD token. | 10959 ConsumeToken(); // Consume the kPERIOD token. |
| 10952 ExpectIdentifier("identifier expected after '.'"); | 10960 ExpectIdentifier("identifier expected after '.'"); |
| 10953 } | 10961 } |
| 10954 } | 10962 } |
| 10955 | 10963 |
| 10956 } // namespace dart | 10964 } // namespace dart |
| OLD | NEW |