OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../closure.dart'; | 7 import '../closure.dart'; |
8 import '../common.dart'; | 8 import '../common.dart'; |
9 import '../common/tasks.dart'; | 9 import '../common/tasks.dart'; |
10 import '../elements/elements.dart'; | 10 import '../elements/elements.dart'; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 /// closure semantics in JS. If this closure captures any variables (meaning | 127 /// closure semantics in JS. If this closure captures any variables (meaning |
128 /// the closure accesses a variable that gets accessed at some point), then | 128 /// the closure accesses a variable that gets accessed at some point), then |
129 /// boxForCapturedVariables stores the local context for those variables. | 129 /// boxForCapturedVariables stores the local context for those variables. |
130 /// If no variables are captured, this parameter is null. | 130 /// If no variables are captured, this parameter is null. |
131 void _produceSyntheticElements( | 131 void _produceSyntheticElements( |
132 MemberEntity member, | 132 MemberEntity member, |
133 ir.TreeNode /* ir.Member | ir.FunctionNode */ node, | 133 ir.TreeNode /* ir.Member | ir.FunctionNode */ node, |
134 ScopeInfo info, | 134 ScopeInfo info, |
135 ClosedWorldRefiner closedWorldRefiner) { | 135 ClosedWorldRefiner closedWorldRefiner) { |
136 String name = _computeClosureName(node); | 136 String name = _computeClosureName(node); |
| 137 KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member); |
137 KernelClosureClass closureClass = new KernelClosureClass.fromScopeInfo( | 138 KernelClosureClass closureClass = new KernelClosureClass.fromScopeInfo( |
138 name, member.library, info, node.location); | 139 name, member.library, info, node.location, localsMap); |
139 | 140 |
140 Entity entity; | 141 Entity entity; |
141 if (node is ir.Member) { | 142 if (node is ir.Member) { |
142 entity = member; | 143 entity = member; |
143 } else { | 144 } else { |
144 assert(node is ir.FunctionNode); | 145 assert(node is ir.FunctionNode); |
145 KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member); | |
146 entity = localsMap.getLocalFunction(node.parent); | 146 entity = localsMap.getLocalFunction(node.parent); |
147 // We want the original declaration where that function is used to point | 147 // We want the original declaration where that function is used to point |
148 // to the correct closure class. | 148 // to the correct closure class. |
149 _closureRepresentationMap[closureClass.callMethod] = closureClass; | 149 _closureRepresentationMap[closureClass.callMethod] = closureClass; |
150 } | 150 } |
151 assert(entity != null); | 151 assert(entity != null); |
152 _closureRepresentationMap[entity] = closureClass; | 152 _closureRepresentationMap[entity] = closureClass; |
153 | 153 |
154 // Register that a new class has been created. | 154 // Register that a new class has been created. |
155 closedWorldRefiner.registerClosureClass(closureClass); | 155 closedWorldRefiner.registerClosureClass(closureClass); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 | 242 |
243 class KernelScopeInfo extends ScopeInfo { | 243 class KernelScopeInfo extends ScopeInfo { |
244 final Set<Local> localsUsedInTryOrSync; | 244 final Set<Local> localsUsedInTryOrSync; |
245 final Local thisLocal; | 245 final Local thisLocal; |
246 final Set<Local> boxedVariables; | 246 final Set<Local> boxedVariables; |
247 | 247 |
248 /// The set of variables that were defined in another scope, but are used in | 248 /// The set of variables that were defined in another scope, but are used in |
249 /// this scope. | 249 /// this scope. |
250 Set<ir.VariableDeclaration> freeVariables = new Set<ir.VariableDeclaration>(); | 250 Set<ir.VariableDeclaration> freeVariables = new Set<ir.VariableDeclaration>(); |
251 | 251 |
252 /// Used to map [freeVariables] to their corresponding locals. | 252 KernelScopeInfo(this.thisLocal) |
253 final KernelToLocalsMap localsMap; | |
254 | |
255 KernelScopeInfo(this.thisLocal, this.localsMap) | |
256 : localsUsedInTryOrSync = new Set<Local>(), | 253 : localsUsedInTryOrSync = new Set<Local>(), |
257 boxedVariables = new Set<Local>(); | 254 boxedVariables = new Set<Local>(); |
258 | 255 |
259 KernelScopeInfo.from(this.thisLocal, KernelScopeInfo info) | 256 KernelScopeInfo.from(this.thisLocal, KernelScopeInfo info) |
260 : localsUsedInTryOrSync = info.localsUsedInTryOrSync, | 257 : localsUsedInTryOrSync = info.localsUsedInTryOrSync, |
261 boxedVariables = info.boxedVariables, | 258 boxedVariables = info.boxedVariables; |
262 localsMap = info.localsMap; | |
263 | 259 |
264 KernelScopeInfo.withBoxedVariables( | 260 KernelScopeInfo.withBoxedVariables(this.boxedVariables, |
265 this.boxedVariables, | 261 this.localsUsedInTryOrSync, this.freeVariables, this.thisLocal); |
266 this.localsUsedInTryOrSync, | |
267 this.freeVariables, | |
268 this.localsMap, | |
269 this.thisLocal); | |
270 | 262 |
271 void forEachBoxedVariable(f(Local local, FieldEntity field)) { | 263 void forEachBoxedVariable(f(Local local, FieldEntity field)) { |
272 boxedVariables.forEach((Local l) { | 264 boxedVariables.forEach((Local l) { |
273 // TODO(efortuna): add FieldEntities as created. | 265 // TODO(efortuna): add FieldEntities as created. |
274 f(l, null); | 266 f(l, null); |
275 }); | 267 }); |
276 } | 268 } |
277 | 269 |
278 bool localIsUsedInTryOrSync(Local variable) => | 270 bool localIsUsedInTryOrSync(Local variable) => |
279 localsUsedInTryOrSync.contains(variable); | 271 localsUsedInTryOrSync.contains(variable); |
280 | 272 |
281 String toString() { | 273 String toString() { |
282 StringBuffer sb = new StringBuffer(); | 274 StringBuffer sb = new StringBuffer(); |
283 sb.write('this=$thisLocal,'); | 275 sb.write('this=$thisLocal,'); |
284 sb.write('localsUsedInTryOrSync={${localsUsedInTryOrSync.join(', ')}}'); | 276 sb.write('localsUsedInTryOrSync={${localsUsedInTryOrSync.join(', ')}}'); |
285 return sb.toString(); | 277 return sb.toString(); |
286 } | 278 } |
287 | 279 |
288 bool isBoxed(Local variable) => boxedVariables.contains(variable); | 280 bool isBoxed(Local variable) => boxedVariables.contains(variable); |
289 } | 281 } |
290 | 282 |
291 class KernelCapturedScope extends KernelScopeInfo implements CapturedScope { | 283 class KernelCapturedScope extends KernelScopeInfo implements CapturedScope { |
292 final Local context; | 284 final Local context; |
293 | 285 |
294 KernelCapturedScope( | 286 KernelCapturedScope( |
295 Set<Local> boxedVariables, | 287 Set<Local> boxedVariables, |
296 this.context, | 288 this.context, |
297 Set<Local> localsUsedInTryOrSync, | 289 Set<Local> localsUsedInTryOrSync, |
298 Set<ir.VariableDeclaration> freeVariables, | 290 Set<ir.VariableDeclaration> freeVariables, |
299 KernelToLocalsMap localsMap, | |
300 Local thisLocal) | 291 Local thisLocal) |
301 : super.withBoxedVariables(boxedVariables, localsUsedInTryOrSync, | 292 : super.withBoxedVariables( |
302 freeVariables, localsMap, thisLocal); | 293 boxedVariables, localsUsedInTryOrSync, freeVariables, thisLocal); |
303 | 294 |
304 bool get requiresContextBox => boxedVariables.isNotEmpty; | 295 bool get requiresContextBox => boxedVariables.isNotEmpty; |
305 } | 296 } |
306 | 297 |
307 class KernelCapturedLoopScope extends KernelCapturedScope | 298 class KernelCapturedLoopScope extends KernelCapturedScope |
308 implements CapturedLoopScope { | 299 implements CapturedLoopScope { |
309 final List<Local> boxedLoopVariables; | 300 final List<Local> boxedLoopVariables; |
310 | 301 |
311 KernelCapturedLoopScope( | 302 KernelCapturedLoopScope( |
312 Set<Local> boxedVariables, | 303 Set<Local> boxedVariables, |
313 this.boxedLoopVariables, | 304 this.boxedLoopVariables, |
314 Local context, | 305 Local context, |
315 Set<Local> localsUsedInTryOrSync, | 306 Set<Local> localsUsedInTryOrSync, |
316 Set<ir.VariableDeclaration> freeVariables, | 307 Set<ir.VariableDeclaration> freeVariables, |
317 KernelToLocalsMap localsMap, | |
318 Local thisLocal) | 308 Local thisLocal) |
319 : super(boxedVariables, context, localsUsedInTryOrSync, freeVariables, | 309 : super(boxedVariables, context, localsUsedInTryOrSync, freeVariables, |
320 localsMap, thisLocal); | 310 thisLocal); |
321 | 311 |
322 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty; | 312 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty; |
323 } | 313 } |
324 | 314 |
325 // TODO(johnniwinther): Add unittest for the computed [ClosureClass]. | 315 // TODO(johnniwinther): Add unittest for the computed [ClosureClass]. |
326 class KernelClosureClass extends KernelScopeInfo | 316 class KernelClosureClass extends KernelScopeInfo |
327 implements ClosureRepresentationInfo, JClass { | 317 implements ClosureRepresentationInfo, JClass { |
328 final ir.Location location; | 318 final ir.Location location; |
329 | 319 |
330 final String name; | 320 final String name; |
331 final JLibrary library; | 321 final JLibrary library; |
332 | 322 |
333 /// Index into the classData, classList and classEnvironment lists where this | 323 /// Index into the classData, classList and classEnvironment lists where this |
334 /// entity is stored in [JsToFrontendMapImpl]. | 324 /// entity is stored in [JsToFrontendMapImpl]. |
335 int classIndex; | 325 int classIndex; |
336 | 326 |
337 final Map<Local, JField> localToFieldMap = new Map<Local, JField>(); | 327 final Map<Local, JField> localToFieldMap = new Map<Local, JField>(); |
338 | 328 |
339 KernelClosureClass.fromScopeInfo( | 329 KernelClosureClass.fromScopeInfo(this.name, this.library, |
340 this.name, this.library, KernelScopeInfo info, this.location) | 330 KernelScopeInfo info, this.location, KernelToLocalsMap localsMap) |
341 : super.from(info.thisLocal, info) { | 331 : super.from(info.thisLocal, info) { |
342 // Make a corresponding field entity in this closure class for every single | 332 // Make a corresponding field entity in this closure class for every single |
343 // freeVariable in the KernelScopeInfo.freeVariable. | 333 // freeVariable in the KernelScopeInfo.freeVariable. |
344 int i = 0; | 334 int i = 0; |
345 for (ir.VariableDeclaration variable in info.freeVariables) { | 335 for (ir.VariableDeclaration variable in info.freeVariables) { |
346 // NOTE: This construction order may be slightly different than the | 336 // NOTE: This construction order may be slightly different than the |
347 // old Element version. The old version did all the boxed items and then | 337 // old Element version. The old version did all the boxed items and then |
348 // all the others. | 338 // all the others. |
349 Local capturedLocal = info.localsMap.getLocalVariable(variable); | 339 Local capturedLocal = localsMap.getLocalVariable(variable); |
350 if (info.isBoxed(capturedLocal)) { | 340 if (info.isBoxed(capturedLocal)) { |
351 // TODO(efortuna): Coming soon. | 341 // TODO(efortuna): Coming soon. |
352 } else { | 342 } else { |
353 localToFieldMap[capturedLocal] = new ClosureField( | 343 localToFieldMap[capturedLocal] = new ClosureField( |
354 _getClosureVariableName(capturedLocal.name, i), | 344 _getClosureVariableName(capturedLocal.name, i), |
355 this, | 345 this, |
356 variable.isConst, | 346 variable.isConst, |
357 variable.isFinal || variable.isConst); | 347 variable.isFinal || variable.isConst); |
358 // TODO(efortuna): These probably need to get registered somewhere. | 348 // TODO(efortuna): These probably need to get registered somewhere. |
359 } | 349 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 ClosureClassDefinition(this.cls, this.location); | 415 ClosureClassDefinition(this.cls, this.location); |
426 | 416 |
427 ClassKind get kind => ClassKind.closure; | 417 ClassKind get kind => ClassKind.closure; |
428 | 418 |
429 ir.Node get node => | 419 ir.Node get node => |
430 throw new UnsupportedError('ClosureClassDefinition.node for $cls'); | 420 throw new UnsupportedError('ClosureClassDefinition.node for $cls'); |
431 | 421 |
432 String toString() => | 422 String toString() => |
433 'ClosureClassDefinition(kind:$kind,cls:$cls,location:$location)'; | 423 'ClosureClassDefinition(kind:$kind,cls:$cls,location:$location)'; |
434 } | 424 } |
OLD | NEW |