| 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 |