1 11 package org.eclipse.jdt.internal.compiler.ast; 12 13 import org.eclipse.jdt.internal.compiler.ASTVisitor; 14 import org.eclipse.jdt.internal.compiler.impl.*; 15 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 16 import org.eclipse.jdt.internal.compiler.codegen.*; 17 import org.eclipse.jdt.internal.compiler.flow.*; 18 import org.eclipse.jdt.internal.compiler.lookup.*; 19 20 public class BinaryExpression extends OperatorExpression { 21 22 34 35 public Expression left, right; 36 public Constant optimizedBooleanConstant; 37 38 public BinaryExpression(Expression left, Expression right, int operator) { 39 this.left = left; 40 this.right = right; 41 this.bits |= operator << ASTNode.OperatorSHIFT; this.sourceStart = left.sourceStart; 43 this.sourceEnd = right.sourceEnd; 44 } 52 53 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, 54 FlowInfo flowInfo) { 55 if (this.resolvedType.id == TypeIds.T_JavaLangString) { 57 return this.right.analyseCode( 58 currentScope, flowContext, 59 this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()) 60 .unconditionalInits(); 61 } else { 62 this.left.checkNPE(currentScope, flowContext, flowInfo); 63 flowInfo = this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); 64 this.right.checkNPE(currentScope, flowContext, flowInfo); 65 return this.right.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); 66 } 67 } 68 69 public void computeConstant(BlockScope scope, int leftId, int rightId) { 70 if ((this.left.constant != Constant.NotAConstant) 72 && (this.right.constant != Constant.NotAConstant)) { 73 try { 74 this.constant = 75 Constant.computeConstantOperation( 76 this.left.constant, 77 leftId, 78 (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT, 79 this.right.constant, 80 rightId); 81 } catch (ArithmeticException e) { 82 this.constant = Constant.NotAConstant; 83 } 86 } else { 87 this.constant = Constant.NotAConstant; 88 this.optimizedBooleanConstant( 90 leftId, 91 (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT, 92 rightId); 93 } 94 } 95 96 public Constant optimizedBooleanConstant() { 97 return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant; 98 } 99 100 103 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 107 int pc = codeStream.position; 108 if (this.constant != Constant.NotAConstant) { 109 if (valueRequired) 110 codeStream.generateConstant(this.constant, this.implicitConversion); 111 codeStream.recordPositionsFrom(pc, this.sourceStart); 112 return; 113 } 114 switch ((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) { 115 case PLUS : 116 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 117 case T_JavaLangString : 118 codeStream.generateStringConcatenationAppend(currentScope, this.left, this.right); 123 if (!valueRequired) 124 codeStream.pop(); 125 break; 126 case T_int : 127 this.left.generateCode(currentScope, codeStream, valueRequired); 128 this.right.generateCode(currentScope, codeStream, valueRequired); 129 if (valueRequired) 130 codeStream.iadd(); 131 break; 132 case T_long : 133 this.left.generateCode(currentScope, codeStream, valueRequired); 134 this.right.generateCode(currentScope, codeStream, valueRequired); 135 if (valueRequired) 136 codeStream.ladd(); 137 break; 138 case T_double : 139 this.left.generateCode(currentScope, codeStream, valueRequired); 140 this.right.generateCode(currentScope, codeStream, valueRequired); 141 if (valueRequired) 142 codeStream.dadd(); 143 break; 144 case T_float : 145 this.left.generateCode(currentScope, codeStream, valueRequired); 146 this.right.generateCode(currentScope, codeStream, valueRequired); 147 if (valueRequired) 148 codeStream.fadd(); 149 break; 150 } 151 break; 152 case MINUS : 153 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 154 case T_int : 155 this.left.generateCode(currentScope, codeStream, valueRequired); 156 this.right.generateCode(currentScope, codeStream, valueRequired); 157 if (valueRequired) 158 codeStream.isub(); 159 break; 160 case T_long : 161 this.left.generateCode(currentScope, codeStream, valueRequired); 162 this.right.generateCode(currentScope, codeStream, valueRequired); 163 if (valueRequired) 164 codeStream.lsub(); 165 break; 166 case T_double : 167 this.left.generateCode(currentScope, codeStream, valueRequired); 168 this.right.generateCode(currentScope, codeStream, valueRequired); 169 if (valueRequired) 170 codeStream.dsub(); 171 break; 172 case T_float : 173 this.left.generateCode(currentScope, codeStream, valueRequired); 174 this.right.generateCode(currentScope, codeStream, valueRequired); 175 if (valueRequired) 176 codeStream.fsub(); 177 break; 178 } 179 break; 180 case MULTIPLY : 181 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 182 case T_int : 183 this.left.generateCode(currentScope, codeStream, valueRequired); 184 this.right.generateCode(currentScope, codeStream, valueRequired); 185 if (valueRequired) 186 codeStream.imul(); 187 break; 188 case T_long : 189 this.left.generateCode(currentScope, codeStream, valueRequired); 190 this.right.generateCode(currentScope, codeStream, valueRequired); 191 if (valueRequired) 192 codeStream.lmul(); 193 break; 194 case T_double : 195 this.left.generateCode(currentScope, codeStream, valueRequired); 196 this.right.generateCode(currentScope, codeStream, valueRequired); 197 if (valueRequired) 198 codeStream.dmul(); 199 break; 200 case T_float : 201 this.left.generateCode(currentScope, codeStream, valueRequired); 202 this.right.generateCode(currentScope, codeStream, valueRequired); 203 if (valueRequired) 204 codeStream.fmul(); 205 break; 206 } 207 break; 208 case DIVIDE : 209 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 210 case T_int : 211 this.left.generateCode(currentScope, codeStream, true); 212 this.right.generateCode(currentScope, codeStream, true); 213 codeStream.idiv(); 214 if (!valueRequired) 215 codeStream.pop(); 216 break; 217 case T_long : 218 this.left.generateCode(currentScope, codeStream, true); 219 this.right.generateCode(currentScope, codeStream, true); 220 codeStream.ldiv(); 221 if (!valueRequired) 222 codeStream.pop2(); 223 break; 224 case T_double : 225 this.left.generateCode(currentScope, codeStream, valueRequired); 226 this.right.generateCode(currentScope, codeStream, valueRequired); 227 if (valueRequired) 228 codeStream.ddiv(); 229 break; 230 case T_float : 231 this.left.generateCode(currentScope, codeStream, valueRequired); 232 this.right.generateCode(currentScope, codeStream, valueRequired); 233 if (valueRequired) 234 codeStream.fdiv(); 235 break; 236 } 237 break; 238 case REMAINDER : 239 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 240 case T_int : 241 this.left.generateCode(currentScope, codeStream, true); 242 this.right.generateCode(currentScope, codeStream, true); 243 codeStream.irem(); 244 if (!valueRequired) 245 codeStream.pop(); 246 break; 247 case T_long : 248 this.left.generateCode(currentScope, codeStream, true); 249 this.right.generateCode(currentScope, codeStream, true); 250 codeStream.lrem(); 251 if (!valueRequired) 252 codeStream.pop2(); 253 break; 254 case T_double : 255 this.left.generateCode(currentScope, codeStream, valueRequired); 256 this.right.generateCode(currentScope, codeStream, valueRequired); 257 if (valueRequired) 258 codeStream.drem(); 259 break; 260 case T_float : 261 this.left.generateCode(currentScope, codeStream, valueRequired); 262 this.right.generateCode(currentScope, codeStream, valueRequired); 263 if (valueRequired) 264 codeStream.frem(); 265 break; 266 } 267 break; 268 case AND : 269 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 270 case T_int : 271 if ((this.left.constant != Constant.NotAConstant) 273 && (this.left.constant.typeID() == TypeIds.T_int) 274 && (this.left.constant.intValue() == 0)) { 275 this.right.generateCode(currentScope, codeStream, false); 276 if (valueRequired) 277 codeStream.iconst_0(); 278 } else { 279 if ((this.right.constant != Constant.NotAConstant) 281 && (this.right.constant.typeID() == TypeIds.T_int) 282 && (this.right.constant.intValue() == 0)) { 283 this.left.generateCode(currentScope, codeStream, false); 284 if (valueRequired) 285 codeStream.iconst_0(); 286 } else { 287 this.left.generateCode(currentScope, codeStream, valueRequired); 288 this.right.generateCode(currentScope, codeStream, valueRequired); 289 if (valueRequired) 290 codeStream.iand(); 291 } 292 } 293 break; 294 case T_long : 295 if ((this.left.constant != Constant.NotAConstant) 297 && (this.left.constant.typeID() == TypeIds.T_long) 298 && (this.left.constant.longValue() == 0L)) { 299 this.right.generateCode(currentScope, codeStream, false); 300 if (valueRequired) 301 codeStream.lconst_0(); 302 } else { 303 if ((this.right.constant != Constant.NotAConstant) 305 && (this.right.constant.typeID() == TypeIds.T_long) 306 && (this.right.constant.longValue() == 0L)) { 307 this.left.generateCode(currentScope, codeStream, false); 308 if (valueRequired) 309 codeStream.lconst_0(); 310 } else { 311 this.left.generateCode(currentScope, codeStream, valueRequired); 312 this.right.generateCode(currentScope, codeStream, valueRequired); 313 if (valueRequired) 314 codeStream.land(); 315 } 316 } 317 break; 318 case T_boolean : generateLogicalAnd(currentScope, codeStream, valueRequired); 320 break; 321 } 322 break; 323 case OR : 324 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 325 case T_int : 326 if ((this.left.constant != Constant.NotAConstant) 328 && (this.left.constant.typeID() == TypeIds.T_int) 329 && (this.left.constant.intValue() == 0)) { 330 this.right.generateCode(currentScope, codeStream, valueRequired); 331 } else { 332 if ((this.right.constant != Constant.NotAConstant) 334 && (this.right.constant.typeID() == TypeIds.T_int) 335 && (this.right.constant.intValue() == 0)) { 336 this.left.generateCode(currentScope, codeStream, valueRequired); 337 } else { 338 this.left.generateCode(currentScope, codeStream, valueRequired); 339 this.right.generateCode(currentScope, codeStream, valueRequired); 340 if (valueRequired) 341 codeStream.ior(); 342 } 343 } 344 break; 345 case T_long : 346 if ((this.left.constant != Constant.NotAConstant) 348 && (this.left.constant.typeID() == TypeIds.T_long) 349 && (this.left.constant.longValue() == 0L)) { 350 this.right.generateCode(currentScope, codeStream, valueRequired); 351 } else { 352 if ((this.right.constant != Constant.NotAConstant) 354 && (this.right.constant.typeID() == TypeIds.T_long) 355 && (this.right.constant.longValue() == 0L)) { 356 this.left.generateCode(currentScope, codeStream, valueRequired); 357 } else { 358 this.left.generateCode(currentScope, codeStream, valueRequired); 359 this.right.generateCode(currentScope, codeStream, valueRequired); 360 if (valueRequired) 361 codeStream.lor(); 362 } 363 } 364 break; 365 case T_boolean : generateLogicalOr(currentScope, codeStream, valueRequired); 367 break; 368 } 369 break; 370 case XOR : 371 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 372 case T_int : 373 if ((this.left.constant != Constant.NotAConstant) 375 && (this.left.constant.typeID() == TypeIds.T_int) 376 && (this.left.constant.intValue() == 0)) { 377 this.right.generateCode(currentScope, codeStream, valueRequired); 378 } else { 379 if ((this.right.constant != Constant.NotAConstant) 381 && (this.right.constant.typeID() == TypeIds.T_int) 382 && (this.right.constant.intValue() == 0)) { 383 this.left.generateCode(currentScope, codeStream, valueRequired); 384 } else { 385 this.left.generateCode(currentScope, codeStream, valueRequired); 386 this.right.generateCode(currentScope, codeStream, valueRequired); 387 if (valueRequired) 388 codeStream.ixor(); 389 } 390 } 391 break; 392 case T_long : 393 if ((this.left.constant != Constant.NotAConstant) 395 && (this.left.constant.typeID() == TypeIds.T_long) 396 && (this.left.constant.longValue() == 0L)) { 397 this.right.generateCode(currentScope, codeStream, valueRequired); 398 } else { 399 if ((this.right.constant != Constant.NotAConstant) 401 && (this.right.constant.typeID() == TypeIds.T_long) 402 && (this.right.constant.longValue() == 0L)) { 403 this.left.generateCode(currentScope, codeStream, valueRequired); 404 } else { 405 this.left.generateCode(currentScope, codeStream, valueRequired); 406 this.right.generateCode(currentScope, codeStream, valueRequired); 407 if (valueRequired) 408 codeStream.lxor(); 409 } 410 } 411 break; 412 case T_boolean : 413 generateLogicalXor(currentScope, codeStream, valueRequired); 414 break; 415 } 416 break; 417 case LEFT_SHIFT : 418 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 419 case T_int : 420 this.left.generateCode(currentScope, codeStream, valueRequired); 421 this.right.generateCode(currentScope, codeStream, valueRequired); 422 if (valueRequired) 423 codeStream.ishl(); 424 break; 425 case T_long : 426 this.left.generateCode(currentScope, codeStream, valueRequired); 427 this.right.generateCode(currentScope, codeStream, valueRequired); 428 if (valueRequired) 429 codeStream.lshl(); 430 } 431 break; 432 case RIGHT_SHIFT : 433 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 434 case T_int : 435 this.left.generateCode(currentScope, codeStream, valueRequired); 436 this.right.generateCode(currentScope, codeStream, valueRequired); 437 if (valueRequired) 438 codeStream.ishr(); 439 break; 440 case T_long : 441 this.left.generateCode(currentScope, codeStream, valueRequired); 442 this.right.generateCode(currentScope, codeStream, valueRequired); 443 if (valueRequired) 444 codeStream.lshr(); 445 } 446 break; 447 case UNSIGNED_RIGHT_SHIFT : 448 switch (this.bits & ASTNode.ReturnTypeIDMASK) { 449 case T_int : 450 this.left.generateCode(currentScope, codeStream, valueRequired); 451 this.right.generateCode(currentScope, codeStream, valueRequired); 452 if (valueRequired) 453 codeStream.iushr(); 454 break; 455 case T_long : 456 this.left.generateCode(currentScope, codeStream, valueRequired); 457 this.right.generateCode(currentScope, codeStream, valueRequired); 458 if (valueRequired) 459 codeStream.lushr(); 460 } 461 break; 462 case GREATER : 463 BranchLabel falseLabel, endLabel; 464 generateOptimizedGreaterThan( 465 currentScope, 466 codeStream, 467 null, 468 (falseLabel = new BranchLabel(codeStream)), 469 valueRequired); 470 if (valueRequired) { 471 codeStream.iconst_1(); 472 if ((this.bits & ASTNode.IsReturnedValue) != 0) { 473 codeStream.generateImplicitConversion(this.implicitConversion); 474 codeStream.generateReturnBytecode(this); 475 falseLabel.place(); 476 codeStream.iconst_0(); 477 } else { 478 codeStream.goto_(endLabel = new BranchLabel(codeStream)); 479 codeStream.decrStackSize(1); 480 falseLabel.place(); 481 codeStream.iconst_0(); 482 endLabel.place(); 483 } 484 } 485 break; 486 case GREATER_EQUAL : 487 generateOptimizedGreaterThanOrEqual( 488 currentScope, 489 codeStream, 490 null, 491 (falseLabel = new BranchLabel(codeStream)), 492 valueRequired); 493 if (valueRequired) { 494 codeStream.iconst_1(); 495 if ((this.bits & ASTNode.IsReturnedValue) != 0) { 496 codeStream.generateImplicitConversion(this.implicitConversion); 497 codeStream.generateReturnBytecode(this); 498 falseLabel.place(); 499 codeStream.iconst_0(); 500 } else { 501 codeStream.goto_(endLabel = new BranchLabel(codeStream)); 502 codeStream.decrStackSize(1); 503 falseLabel.place(); 504 codeStream.iconst_0(); 505 endLabel.place(); 506 } 507 } 508 break; 509 case LESS : 510 generateOptimizedLessThan( 511 currentScope, 512 codeStream, 513 null, 514 (falseLabel = new BranchLabel(codeStream)), 515 valueRequired); 516 if (valueRequired) { 517 codeStream.iconst_1(); 518 if ((this.bits & ASTNode.IsReturnedValue) != 0) { 519 codeStream.generateImplicitConversion(this.implicitConversion); 520 codeStream.generateReturnBytecode(this); 521 falseLabel.place(); 522 codeStream.iconst_0(); 523 } else { 524 codeStream.goto_(endLabel = new BranchLabel(codeStream)); 525 codeStream.decrStackSize(1); 526 falseLabel.place(); 527 codeStream.iconst_0(); 528 endLabel.place(); 529 } 530 } 531 break; 532 case LESS_EQUAL : 533 generateOptimizedLessThanOrEqual( 534 currentScope, 535 codeStream, 536 null, 537 (falseLabel = new BranchLabel(codeStream)), 538 valueRequired); 539 if (valueRequired) { 540 codeStream.iconst_1(); 541 if ((this.bits & ASTNode.IsReturnedValue) != 0) { 542 codeStream.generateImplicitConversion(this.implicitConversion); 543 codeStream.generateReturnBytecode(this); 544 falseLabel.place(); 545 codeStream.iconst_0(); 546 } else { 547 codeStream.goto_(endLabel = new BranchLabel(codeStream)); 548 codeStream.decrStackSize(1); 549 falseLabel.place(); 550 codeStream.iconst_0(); 551 endLabel.place(); 552 } 553 } 554 } 555 if (valueRequired) { 556 codeStream.generateImplicitConversion(this.implicitConversion); 557 } 558 codeStream.recordPositionsFrom(pc, this.sourceStart); 559 } 560 561 565 public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 566 if ((this.constant != Constant.NotAConstant) && (this.constant.typeID() == TypeIds.T_boolean)) { 567 super.generateOptimizedBoolean( 568 currentScope, 569 codeStream, 570 trueLabel, 571 falseLabel, 572 valueRequired); 573 return; 574 } 575 switch ((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) { 576 case LESS : 577 generateOptimizedLessThan( 578 currentScope, 579 codeStream, 580 trueLabel, 581 falseLabel, 582 valueRequired); 583 return; 584 case LESS_EQUAL : 585 generateOptimizedLessThanOrEqual( 586 currentScope, 587 codeStream, 588 trueLabel, 589 falseLabel, 590 valueRequired); 591 return; 592 case GREATER : 593 generateOptimizedGreaterThan( 594 currentScope, 595 codeStream, 596 trueLabel, 597 falseLabel, 598 valueRequired); 599 return; 600 case GREATER_EQUAL : 601 generateOptimizedGreaterThanOrEqual( 602 currentScope, 603 codeStream, 604 trueLabel, 605 falseLabel, 606 valueRequired); 607 return; 608 case AND : 609 generateOptimizedLogicalAnd( 610 currentScope, 611 codeStream, 612 trueLabel, 613 falseLabel, 614 valueRequired); 615 return; 616 case OR : 617 generateOptimizedLogicalOr( 618 currentScope, 619 codeStream, 620 trueLabel, 621 falseLabel, 622 valueRequired); 623 return; 624 case XOR : 625 generateOptimizedLogicalXor( 626 currentScope, 627 codeStream, 628 trueLabel, 629 falseLabel, 630 valueRequired); 631 return; 632 } 633 super.generateOptimizedBoolean( 634 currentScope, 635 codeStream, 636 trueLabel, 637 falseLabel, 638 valueRequired); 639 } 640 641 644 public void generateOptimizedGreaterThan(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 645 int promotedTypeID = (this.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; 646 if (promotedTypeID == TypeIds.T_int) { 648 if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.intValue() == 0)) { 650 this.right.generateCode(currentScope, codeStream, valueRequired); 651 if (valueRequired) { 652 if (falseLabel == null) { 653 if (trueLabel != null) { 654 codeStream.iflt(trueLabel); 656 } 657 } else { 658 if (trueLabel == null) { 659 codeStream.ifge(falseLabel); 661 } else { 662 } 664 } 665 } 666 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 668 return; 669 } 670 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.intValue() == 0)) { 672 this.left.generateCode(currentScope, codeStream, valueRequired); 673 if (valueRequired) { 674 if (falseLabel == null) { 675 if (trueLabel != null) { 676 codeStream.ifgt(trueLabel); 678 } 679 } else { 680 if (trueLabel == null) { 681 codeStream.ifle(falseLabel); 683 } else { 684 } 686 } 687 } 688 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 690 return; 691 } 692 } 693 this.left.generateCode(currentScope, codeStream, valueRequired); 695 this.right.generateCode(currentScope, codeStream, valueRequired); 696 if (valueRequired) { 697 if (falseLabel == null) { 698 if (trueLabel != null) { 699 switch (promotedTypeID) { 701 case T_int : 702 codeStream.if_icmpgt(trueLabel); 703 break; 704 case T_float : 705 codeStream.fcmpl(); 706 codeStream.ifgt(trueLabel); 707 break; 708 case T_long : 709 codeStream.lcmp(); 710 codeStream.ifgt(trueLabel); 711 break; 712 case T_double : 713 codeStream.dcmpl(); 714 codeStream.ifgt(trueLabel); 715 } 716 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 718 return; 719 } 720 } else { 721 if (trueLabel == null) { 722 switch (promotedTypeID) { 724 case T_int : 725 codeStream.if_icmple(falseLabel); 726 break; 727 case T_float : 728 codeStream.fcmpl(); 729 codeStream.ifle(falseLabel); 730 break; 731 case T_long : 732 codeStream.lcmp(); 733 codeStream.ifle(falseLabel); 734 break; 735 case T_double : 736 codeStream.dcmpl(); 737 codeStream.ifle(falseLabel); 738 } 739 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 741 return; 742 } else { 743 } 745 } 746 } 747 } 748 749 752 public void generateOptimizedGreaterThanOrEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 753 int promotedTypeID = (this.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; 754 if (promotedTypeID == TypeIds.T_int) { 756 if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.intValue() == 0)) { 758 this.right.generateCode(currentScope, codeStream, valueRequired); 759 if (valueRequired) { 760 if (falseLabel == null) { 761 if (trueLabel != null) { 762 codeStream.ifle(trueLabel); 764 } 765 } else { 766 if (trueLabel == null) { 767 codeStream.ifgt(falseLabel); 769 } else { 770 } 772 } 773 } 774 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 776 return; 777 } 778 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.intValue() == 0)) { 780 this.left.generateCode(currentScope, codeStream, valueRequired); 781 if (valueRequired) { 782 if (falseLabel == null) { 783 if (trueLabel != null) { 784 codeStream.ifge(trueLabel); 786 } 787 } else { 788 if (trueLabel == null) { 789 codeStream.iflt(falseLabel); 791 } else { 792 } 794 } 795 } 796 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 798 return; 799 } 800 } 801 this.left.generateCode(currentScope, codeStream, valueRequired); 803 this.right.generateCode(currentScope, codeStream, valueRequired); 804 if (valueRequired) { 805 if (falseLabel == null) { 806 if (trueLabel != null) { 807 switch (promotedTypeID) { 809 case T_int : 810 codeStream.if_icmpge(trueLabel); 811 break; 812 case T_float : 813 codeStream.fcmpl(); 814 codeStream.ifge(trueLabel); 815 break; 816 case T_long : 817 codeStream.lcmp(); 818 codeStream.ifge(trueLabel); 819 break; 820 case T_double : 821 codeStream.dcmpl(); 822 codeStream.ifge(trueLabel); 823 } 824 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 826 return; 827 } 828 } else { 829 if (trueLabel == null) { 830 switch (promotedTypeID) { 832 case T_int : 833 codeStream.if_icmplt(falseLabel); 834 break; 835 case T_float : 836 codeStream.fcmpl(); 837 codeStream.iflt(falseLabel); 838 break; 839 case T_long : 840 codeStream.lcmp(); 841 codeStream.iflt(falseLabel); 842 break; 843 case T_double : 844 codeStream.dcmpl(); 845 codeStream.iflt(falseLabel); 846 } 847 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 849 return; 850 } else { 851 } 853 } 854 } 855 } 856 857 860 public void generateOptimizedLessThan(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 861 int promotedTypeID = (this.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; 862 if (promotedTypeID == TypeIds.T_int) { 864 if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.intValue() == 0)) { 866 this.right.generateCode(currentScope, codeStream, valueRequired); 867 if (valueRequired) { 868 if (falseLabel == null) { 869 if (trueLabel != null) { 870 codeStream.ifgt(trueLabel); 872 } 873 } else { 874 if (trueLabel == null) { 875 codeStream.ifle(falseLabel); 877 } else { 878 } 880 } 881 } 882 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 883 return; 884 } 885 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.intValue() == 0)) { 887 this.left.generateCode(currentScope, codeStream, valueRequired); 888 if (valueRequired) { 889 if (falseLabel == null) { 890 if (trueLabel != null) { 891 codeStream.iflt(trueLabel); 893 } 894 } else { 895 if (trueLabel == null) { 896 codeStream.ifge(falseLabel); 898 } else { 899 } 901 } 902 } 903 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 904 return; 905 } 906 } 907 this.left.generateCode(currentScope, codeStream, valueRequired); 909 this.right.generateCode(currentScope, codeStream, valueRequired); 910 if (valueRequired) { 911 if (falseLabel == null) { 912 if (trueLabel != null) { 913 switch (promotedTypeID) { 915 case T_int : 916 codeStream.if_icmplt(trueLabel); 917 break; 918 case T_float : 919 codeStream.fcmpg(); 920 codeStream.iflt(trueLabel); 921 break; 922 case T_long : 923 codeStream.lcmp(); 924 codeStream.iflt(trueLabel); 925 break; 926 case T_double : 927 codeStream.dcmpg(); 928 codeStream.iflt(trueLabel); 929 } 930 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 931 return; 932 } 933 } else { 934 if (trueLabel == null) { 935 switch (promotedTypeID) { 937 case T_int : 938 codeStream.if_icmpge(falseLabel); 939 break; 940 case T_float : 941 codeStream.fcmpg(); 942 codeStream.ifge(falseLabel); 943 break; 944 case T_long : 945 codeStream.lcmp(); 946 codeStream.ifge(falseLabel); 947 break; 948 case T_double : 949 codeStream.dcmpg(); 950 codeStream.ifge(falseLabel); 951 } 952 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 953 return; 954 } else { 955 } 957 } 958 } 959 } 960 961 964 public void generateOptimizedLessThanOrEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 965 int promotedTypeID = (this.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; 966 if (promotedTypeID == TypeIds.T_int) { 968 if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.intValue() == 0)) { 970 this.right.generateCode(currentScope, codeStream, valueRequired); 971 if (valueRequired) { 972 if (falseLabel == null) { 973 if (trueLabel != null) { 974 codeStream.ifge(trueLabel); 976 } 977 } else { 978 if (trueLabel == null) { 979 codeStream.iflt(falseLabel); 981 } else { 982 } 984 } 985 } 986 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 988 return; 989 } 990 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.intValue() == 0)) { 992 this.left.generateCode(currentScope, codeStream, valueRequired); 993 if (valueRequired) { 994 if (falseLabel == null) { 995 if (trueLabel != null) { 996 codeStream.ifle(trueLabel); 998 } 999 } else { 1000 if (trueLabel == null) { 1001 codeStream.ifgt(falseLabel); 1003 } else { 1004 } 1006 } 1007 } 1008 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1010 return; 1011 } 1012 } 1013 this.left.generateCode(currentScope, codeStream, valueRequired); 1015 this.right.generateCode(currentScope, codeStream, valueRequired); 1016 if (valueRequired) { 1017 if (falseLabel == null) { 1018 if (trueLabel != null) { 1019 switch (promotedTypeID) { 1021 case T_int : 1022 codeStream.if_icmple(trueLabel); 1023 break; 1024 case T_float : 1025 codeStream.fcmpg(); 1026 codeStream.ifle(trueLabel); 1027 break; 1028 case T_long : 1029 codeStream.lcmp(); 1030 codeStream.ifle(trueLabel); 1031 break; 1032 case T_double : 1033 codeStream.dcmpg(); 1034 codeStream.ifle(trueLabel); 1035 } 1036 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1038 return; 1039 } 1040 } else { 1041 if (trueLabel == null) { 1042 switch (promotedTypeID) { 1044 case T_int : 1045 codeStream.if_icmpgt(falseLabel); 1046 break; 1047 case T_float : 1048 codeStream.fcmpg(); 1049 codeStream.ifgt(falseLabel); 1050 break; 1051 case T_long : 1052 codeStream.lcmp(); 1053 codeStream.ifgt(falseLabel); 1054 break; 1055 case T_double : 1056 codeStream.dcmpg(); 1057 codeStream.ifgt(falseLabel); 1058 } 1059 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1061 return; 1062 } else { 1063 } 1065 } 1066 } 1067} 1068 1069 1072public void generateLogicalAnd(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 1073 Constant condConst; 1074 if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { 1075 if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { 1076 if (condConst.booleanValue() == true) { 1077 this.left.generateCode(currentScope, codeStream, false); 1079 this.right.generateCode(currentScope, codeStream, valueRequired); 1080 } else { 1081 this.left.generateCode(currentScope, codeStream, false); 1083 this.right.generateCode(currentScope, codeStream, false); 1084 if (valueRequired) { 1085 codeStream.iconst_0(); 1086 } 1087 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1089 } 1090 return; 1091 } 1092 if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1093 if (condConst.booleanValue() == true) { 1094 this.left.generateCode(currentScope, codeStream, valueRequired); 1096 this.right.generateCode(currentScope, codeStream, false); 1097 } else { 1098 this.left.generateCode(currentScope, codeStream, false); 1100 this.right.generateCode(currentScope, codeStream, false); 1101 if (valueRequired) { 1102 codeStream.iconst_0(); 1103 } 1104 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1106 } 1107 return; 1108 } 1109 } 1110 this.left.generateCode(currentScope, codeStream, valueRequired); 1112 this.right.generateCode(currentScope, codeStream, valueRequired); 1113 if (valueRequired) { 1114 codeStream.iand(); 1115 } 1116 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1118} 1119 1120 1123public void generateLogicalOr(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 1124 Constant condConst; 1125 if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { 1126 if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { 1127 if (condConst.booleanValue() == true) { 1128 this.left.generateCode(currentScope, codeStream, false); 1130 this.right.generateCode(currentScope, codeStream, false); 1131 if (valueRequired) { 1132 codeStream.iconst_1(); 1133 } 1134 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1136 } else { 1137 this.left.generateCode(currentScope, codeStream, false); 1139 this.right.generateCode(currentScope, codeStream, valueRequired); 1140 } 1141 return; 1142 } 1143 if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1144 if (condConst.booleanValue() == true) { 1145 this.left.generateCode(currentScope, codeStream, false); 1147 this.right.generateCode(currentScope, codeStream, false); 1148 if (valueRequired) { 1149 codeStream.iconst_1(); 1150 } 1151 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1153 } else { 1154 this.left.generateCode(currentScope, codeStream, valueRequired); 1156 this.right.generateCode(currentScope, codeStream, false); 1157 } 1158 return; 1159 } 1160 } 1161 this.left.generateCode(currentScope, codeStream, valueRequired); 1163 this.right.generateCode(currentScope, codeStream, valueRequired); 1164 if (valueRequired) { 1165 codeStream.ior(); 1166 } 1167 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1169} 1170 1171 1174public void generateLogicalXor(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 1175 Constant condConst; 1176 if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { 1177 if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { 1178 if (condConst.booleanValue() == true) { 1179 this.left.generateCode(currentScope, codeStream, false); 1181 if (valueRequired) { 1182 codeStream.iconst_1(); 1183 } 1184 this.right.generateCode(currentScope, codeStream, valueRequired); 1185 if (valueRequired) { 1186 codeStream.ixor(); codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1188 } 1189 } else { 1190 this.left.generateCode(currentScope, codeStream, false); 1192 this.right.generateCode(currentScope, codeStream, valueRequired); 1193 } 1194 return; 1195 } 1196 if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1197 if (condConst.booleanValue() == true) { 1198 this.left.generateCode(currentScope, codeStream, valueRequired); 1200 this.right.generateCode(currentScope, codeStream, false); 1201 if (valueRequired) { 1202 codeStream.iconst_1(); 1203 codeStream.ixor(); codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1205 } 1206 } else { 1207 this.left.generateCode(currentScope, codeStream, valueRequired); 1209 this.right.generateCode(currentScope, codeStream, false); 1210 } 1211 return; 1212 } 1213 } 1214 this.left.generateCode(currentScope, codeStream, valueRequired); 1216 this.right.generateCode(currentScope, codeStream, valueRequired); 1217 if (valueRequired) { 1218 codeStream.ixor(); 1219 } 1220 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1222} 1223 1224 1227public void generateOptimizedLogicalAnd(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 1228 Constant condConst; 1229 if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { 1230 if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { 1231 if (condConst.booleanValue() == true) { 1232 this.left.generateOptimizedBoolean( 1234 currentScope, 1235 codeStream, 1236 trueLabel, 1237 falseLabel, 1238 false); 1239 this.right.generateOptimizedBoolean( 1240 currentScope, 1241 codeStream, 1242 trueLabel, 1243 falseLabel, 1244 valueRequired); 1245 } else { 1246 this.left.generateOptimizedBoolean( 1248 currentScope, 1249 codeStream, 1250 trueLabel, 1251 falseLabel, 1252 false); 1253 this.right.generateOptimizedBoolean( 1254 currentScope, 1255 codeStream, 1256 trueLabel, 1257 falseLabel, 1258 false); 1259 if (valueRequired) { 1260 if (falseLabel != null) { 1261 codeStream.goto_(falseLabel); 1263 } 1264 } 1265 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1267 } 1268 return; 1269 } 1270 if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1271 if (condConst.booleanValue() == true) { 1272 this.left.generateOptimizedBoolean( 1274 currentScope, 1275 codeStream, 1276 trueLabel, 1277 falseLabel, 1278 valueRequired); 1279 this.right.generateOptimizedBoolean( 1280 currentScope, 1281 codeStream, 1282 trueLabel, 1283 falseLabel, 1284 false); 1285 } else { 1286 BranchLabel internalTrueLabel = new BranchLabel(codeStream); 1288 this.left.generateOptimizedBoolean( 1289 currentScope, 1290 codeStream, 1291 internalTrueLabel, 1292 falseLabel, 1293 false); 1294 internalTrueLabel.place(); 1295 this.right.generateOptimizedBoolean( 1296 currentScope, 1297 codeStream, 1298 trueLabel, 1299 falseLabel, 1300 false); 1301 if (valueRequired) { 1302 if (falseLabel != null) { 1303 codeStream.goto_(falseLabel); 1305 } 1306 } 1307 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1309 } 1310 return; 1311 } 1312 } 1313 this.left.generateCode(currentScope, codeStream, valueRequired); 1315 this.right.generateCode(currentScope, codeStream, valueRequired); 1316 if (valueRequired) { 1317 codeStream.iand(); 1318 if (falseLabel == null) { 1319 if (trueLabel != null) { 1320 codeStream.ifne(trueLabel); 1322 } 1323 } else { 1324 if (trueLabel == null) { 1326 codeStream.ifeq(falseLabel); 1327 } else { 1328 } 1330 } 1331 } 1332 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1334} 1335 1336 1339public void generateOptimizedLogicalOr(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 1340 Constant condConst; 1341 if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { 1342 if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { 1343 if (condConst.booleanValue() == true) { 1344 this.left.generateOptimizedBoolean( 1346 currentScope, 1347 codeStream, 1348 trueLabel, 1349 falseLabel, 1350 false); 1351 BranchLabel internalFalseLabel = new BranchLabel(codeStream); 1352 this.right.generateOptimizedBoolean( 1353 currentScope, 1354 codeStream, 1355 trueLabel, 1356 internalFalseLabel, 1357 false); 1358 internalFalseLabel.place(); 1359 if (valueRequired) { 1360 if (trueLabel != null) { 1361 codeStream.goto_(trueLabel); 1362 } 1363 } 1364 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1366 } else { 1367 this.left.generateOptimizedBoolean( 1369 currentScope, 1370 codeStream, 1371 trueLabel, 1372 falseLabel, 1373 false); 1374 this.right.generateOptimizedBoolean( 1375 currentScope, 1376 codeStream, 1377 trueLabel, 1378 falseLabel, 1379 valueRequired); 1380 } 1381 return; 1382 } 1383 if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1384 if (condConst.booleanValue() == true) { 1385 BranchLabel internalFalseLabel = new BranchLabel(codeStream); 1387 this.left.generateOptimizedBoolean( 1388 currentScope, 1389 codeStream, 1390 trueLabel, 1391 internalFalseLabel, 1392 false); 1393 internalFalseLabel.place(); 1394 this.right.generateOptimizedBoolean( 1395 currentScope, 1396 codeStream, 1397 trueLabel, 1398 falseLabel, 1399 false); 1400 if (valueRequired) { 1401 if (trueLabel != null) { 1402 codeStream.goto_(trueLabel); 1403 } 1404 } 1405 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1407 } else { 1408 this.left.generateOptimizedBoolean( 1410 currentScope, 1411 codeStream, 1412 trueLabel, 1413 falseLabel, 1414 valueRequired); 1415 this.right.generateOptimizedBoolean( 1416 currentScope, 1417 codeStream, 1418 trueLabel, 1419 falseLabel, 1420 false); 1421 } 1422 return; 1423 } 1424 } 1425 this.left.generateCode(currentScope, codeStream, valueRequired); 1427 this.right.generateCode(currentScope, codeStream, valueRequired); 1428 if (valueRequired) { 1429 codeStream.ior(); 1430 if (falseLabel == null) { 1431 if (trueLabel != null) { 1432 codeStream.ifne(trueLabel); 1434 } 1435 } else { 1436 if (trueLabel == null) { 1438 codeStream.ifeq(falseLabel); 1439 } else { 1440 } 1442 } 1443 } 1444 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1446} 1447 1448 1451public void generateOptimizedLogicalXor(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 1452 Constant condConst; 1453 if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { 1454 if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { 1455 if (condConst.booleanValue() == true) { 1456 this.left.generateOptimizedBoolean( 1458 currentScope, 1459 codeStream, 1460 trueLabel, 1461 falseLabel, 1462 false); 1463 this.right.generateOptimizedBoolean( 1464 currentScope, 1465 codeStream, 1466 falseLabel, trueLabel, 1468 valueRequired); 1469 } else { 1470 this.left.generateOptimizedBoolean( 1472 currentScope, 1473 codeStream, 1474 trueLabel, 1475 falseLabel, 1476 false); 1477 this.right.generateOptimizedBoolean( 1478 currentScope, 1479 codeStream, 1480 trueLabel, 1481 falseLabel, 1482 valueRequired); 1483 } 1484 return; 1485 } 1486 if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1487 if (condConst.booleanValue() == true) { 1488 this.left.generateOptimizedBoolean( 1490 currentScope, 1491 codeStream, 1492 falseLabel, trueLabel, 1494 valueRequired); 1495 this.right.generateOptimizedBoolean( 1496 currentScope, 1497 codeStream, 1498 trueLabel, 1499 falseLabel, 1500 false); 1501 } else { 1502 this.left.generateOptimizedBoolean( 1504 currentScope, 1505 codeStream, 1506 trueLabel, 1507 falseLabel, 1508 valueRequired); 1509 this.right.generateOptimizedBoolean( 1510 currentScope, 1511 codeStream, 1512 trueLabel, 1513 falseLabel, 1514 false); 1515 } 1516 return; 1517 } 1518 } 1519 this.left.generateCode(currentScope, codeStream, valueRequired); 1521 this.right.generateCode(currentScope, codeStream, valueRequired); 1522 if (valueRequired) { 1523 codeStream.ixor(); 1524 if (falseLabel == null) { 1525 if (trueLabel != null) { 1526 codeStream.ifne(trueLabel); 1528 } 1529 } else { 1530 if (trueLabel == null) { 1532 codeStream.ifeq(falseLabel); 1533 } else { 1534 } 1536 } 1537 } 1538 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 1540} 1541 1542public void generateOptimizedStringConcatenation(BlockScope blockScope, CodeStream codeStream, int typeID) { 1543 1549 1550 if ((((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) 1551 && ((this.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)) { 1552 if (this.constant != Constant.NotAConstant) { 1553 codeStream.generateConstant(this.constant, this.implicitConversion); 1554 codeStream.invokeStringConcatenationAppendForType(this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); 1555 } else { 1556 int pc = codeStream.position; 1557 this.left.generateOptimizedStringConcatenation( 1558 blockScope, 1559 codeStream, 1560 this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK); 1561 codeStream.recordPositionsFrom(pc, this.left.sourceStart); 1562 pc = codeStream.position; 1563 this.right.generateOptimizedStringConcatenation( 1564 blockScope, 1565 codeStream, 1566 this.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); 1567 codeStream.recordPositionsFrom(pc, this.right.sourceStart); 1568 } 1569 } else { 1570 super.generateOptimizedStringConcatenation(blockScope, codeStream, typeID); 1571 } 1572} 1573 1574public void generateOptimizedStringConcatenationCreation(BlockScope blockScope, CodeStream codeStream, int typeID) { 1575 1581 if ((((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) 1582 && ((this.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)) { 1583 if (this.constant != Constant.NotAConstant) { 1584 codeStream.newStringContatenation(); codeStream.dup(); 1586 codeStream.ldc(this.constant.stringValue()); 1587 codeStream.invokeStringConcatenationStringConstructor(); 1588 } else { 1590 int pc = codeStream.position; 1591 this.left.generateOptimizedStringConcatenationCreation( 1592 blockScope, 1593 codeStream, 1594 this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK); 1595 codeStream.recordPositionsFrom(pc, this.left.sourceStart); 1596 pc = codeStream.position; 1597 this.right.generateOptimizedStringConcatenation( 1598 blockScope, 1599 codeStream, 1600 this.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); 1601 codeStream.recordPositionsFrom(pc, this.right.sourceStart); 1602 } 1603 } else { 1604 super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID); 1605 } 1606} 1607 1608public boolean isCompactableOperation() { 1609 return true; 1610} 1611 1612 1619void nonRecursiveResolveTypeUpwards(BlockScope scope) { 1620 boolean leftIsCast, rightIsCast; 1622 TypeBinding leftType = this.left.resolvedType; 1623 1624 if ((rightIsCast = this.right instanceof CastExpression) == true) { 1625 this.right.bits |= ASTNode.DisableUnnecessaryCastCheck; } 1627 TypeBinding rightType = this.right.resolveType(scope); 1628 1629 if (leftType == null || rightType == null) { 1631 this.constant = Constant.NotAConstant; 1632 return; 1633 } 1634 1635 int leftTypeID = leftType.id; 1636 int rightTypeID = rightType.id; 1637 1638 boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; 1640 if (use15specifics) { 1641 if (!leftType.isBaseType() && rightTypeID != TypeIds.T_JavaLangString && rightTypeID != TypeIds.T_null) { 1642 leftTypeID = scope.environment().computeBoxingType(leftType).id; 1643 } 1644 if (!rightType.isBaseType() && leftTypeID != TypeIds.T_JavaLangString && leftTypeID != TypeIds.T_null) { 1645 rightTypeID = scope.environment().computeBoxingType(rightType).id; 1646 } 1647 } 1648 if (leftTypeID > 15 1649 || rightTypeID > 15) { if (leftTypeID == TypeIds.T_JavaLangString) { 1651 rightTypeID = TypeIds.T_JavaLangObject; 1652 } else if (rightTypeID == TypeIds.T_JavaLangString) { 1653 leftTypeID = TypeIds.T_JavaLangObject; 1654 } else { 1655 this.constant = Constant.NotAConstant; 1656 scope.problemReporter().invalidOperator(this, leftType, rightType); 1657 return; 1658 } 1659 } 1660 if (((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) { 1661 if (leftTypeID == TypeIds.T_JavaLangString) { 1662 this.left.computeConversion(scope, leftType, leftType); 1663 if (rightType.isArrayType() && ((ArrayBinding) rightType).elementsType() == TypeBinding.CHAR) { 1664 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(this.right); 1665 } 1666 } 1667 if (rightTypeID == TypeIds.T_JavaLangString) { 1668 this.right.computeConversion(scope, rightType, rightType); 1669 if (leftType.isArrayType() && ((ArrayBinding) leftType).elementsType() == TypeBinding.CHAR) { 1670 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(this.left); 1671 } 1672 } 1673 } 1674 1675 1680 int operator = (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT; 1683 int operatorSignature = OperatorExpression.OperatorSignatures[operator][(leftTypeID << 4) + rightTypeID]; 1684 1685 this.left.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), leftType); 1686 this.right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), rightType); 1687 this.bits |= operatorSignature & 0xF; 1688 switch (operatorSignature & 0xF) { case T_boolean : 1691 this.resolvedType = TypeBinding.BOOLEAN; 1692 break; 1693 case T_byte : 1694 this.resolvedType = TypeBinding.BYTE; 1695 break; 1696 case T_char : 1697 this.resolvedType = TypeBinding.CHAR; 1698 break; 1699 case T_double : 1700 this.resolvedType = TypeBinding.DOUBLE; 1701 break; 1702 case T_float : 1703 this.resolvedType = TypeBinding.FLOAT; 1704 break; 1705 case T_int : 1706 this.resolvedType = TypeBinding.INT; 1707 break; 1708 case T_long : 1709 this.resolvedType = TypeBinding.LONG; 1710 break; 1711 case T_JavaLangString : 1712 this.resolvedType = scope.getJavaLangString(); 1713 break; 1714 default : this.constant = Constant.NotAConstant; 1716 scope.problemReporter().invalidOperator(this, leftType, rightType); 1717 return; 1718 } 1719 1720 if ((leftIsCast = (this.left instanceof CastExpression)) == true || 1722 rightIsCast) { 1723 CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, this.left, leftTypeID, leftIsCast, this.right, rightTypeID, rightIsCast); 1724 } 1725 computeConstant(scope, leftTypeID, rightTypeID); 1727} 1728 1729public void optimizedBooleanConstant(int leftId, int operator, int rightId) { 1730 switch (operator) { 1731 case AND : 1732 if ((leftId != TypeIds.T_boolean) || (rightId != TypeIds.T_boolean)) 1733 return; 1734 case AND_AND : 1735 Constant cst; 1736 if ((cst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { 1737 if (cst.booleanValue() == false) { this.optimizedBooleanConstant = cst; return; 1740 } else { if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1742 this.optimizedBooleanConstant = cst; 1743 } 1745 return; 1746 } 1747 } 1748 if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1749 if (cst.booleanValue() == false) { this.optimizedBooleanConstant = cst; } 1752 } 1753 return; 1754 case OR : 1755 if ((leftId != TypeIds.T_boolean) || (rightId != TypeIds.T_boolean)) 1756 return; 1757 case OR_OR : 1758 if ((cst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { 1759 if (cst.booleanValue() == true) { this.optimizedBooleanConstant = cst; return; 1762 } else { if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1764 this.optimizedBooleanConstant = cst; 1765 } 1766 return; 1767 } 1768 } 1769 if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { 1770 if (cst.booleanValue() == true) { this.optimizedBooleanConstant = cst; } 1773 } 1774 } 1775} 1776 1777public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { 1778 this.left.printExpression(indent, output).append(' ').append(operatorToString()).append(' '); 1781 return this.right.printExpression(0, output); 1782} 1783 1784public TypeBinding resolveType(BlockScope scope) { 1785 boolean leftIsCast, rightIsCast; 1788 if ((leftIsCast = this.left instanceof CastExpression) == true) this.left.bits |= ASTNode.DisableUnnecessaryCastCheck; TypeBinding leftType = this.left.resolveType(scope); 1790 1791 if ((rightIsCast = this.right instanceof CastExpression) == true) this.right.bits |= ASTNode.DisableUnnecessaryCastCheck; TypeBinding rightType = this.right.resolveType(scope); 1793 1794 if (leftType == null || rightType == null) { 1796 this.constant = Constant.NotAConstant; 1797 return null; 1798 } 1799 1800 int leftTypeID = leftType.id; 1801 int rightTypeID = rightType.id; 1802 1803 boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; 1805 if (use15specifics) { 1806 if (!leftType.isBaseType() && rightTypeID != TypeIds.T_JavaLangString && rightTypeID != TypeIds.T_null) { 1807 leftTypeID = scope.environment().computeBoxingType(leftType).id; 1808 } 1809 if (!rightType.isBaseType() && leftTypeID != TypeIds.T_JavaLangString && leftTypeID != TypeIds.T_null) { 1810 rightTypeID = scope.environment().computeBoxingType(rightType).id; 1811 } 1812 } 1813 if (leftTypeID > 15 1814 || rightTypeID > 15) { if (leftTypeID == TypeIds.T_JavaLangString) { 1816 rightTypeID = TypeIds.T_JavaLangObject; 1817 } else if (rightTypeID == TypeIds.T_JavaLangString) { 1818 leftTypeID = TypeIds.T_JavaLangObject; 1819 } else { 1820 this.constant = Constant.NotAConstant; 1821 scope.problemReporter().invalidOperator(this, leftType, rightType); 1822 return null; 1823 } 1824 } 1825 if (((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) { 1826 if (leftTypeID == TypeIds.T_JavaLangString) { 1827 this.left.computeConversion(scope, leftType, leftType); 1828 if (rightType.isArrayType() && ((ArrayBinding) rightType).elementsType() == TypeBinding.CHAR) { 1829 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(this.right); 1830 } 1831 } 1832 if (rightTypeID == TypeIds.T_JavaLangString) { 1833 this.right.computeConversion(scope, rightType, rightType); 1834 if (leftType.isArrayType() && ((ArrayBinding) leftType).elementsType() == TypeBinding.CHAR) { 1835 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(this.left); 1836 } 1837 } 1838 } 1839 1840 1845 int operator = (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT; 1848 int operatorSignature = OperatorExpression.OperatorSignatures[operator][(leftTypeID << 4) + rightTypeID]; 1849 1850 this.left.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), leftType); 1851 this.right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), rightType); 1852 this.bits |= operatorSignature & 0xF; 1853 switch (operatorSignature & 0xF) { case T_boolean : 1856 this.resolvedType = TypeBinding.BOOLEAN; 1857 break; 1858 case T_byte : 1859 this.resolvedType = TypeBinding.BYTE; 1860 break; 1861 case T_char : 1862 this.resolvedType = TypeBinding.CHAR; 1863 break; 1864 case T_double : 1865 this.resolvedType = TypeBinding.DOUBLE; 1866 break; 1867 case T_float : 1868 this.resolvedType = TypeBinding.FLOAT; 1869 break; 1870 case T_int : 1871 this.resolvedType = TypeBinding.INT; 1872 break; 1873 case T_long : 1874 this.resolvedType = TypeBinding.LONG; 1875 break; 1876 case T_JavaLangString : 1877 this.resolvedType = scope.getJavaLangString(); 1878 break; 1879 default : this.constant = Constant.NotAConstant; 1881 scope.problemReporter().invalidOperator(this, leftType, rightType); 1882 return null; 1883 } 1884 1885 if (leftIsCast || rightIsCast) { 1887 CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, this.left, leftTypeID, leftIsCast, this.right, rightTypeID, rightIsCast); 1888 } 1889 computeConstant(scope, leftTypeID, rightTypeID); 1891 return this.resolvedType; 1892} 1893 1894public void traverse(ASTVisitor visitor, BlockScope scope) { 1895 if (visitor.visit(this, scope)) { 1896 this.left.traverse(visitor, scope); 1897 this.right.traverse(visitor, scope); 1898 } 1899 visitor.endVisit(this, scope); 1900} 1901} 1902 | Popular Tags |