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 must not exist a [SetClosureVariable] to [variable]. |
| 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 |