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 |