OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 // IrNodes are kept in a separate library to have precise control over their | 5 // IrNodes are kept in a separate library to have precise control over their |
6 // dependencies on other parts of the system. | 6 // dependencies on other parts of the system. |
7 library dart2js.ir_nodes; | 7 library dart2js.ir_nodes; |
8 | 8 |
9 import '../dart2jslib.dart' as dart2js show Constant, ConstructedConstant, | 9 import '../dart2jslib.dart' as dart2js show Constant, ConstructedConstant, |
10 StringConstant, ListConstant, MapConstant; | 10 StringConstant, ListConstant, MapConstant; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
42 do { | 42 do { |
43 current.definition = this; | 43 current.definition = this; |
44 previous = current; | 44 previous = current; |
45 current = current.nextRef; | 45 current = current.nextRef; |
46 } while (current != null); | 46 } while (current != null); |
47 previous.nextRef = firstRef; | 47 previous.nextRef = firstRef; |
48 firstRef = other.firstRef; | 48 firstRef = other.firstRef; |
49 } | 49 } |
50 } | 50 } |
51 | 51 |
52 /// A pure expression that cannot throw or diverge. | 52 /// An expression that cannot throw or diverge and has no side-effects. |
53 /// All primitives are named using the identity of the [Primitive] object. | 53 /// All primitives are named using the identity of the [Primitive] object. |
54 /// | |
55 /// Primitives may allocate objects, this is not considered side-effect here. | |
56 /// | |
57 /// Although primitives may not mutate state, they may depend on state. | |
54 abstract class Primitive extends Definition { | 58 abstract class Primitive extends Definition { |
55 /// The [VariableElement] or [ParameterElement] from which the primitive | 59 /// The [VariableElement] or [ParameterElement] from which the primitive |
56 /// binding originated. | 60 /// binding originated. |
57 Element element; | 61 Element hint; |
58 | 62 |
59 /// Register in which the variable binding this primitive can be allocated. | 63 /// Register in which the variable binding this primitive can be allocated. |
60 /// Separate register spaces are used for primitives with different [element]. | 64 /// Separate register spaces are used for primitives with different [element]. |
61 /// Assigned by [RegisterAllocator], is null before that phase. | 65 /// Assigned by [RegisterAllocator], is null before that phase. |
62 int registerIndex; | 66 int registerIndex; |
63 | 67 |
64 /// Use the given element as a hint for naming this primitive. | 68 /// Use the given element as a hint for naming this primitive. |
65 /// | 69 /// |
66 /// Has no effect if this primitive already has a non-null [element]. | 70 /// Has no effect if this primitive already has a non-null [element]. |
67 void useElementAsHint(Element hint) { | 71 void useElementAsHint(Element hint) { |
68 if (element == null) { | 72 if (this.hint == null) { |
69 element = hint; | 73 this.hint = hint; |
70 } | 74 } |
71 } | 75 } |
72 } | 76 } |
73 | 77 |
74 /// Operands to invocations and primitives are always variables. They point to | 78 /// Operands to invocations and primitives are always variables. They point to |
75 /// their definition and are linked into a list of occurrences. | 79 /// their definition and are linked into a list of occurrences. |
76 class Reference { | 80 class Reference { |
77 Definition definition; | 81 Definition definition; |
78 Reference nextRef = null; | 82 Reference nextRef = null; |
79 | 83 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 final Reference continuation; | 253 final Reference continuation; |
250 final List<Reference> arguments; | 254 final List<Reference> arguments; |
251 | 255 |
252 ConcatenateStrings(Continuation cont, List<Definition> args) | 256 ConcatenateStrings(Continuation cont, List<Definition> args) |
253 : continuation = new Reference(cont), | 257 : continuation = new Reference(cont), |
254 arguments = _referenceList(args); | 258 arguments = _referenceList(args); |
255 | 259 |
256 accept(Visitor visitor) => visitor.visitConcatenateStrings(this); | 260 accept(Visitor visitor) => visitor.visitConcatenateStrings(this); |
257 } | 261 } |
258 | 262 |
263 /// Gets the value from a closure variable. The identity of the variable is | |
264 /// determined by an [Element]. | |
265 /// | |
266 /// Closure variables can be seen as ref cells that are not first-class values. | |
267 /// A [LetPrim] with a [GetClosureVariable] can then be seen as: | |
268 /// | |
269 /// let prim p = ![variable] in [body] | |
270 /// | |
271 class GetClosureVariable extends Primitive { | |
272 final Element variable; | |
273 | |
274 GetClosureVariable(this.variable) { | |
275 assert(variable != null); | |
276 } | |
277 | |
278 accept(Visitor visitor) => visitor.visitGetClosureVariable(this); | |
279 } | |
280 | |
281 /// Assign or declare a closure variable. The identity of the variable is | |
282 /// determined by an [Element]. | |
283 /// | |
284 /// Closure variables can be seen as ref cells that are not first-class values. | |
285 /// If [isDeclaration], this can seen as a let binding: | |
286 /// | |
287 /// let [variable] = ref [value] in [body] | |
288 /// | |
289 /// And otherwise, it can be seen as a dereferencing assignment: | |
290 /// | |
291 /// { ![variable] := [value]; [body] } | |
292 /// | |
293 /// Closure variables without a declaring [SetClosureVariable] are implicitly | |
294 /// declared at the entry to the [variable]'s enclosing function. | |
295 class SetClosureVariable extends Expression { | |
296 final Element variable; | |
297 final Reference value; | |
298 Expression body; | |
299 | |
300 /// If true, this declares a new copy of the closure variable. If so, all | |
301 /// uses of the closure variable must occur in the [body]. | |
302 /// | |
303 /// There can be at most one declaration per closure variable. If there is no | |
304 /// declaration, only one copy exists (per function execution). It is best to | |
305 /// avoid declaring closure variables if it is not necessary. | |
306 final bool isDeclaration; | |
307 | |
308 SetClosureVariable(this.variable, Primitive value, | |
309 {this.isDeclaration : false }) | |
310 : this.value = new Reference(value) { | |
311 assert(variable != null); | |
312 } | |
313 | |
314 accept(Visitor visitor) => visitor.visitSetClosureVariable(this); | |
315 | |
316 Expression plug(Expression expr) { | |
317 assert(body == null); | |
318 return body = expr; | |
319 } | |
320 } | |
321 | |
322 /// Create a potentially recursive function and store it in a closure variable. | |
323 /// The function can access itself using [GetClosureVariable] on [variable]. | |
324 /// There may not exist a [SetClosureVariable] to [variable]. | |
sigurdm
2014/07/02 14:29:20
I guess it is clearer to write
/// There must not
asgerf
2014/07/02 14:35:32
You're right, thanks.
| |
325 /// | |
326 /// This can be seen as a let rec binding: | |
327 /// | |
328 /// let rec [variable] = [definition] in [body] | |
329 /// | |
330 class DeclareFunction extends Expression { | |
331 final Element variable; | |
332 final FunctionDefinition definition; | |
333 Expression body; | |
334 | |
335 DeclareFunction(this.variable, this.definition); | |
336 | |
337 Expression plug(Expression expr) { | |
338 assert(body == null); | |
339 return body = expr; | |
340 } | |
341 | |
342 accept(Visitor visitor) => visitor.visitDeclareFunction(this); | |
343 } | |
344 | |
259 /// Invoke a continuation in tail position. | 345 /// Invoke a continuation in tail position. |
260 class InvokeContinuation extends Expression { | 346 class InvokeContinuation extends Expression { |
261 final Reference continuation; | 347 final Reference continuation; |
262 final List<Reference> arguments; | 348 final List<Reference> arguments; |
263 | 349 |
264 // An invocation of a continuation is recursive if it occurs in the body of | 350 // An invocation of a continuation is recursive if it occurs in the body of |
265 // the continuation itself. | 351 // the continuation itself. |
266 bool isRecursive; | 352 bool isRecursive; |
267 | 353 |
268 InvokeContinuation(Continuation cont, List<Definition> args, | 354 InvokeContinuation(Continuation cont, List<Definition> args, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 | 398 |
313 class This extends Primitive { | 399 class This extends Primitive { |
314 This(); | 400 This(); |
315 | 401 |
316 accept(Visitor visitor) => visitor.visitThis(this); | 402 accept(Visitor visitor) => visitor.visitThis(this); |
317 } | 403 } |
318 | 404 |
319 /// Reify the given type variable as a [Type]. | 405 /// Reify the given type variable as a [Type]. |
320 /// This depends on the current binding of 'this'. | 406 /// This depends on the current binding of 'this'. |
321 class ReifyTypeVar extends Primitive { | 407 class ReifyTypeVar extends Primitive { |
322 final TypeVariableElement element; | 408 final TypeVariableElement typeVariable; |
323 | 409 |
324 ReifyTypeVar(this.element); | 410 ReifyTypeVar(this.typeVariable); |
325 | 411 |
326 dart2js.Constant get constant => null; | 412 dart2js.Constant get constant => null; |
327 | 413 |
328 accept(Visitor visitor) => visitor.visitReifyTypeVar(this); | 414 accept(Visitor visitor) => visitor.visitReifyTypeVar(this); |
329 } | 415 } |
330 | 416 |
331 class LiteralList extends Primitive { | 417 class LiteralList extends Primitive { |
332 /// The List type being created; this is not the type argument. | 418 /// The List type being created; this is not the type argument. |
333 final GenericType type; | 419 final GenericType type; |
334 final List<Reference> values; | 420 final List<Reference> values; |
335 | 421 |
336 LiteralList(this.type, List<Primitive> values) | 422 LiteralList(this.type, List<Primitive> values) |
337 : this.values = _referenceList(values); | 423 : this.values = _referenceList(values); |
338 | 424 |
339 accept(Visitor visitor) => visitor.visitLiteralList(this); | 425 accept(Visitor visitor) => visitor.visitLiteralList(this); |
340 } | 426 } |
341 | 427 |
342 class LiteralMap extends Primitive { | 428 class LiteralMap extends Primitive { |
343 final GenericType type; | 429 final GenericType type; |
344 final List<Reference> keys; | 430 final List<Reference> keys; |
345 final List<Reference> values; | 431 final List<Reference> values; |
346 | 432 |
347 LiteralMap(this.type, List<Primitive> keys, List<Primitive> values) | 433 LiteralMap(this.type, List<Primitive> keys, List<Primitive> values) |
348 : this.keys = _referenceList(keys), | 434 : this.keys = _referenceList(keys), |
349 this.values = _referenceList(values); | 435 this.values = _referenceList(values); |
350 | 436 |
351 accept(Visitor visitor) => visitor.visitLiteralMap(this); | 437 accept(Visitor visitor) => visitor.visitLiteralMap(this); |
352 } | 438 } |
353 | 439 |
440 /// Create a non-recursive function. | |
441 class CreateFunction extends Primitive { | |
442 final FunctionDefinition definition; | |
443 | |
444 CreateFunction(this.definition); | |
445 | |
446 accept(Visitor visitor) => visitor.visitCreateFunction(this); | |
447 } | |
448 | |
354 class IsCheck extends Primitive { | 449 class IsCheck extends Primitive { |
355 final Reference receiver; | 450 final Reference receiver; |
356 final DartType type; | 451 final DartType type; |
357 | 452 |
358 dart2js.Constant get constant => null; | 453 dart2js.Constant get constant => null; |
359 | 454 |
360 IsCheck(Primitive receiver, this.type) | 455 IsCheck(Primitive receiver, this.type) |
361 : this.receiver = new Reference(receiver); | 456 : this.receiver = new Reference(receiver); |
362 | 457 |
363 accept(Visitor visitor) => visitor.visitIsCheck(this); | 458 accept(Visitor visitor) => visitor.visitIsCheck(this); |
364 } | 459 } |
365 | 460 |
366 class Parameter extends Primitive { | 461 class Parameter extends Primitive { |
367 Parameter(Element element) { | 462 Parameter(Element element) { |
368 super.element = element; | 463 super.hint = element; |
369 } | 464 } |
370 | 465 |
371 accept(Visitor visitor) => visitor.visitParameter(this); | 466 accept(Visitor visitor) => visitor.visitParameter(this); |
372 } | 467 } |
373 | 468 |
374 /// Continuations are normally bound by 'let cont'. A continuation with no | 469 /// Continuations are normally bound by 'let cont'. A continuation with no |
375 /// parameter (or body) is used to represent a function's return continuation. | 470 /// parameter (or body) is used to represent a function's return continuation. |
376 /// The return continuation is bound by the Function, not by 'let cont'. | 471 /// The return continuation is bound by the Function, not by 'let cont'. |
377 class Continuation extends Definition { | 472 class Continuation extends Definition { |
378 final List<Parameter> parameters; | 473 final List<Parameter> parameters; |
379 Expression body = null; | 474 Expression body = null; |
380 | 475 |
381 // A continuation is recursive if it has any recursive invocations. | 476 // A continuation is recursive if it has any recursive invocations. |
382 bool isRecursive = false; | 477 bool isRecursive = false; |
383 | 478 |
384 Continuation(this.parameters); | 479 Continuation(this.parameters); |
385 | 480 |
386 Continuation.retrn() : parameters = null; | 481 Continuation.retrn() : parameters = null; |
387 | 482 |
388 accept(Visitor visitor) => visitor.visitContinuation(this); | 483 accept(Visitor visitor) => visitor.visitContinuation(this); |
389 } | 484 } |
390 | 485 |
391 /// A function definition, consisting of parameters and a body. The parameters | 486 /// A function definition, consisting of parameters and a body. The parameters |
392 /// include a distinguished continuation parameter. | 487 /// include a distinguished continuation parameter. |
393 class FunctionDefinition extends Node { | 488 class FunctionDefinition extends Node { |
489 final FunctionElement element; | |
394 final Continuation returnContinuation; | 490 final Continuation returnContinuation; |
395 final List<Parameter> parameters; | 491 final List<Parameter> parameters; |
396 final Expression body; | 492 final Expression body; |
397 final List<ConstDeclaration> localConstants; | 493 final List<ConstDeclaration> localConstants; |
398 | 494 |
399 FunctionDefinition(this.returnContinuation, this.parameters, this.body, | 495 FunctionDefinition(this.element, this.returnContinuation, |
400 this.localConstants); | 496 this.parameters, this.body, this.localConstants); |
401 | 497 |
402 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); | 498 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
403 } | 499 } |
404 | 500 |
405 List<Reference> _referenceList(List<Definition> definitions) { | 501 List<Reference> _referenceList(List<Definition> definitions) { |
406 return definitions.map((e) => new Reference(e)).toList(growable: false); | 502 return definitions.map((e) => new Reference(e)).toList(growable: false); |
407 } | 503 } |
408 | 504 |
409 abstract class Visitor<T> { | 505 abstract class Visitor<T> { |
410 T visit(Node node) => node.accept(this); | 506 T visit(Node node) => node.accept(this); |
(...skipping 11 matching lines...) Expand all Loading... | |
422 T visitLetPrim(LetPrim node) => visitExpression(node); | 518 T visitLetPrim(LetPrim node) => visitExpression(node); |
423 T visitLetCont(LetCont node) => visitExpression(node); | 519 T visitLetCont(LetCont node) => visitExpression(node); |
424 T visitInvokeStatic(InvokeStatic node) => visitExpression(node); | 520 T visitInvokeStatic(InvokeStatic node) => visitExpression(node); |
425 T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node); | 521 T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node); |
426 T visitInvokeMethod(InvokeMethod node) => visitExpression(node); | 522 T visitInvokeMethod(InvokeMethod node) => visitExpression(node); |
427 T visitInvokeSuperMethod(InvokeSuperMethod node) => visitExpression(node); | 523 T visitInvokeSuperMethod(InvokeSuperMethod node) => visitExpression(node); |
428 T visitInvokeConstructor(InvokeConstructor node) => visitExpression(node); | 524 T visitInvokeConstructor(InvokeConstructor node) => visitExpression(node); |
429 T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node); | 525 T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node); |
430 T visitBranch(Branch node) => visitExpression(node); | 526 T visitBranch(Branch node) => visitExpression(node); |
431 T visitAsCast(AsCast node) => visitExpression(node); | 527 T visitAsCast(AsCast node) => visitExpression(node); |
528 T visitSetClosureVariable(SetClosureVariable node) => visitExpression(node); | |
529 T visitDeclareFunction(DeclareFunction node) => visitExpression(node); | |
432 | 530 |
433 // Definitions. | 531 // Definitions. |
434 T visitLiteralList(LiteralList node) => visitPrimitive(node); | 532 T visitLiteralList(LiteralList node) => visitPrimitive(node); |
435 T visitLiteralMap(LiteralMap node) => visitPrimitive(node); | 533 T visitLiteralMap(LiteralMap node) => visitPrimitive(node); |
436 T visitIsCheck(IsCheck node) => visitPrimitive(node); | 534 T visitIsCheck(IsCheck node) => visitPrimitive(node); |
437 T visitConstant(Constant node) => visitPrimitive(node); | 535 T visitConstant(Constant node) => visitPrimitive(node); |
438 T visitThis(This node) => visitPrimitive(node); | 536 T visitThis(This node) => visitPrimitive(node); |
439 T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node); | 537 T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node); |
538 T visitCreateFunction(CreateFunction node) => visitPrimitive(node); | |
539 T visitGetClosureVariable(GetClosureVariable node) => visitPrimitive(node); | |
440 T visitParameter(Parameter node) => visitPrimitive(node); | 540 T visitParameter(Parameter node) => visitPrimitive(node); |
441 T visitContinuation(Continuation node) => visitDefinition(node); | 541 T visitContinuation(Continuation node) => visitDefinition(node); |
442 | 542 |
443 // Conditions. | 543 // Conditions. |
444 T visitIsTrue(IsTrue node) => visitCondition(node); | 544 T visitIsTrue(IsTrue node) => visitCondition(node); |
445 } | 545 } |
446 | 546 |
447 /// Generate a Lisp-like S-expression representation of an IR node as a string. | 547 /// Generate a Lisp-like S-expression representation of an IR node as a string. |
448 /// The representation is not pretty-printed, but it can easily be quoted and | 548 /// The representation is not pretty-printed, but it can easily be quoted and |
449 /// dropped into the REPL of one's favorite Lisp or Scheme implementation to be | 549 /// dropped into the REPL of one's favorite Lisp or Scheme implementation to be |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
556 | 656 |
557 String visitConstant(Constant node) { | 657 String visitConstant(Constant node) { |
558 return '(Constant ${node.value})'; | 658 return '(Constant ${node.value})'; |
559 } | 659 } |
560 | 660 |
561 String visitThis(This node) { | 661 String visitThis(This node) { |
562 return '(This)'; | 662 return '(This)'; |
563 } | 663 } |
564 | 664 |
565 String visitReifyTypeVar(ReifyTypeVar node) { | 665 String visitReifyTypeVar(ReifyTypeVar node) { |
566 return '(ReifyTypeVar ${node.element.name})'; | 666 return '(ReifyTypeVar ${node.typeVariable.name})'; |
667 } | |
668 | |
669 String visitCreateFunction(CreateFunction node) { | |
670 String function = visit(node.definition); | |
671 return '(CreateFunction ${node.definition.element} $function)'; | |
567 } | 672 } |
568 | 673 |
569 String visitParameter(Parameter node) { | 674 String visitParameter(Parameter node) { |
570 // Parameters are visited directly in visitLetCont. | 675 // Parameters are visited directly in visitLetCont. |
571 return '(Unexpected Parameter)'; | 676 return '(Unexpected Parameter)'; |
572 } | 677 } |
573 | 678 |
574 String visitContinuation(Continuation node) { | 679 String visitContinuation(Continuation node) { |
575 // Continuations are visited directly in visitLetCont. | 680 // Continuations are visited directly in visitLetCont. |
576 return '(Unexpected Continuation)'; | 681 return '(Unexpected Continuation)'; |
577 } | 682 } |
578 | 683 |
684 String visitGetClosureVariable(GetClosureVariable node) { | |
685 return '(GetClosureVariable ${node.variable.name})'; | |
686 } | |
687 | |
688 String visitSetClosureVariable(SetClosureVariable node) { | |
689 String value = names[node.value.definition]; | |
690 String body = visit(node.body); | |
691 return '(SetClosureVariable ${node.variable.name} $value $body)'; | |
692 } | |
693 | |
694 String visitDeclareFunction(DeclareFunction node) { | |
695 String function = visit(node.definition); | |
696 String body = visit(node.body); | |
697 return '(DeclareFunction ${node.variable} = $function in $body)'; | |
698 } | |
699 | |
579 String visitIsTrue(IsTrue node) { | 700 String visitIsTrue(IsTrue node) { |
580 String value = names[node.value.definition]; | 701 String value = names[node.value.definition]; |
581 return '(IsTrue $value)'; | 702 return '(IsTrue $value)'; |
582 } | 703 } |
583 } | 704 } |
584 | 705 |
585 /// Keeps track of currently unused register indices. | 706 /// Keeps track of currently unused register indices. |
586 class RegisterArray { | 707 class RegisterArray { |
587 int nextIndex = 0; | 708 int nextIndex = 0; |
588 final List<int> freeStack = <int>[]; | 709 final List<int> freeStack = <int>[]; |
(...skipping 28 matching lines...) Expand all Loading... | |
617 RegisterArray registers = elementRegisters[element]; | 738 RegisterArray registers = elementRegisters[element]; |
618 if (registers == null) { | 739 if (registers == null) { |
619 registers = new RegisterArray(); | 740 registers = new RegisterArray(); |
620 elementRegisters[element] = registers; | 741 elementRegisters[element] = registers; |
621 } | 742 } |
622 return registers; | 743 return registers; |
623 } | 744 } |
624 | 745 |
625 void allocate(Primitive primitive) { | 746 void allocate(Primitive primitive) { |
626 if (primitive.registerIndex == null) { | 747 if (primitive.registerIndex == null) { |
627 primitive.registerIndex = getRegisterArray(primitive.element).makeIndex(); | 748 primitive.registerIndex = getRegisterArray(primitive.hint).makeIndex(); |
628 } | 749 } |
629 } | 750 } |
630 | 751 |
631 void release(Primitive primitive) { | 752 void release(Primitive primitive) { |
632 // Do not share indices for temporaries as this may obstruct inlining. | 753 // Do not share indices for temporaries as this may obstruct inlining. |
633 if (primitive.element == null) return; | 754 if (primitive.hint == null) return; |
634 if (primitive.registerIndex != null) { | 755 if (primitive.registerIndex != null) { |
635 getRegisterArray(primitive.element).releaseIndex(primitive.registerIndex); | 756 getRegisterArray(primitive.hint).releaseIndex(primitive.registerIndex); |
636 } | 757 } |
637 } | 758 } |
638 | 759 |
639 void visitReference(Reference reference) { | 760 void visitReference(Reference reference) { |
640 allocate(reference.definition); | 761 allocate(reference.definition); |
641 } | 762 } |
642 | 763 |
643 void visitFunctionDefinition(FunctionDefinition node) { | 764 void visitFunctionDefinition(FunctionDefinition node) { |
644 visit(node.body); | 765 visit(node.body); |
645 node.parameters.forEach(allocate); // Assign indices to unused parameters. | 766 node.parameters.forEach(allocate); // Assign indices to unused parameters. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
707 | 828 |
708 void visitConstant(Constant node) { | 829 void visitConstant(Constant node) { |
709 } | 830 } |
710 | 831 |
711 void visitThis(This node) { | 832 void visitThis(This node) { |
712 } | 833 } |
713 | 834 |
714 void visitReifyTypeVar(ReifyTypeVar node) { | 835 void visitReifyTypeVar(ReifyTypeVar node) { |
715 } | 836 } |
716 | 837 |
838 void visitCreateFunction(CreateFunction node) { | |
839 new RegisterAllocator().visit(node.definition); | |
840 } | |
841 | |
842 void visitGetClosureVariable(GetClosureVariable node) { | |
843 } | |
844 | |
845 void visitSetClosureVariable(SetClosureVariable node) { | |
846 visit(node.body); | |
847 visitReference(node.value); | |
848 } | |
849 | |
850 void visitDeclareFunction(DeclareFunction node) { | |
851 new RegisterAllocator().visit(node.definition); | |
852 visit(node.body); | |
853 } | |
854 | |
717 void visitParameter(Parameter node) { | 855 void visitParameter(Parameter node) { |
718 throw "Parameters should not be visited by RegisterAllocator"; | 856 throw "Parameters should not be visited by RegisterAllocator"; |
719 } | 857 } |
720 | 858 |
721 void visitContinuation(Continuation node) { | 859 void visitContinuation(Continuation node) { |
722 visit(node.body); | 860 visit(node.body); |
723 | 861 |
724 // Arguments get allocated left-to-right, so we release parameters | 862 // Arguments get allocated left-to-right, so we release parameters |
725 // right-to-left. This increases the likelihood that arguments can be | 863 // right-to-left. This increases the likelihood that arguments can be |
726 // transferred without intermediate assignments. | 864 // transferred without intermediate assignments. |
727 for (int i = node.parameters.length - 1; i >= 0; --i) { | 865 for (int i = node.parameters.length - 1; i >= 0; --i) { |
728 release(node.parameters[i]); | 866 release(node.parameters[i]); |
729 } | 867 } |
730 } | 868 } |
731 | 869 |
732 void visitIsTrue(IsTrue node) { | 870 void visitIsTrue(IsTrue node) { |
733 visitReference(node.value); | 871 visitReference(node.value); |
734 } | 872 } |
735 | 873 |
736 } | 874 } |
OLD | NEW |