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.classfmt.ClassFileConstants; 15 import org.eclipse.jdt.internal.compiler.codegen.*; 16 import org.eclipse.jdt.internal.compiler.flow.*; 17 import org.eclipse.jdt.internal.compiler.impl.Constant; 18 import org.eclipse.jdt.internal.compiler.lookup.*; 19 20 public class TryStatement extends SubRoutineStatement { 21 22 private final static char[] SECRET_RETURN_ADDRESS_NAME = " returnAddress".toCharArray(); private final static char[] SECRET_ANY_HANDLER_NAME = " anyExceptionHandler".toCharArray(); private final static char[] SECRET_RETURN_VALUE_NAME = " returnValue".toCharArray(); 26 public Block tryBlock; 27 public Block[] catchBlocks; 28 29 public Argument[] catchArguments; 30 31 33 public Block finallyBlock; 34 BlockScope scope; 35 36 public UnconditionalFlowInfo subRoutineInits; 37 ReferenceBinding[] caughtExceptionTypes; 38 boolean[] catchExits; 39 40 BranchLabel subRoutineStartLabel; 41 public LocalVariableBinding anyExceptionVariable, 42 returnAddressVariable, 43 secretReturnValue; 44 45 ExceptionLabel[] declaredExceptionLabels; 47 private Object [] reusableJSRTargets; 49 private BranchLabel[] reusableJSRSequenceStartLabels; 50 private int[] reusableJSRStateIndexes; 51 private int reusableJSRTargetsCount = 0; 52 53 private final static int NO_FINALLY = 0; private final static int FINALLY_SUBROUTINE = 1; private final static int FINALLY_DOES_NOT_COMPLETE = 2; private final static int FINALLY_INLINE = 3; 58 int mergedInitStateIndex = -1; 60 int preTryInitStateIndex = -1; 61 int naturalExitMergeInitStateIndex = -1; 62 int[] catchExitInitStateIndexes; 63 64 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { 65 66 71 73 this.preTryInitStateIndex = 74 currentScope.methodScope().recordInitializationStates(flowInfo); 75 76 if (this.anyExceptionVariable != null) { 77 this.anyExceptionVariable.useFlag = LocalVariableBinding.USED; 78 } 79 if (this.returnAddressVariable != null) { this.returnAddressVariable.useFlag = LocalVariableBinding.USED; 81 } 82 if (this.subRoutineStartLabel == null) { 83 ExceptionHandlingFlowContext handlingContext = 86 new ExceptionHandlingFlowContext( 87 flowContext, 88 this, 89 this.caughtExceptionTypes, 90 this.scope, 91 flowInfo.unconditionalInits()); 92 handlingContext.initsOnFinally = 93 new NullInfoRegistry(flowInfo.unconditionalInits()); 94 97 FlowInfo tryInfo; 98 if (this.tryBlock.isEmptyBlock()) { 99 tryInfo = flowInfo; 100 } else { 101 tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy()); 102 if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0) 103 this.bits |= ASTNode.IsTryBlockExiting; 104 } 105 106 handlingContext.complainIfUnusedExceptionHandlers(this.scope, this); 108 109 if (this.catchArguments != null) { 111 int catchCount; 112 this.catchExits = new boolean[catchCount = this.catchBlocks.length]; 113 this.catchExitInitStateIndexes = new int[catchCount]; 114 for (int i = 0; i < catchCount; i++) { 115 FlowInfo catchInfo; 117 if (this.caughtExceptionTypes[i].isUncheckedException(true)) { 118 catchInfo = 119 handlingContext.initsOnFinally.mitigateNullInfoOf( 120 flowInfo.unconditionalCopy(). 121 addPotentialInitializationsFrom( 122 handlingContext.initsOnException( 123 this.caughtExceptionTypes[i])). 124 addPotentialInitializationsFrom(tryInfo). 125 addPotentialInitializationsFrom( 126 handlingContext.initsOnReturn)); 127 } else { 128 catchInfo = 129 flowInfo.unconditionalCopy(). 130 addPotentialInitializationsFrom( 131 handlingContext.initsOnException( 132 this.caughtExceptionTypes[i])) 133 .addPotentialInitializationsFrom( 134 tryInfo.nullInfoLessUnconditionalCopy()) 135 .addPotentialInitializationsFrom( 138 handlingContext.initsOnReturn. 139 nullInfoLessUnconditionalCopy()); 140 } 141 142 LocalVariableBinding catchArg = this.catchArguments[i].binding; 144 catchInfo.markAsDefinitelyAssigned(catchArg); 145 catchInfo.markAsDefinitelyNonNull(catchArg); 146 153 if (this.tryBlock.statements == null) { 154 catchInfo.setReachMode(FlowInfo.UNREACHABLE); 155 } 156 catchInfo = 157 this.catchBlocks[i].analyseCode( 158 currentScope, 159 flowContext, 160 catchInfo); 161 this.catchExitInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(catchInfo); 162 this.catchExits[i] = 163 (catchInfo.tagBits & FlowInfo.UNREACHABLE) != 0; 164 tryInfo = tryInfo.mergedWith(catchInfo.unconditionalInits()); 165 } 166 } 167 this.mergedInitStateIndex = 168 currentScope.methodScope().recordInitializationStates(tryInfo); 169 170 if (flowContext.initsOnFinally != null) { 172 flowContext.initsOnFinally.add(handlingContext.initsOnFinally); 173 } 174 175 return tryInfo; 176 } else { 177 InsideSubRoutineFlowContext insideSubContext; 178 FinallyFlowContext finallyContext; 179 UnconditionalFlowInfo subInfo; 180 insideSubContext = new InsideSubRoutineFlowContext(flowContext, this); 182 183 subInfo = 184 this.finallyBlock 185 .analyseCode( 186 currentScope, 187 finallyContext = new FinallyFlowContext(flowContext, this.finallyBlock), 188 flowInfo.nullInfoLessUnconditionalCopy()) 189 .unconditionalInits(); 190 if (subInfo == FlowInfo.DEAD_END) { 191 this.bits |= ASTNode.IsSubRoutineEscaping; 192 this.scope.problemReporter().finallyMustCompleteNormally(this.finallyBlock); 193 } 194 this.subRoutineInits = subInfo; 195 ExceptionHandlingFlowContext handlingContext = 197 new ExceptionHandlingFlowContext( 198 insideSubContext, 199 this, 200 this.caughtExceptionTypes, 201 this.scope, 202 flowInfo.unconditionalInits()); 203 handlingContext.initsOnFinally = 204 new NullInfoRegistry(flowInfo.unconditionalInits()); 205 208 FlowInfo tryInfo; 209 if (this.tryBlock.isEmptyBlock()) { 210 tryInfo = flowInfo; 211 } else { 212 tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy()); 213 if ((tryInfo.tagBits & FlowInfo.UNREACHABLE) != 0) 214 this.bits |= ASTNode.IsTryBlockExiting; 215 } 216 217 handlingContext.complainIfUnusedExceptionHandlers(this.scope, this); 219 220 if (this.catchArguments != null) { 222 int catchCount; 223 this.catchExits = new boolean[catchCount = this.catchBlocks.length]; 224 this.catchExitInitStateIndexes = new int[catchCount]; 225 for (int i = 0; i < catchCount; i++) { 226 FlowInfo catchInfo; 228 if (this.caughtExceptionTypes[i].isUncheckedException(true)) { 229 catchInfo = 230 handlingContext.initsOnFinally.mitigateNullInfoOf( 231 flowInfo.unconditionalCopy(). 232 addPotentialInitializationsFrom( 233 handlingContext.initsOnException( 234 this.caughtExceptionTypes[i])). 235 addPotentialInitializationsFrom(tryInfo). 236 addPotentialInitializationsFrom( 237 handlingContext.initsOnReturn)); 238 }else { 239 catchInfo = 240 flowInfo.unconditionalCopy() 241 .addPotentialInitializationsFrom( 242 handlingContext.initsOnException( 243 this.caughtExceptionTypes[i])) 244 .addPotentialInitializationsFrom( 245 tryInfo.nullInfoLessUnconditionalCopy()) 246 .addPotentialInitializationsFrom( 249 handlingContext.initsOnReturn. 250 nullInfoLessUnconditionalCopy()); 251 } 252 253 LocalVariableBinding catchArg = this.catchArguments[i].binding; 255 catchInfo.markAsDefinitelyAssigned(catchArg); 256 catchInfo.markAsDefinitelyNonNull(catchArg); 257 264 if (this.tryBlock.statements == null) { 265 catchInfo.setReachMode(FlowInfo.UNREACHABLE); 266 } 267 catchInfo = 268 this.catchBlocks[i].analyseCode( 269 currentScope, 270 insideSubContext, 271 catchInfo); 272 this.catchExitInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(catchInfo); 273 this.catchExits[i] = 274 (catchInfo.tagBits & FlowInfo.UNREACHABLE) != 0; 275 tryInfo = tryInfo.mergedWith(catchInfo.unconditionalInits()); 276 } 277 } 278 finallyContext.complainOnDeferredChecks( 281 handlingContext.initsOnFinally.mitigateNullInfoOf( 282 (tryInfo.tagBits & FlowInfo.UNREACHABLE) == 0 ? 283 flowInfo.unconditionalCopy(). 284 addPotentialInitializationsFrom(tryInfo). 285 addPotentialInitializationsFrom(insideSubContext.initsOnReturn) : 288 insideSubContext.initsOnReturn), 289 currentScope); 290 291 if (flowContext.initsOnFinally != null) { 293 flowContext.initsOnFinally.add(handlingContext.initsOnFinally); 294 } 295 296 this.naturalExitMergeInitStateIndex = 297 currentScope.methodScope().recordInitializationStates(tryInfo); 298 if (subInfo == FlowInfo.DEAD_END) { 299 this.mergedInitStateIndex = 300 currentScope.methodScope().recordInitializationStates(subInfo); 301 return subInfo; 302 } else { 303 FlowInfo mergedInfo = tryInfo.addInitializationsFrom(subInfo); 304 this.mergedInitStateIndex = 305 currentScope.methodScope().recordInitializationStates(mergedInfo); 306 return mergedInfo; 307 } 308 } 309 } 310 311 public ExceptionLabel enterAnyExceptionHandler(CodeStream codeStream) { 312 if (this.subRoutineStartLabel == null) 313 return null; 314 return super.enterAnyExceptionHandler(codeStream); 315 } 316 317 public void enterDeclaredExceptionHandlers(CodeStream codeStream) { 318 for (int i = 0, length = this.declaredExceptionLabels == null ? 0 : this.declaredExceptionLabels.length; i < length; i++) { 319 this.declaredExceptionLabels[i].placeStart(); 320 } 321 } 322 323 public void exitAnyExceptionHandler() { 324 if (this.subRoutineStartLabel == null) 325 return; 326 super.exitAnyExceptionHandler(); 327 } 328 329 public void exitDeclaredExceptionHandlers(CodeStream codeStream) { 330 for (int i = 0, length = this.declaredExceptionLabels == null ? 0 : this.declaredExceptionLabels.length; i < length; i++) { 331 this.declaredExceptionLabels[i].placeEnd(); 332 } 333 } 334 335 private int finallyMode() { 336 if (this.subRoutineStartLabel == null) { 337 return NO_FINALLY; 338 } else if (isSubRoutineEscaping()) { 339 return FINALLY_DOES_NOT_COMPLETE; 340 } else if (scope.compilerOptions().inlineJsrBytecode) { 341 return FINALLY_INLINE; 342 } else { 343 return FINALLY_SUBROUTINE; 344 } 345 } 346 351 public void generateCode(BlockScope currentScope, CodeStream codeStream) { 352 if ((this.bits & ASTNode.IsReachable) == 0) { 353 return; 354 } 355 boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream; 356 this.anyExceptionLabel = null; 359 this.reusableJSRTargets = null; 360 this.reusableJSRSequenceStartLabels = null; 361 this.reusableJSRTargetsCount = 0; 362 363 int pc = codeStream.position; 364 int finallyMode = finallyMode(); 365 366 boolean requiresNaturalExit = false; 367 int maxCatches = this.catchArguments == null ? 0 : this.catchArguments.length; 369 ExceptionLabel[] exceptionLabels; 370 if (maxCatches > 0) { 371 exceptionLabels = new ExceptionLabel[maxCatches]; 372 for (int i = 0; i < maxCatches; i++) { 373 ExceptionLabel exceptionLabel = new ExceptionLabel(codeStream, this.catchArguments[i].binding.type); 374 exceptionLabel.placeStart(); 375 exceptionLabels[i] = exceptionLabel; 376 } 377 } else { 378 exceptionLabels = null; 379 } 380 if (this.subRoutineStartLabel != null) { 381 this.subRoutineStartLabel.initialize(codeStream); 382 this.enterAnyExceptionHandler(codeStream); 383 } 384 try { 386 this.declaredExceptionLabels = exceptionLabels; 387 this.tryBlock.generateCode(this.scope, codeStream); 388 } finally { 389 this.declaredExceptionLabels = null; 390 } 391 boolean tryBlockHasSomeCode = codeStream.position != pc; 392 394 if (tryBlockHasSomeCode) { 396 BranchLabel naturalExitLabel = new BranchLabel(codeStream); 398 BranchLabel postCatchesFinallyLabel = null; 399 for (int i = 0; i < maxCatches; i++) { 400 exceptionLabels[i].placeEnd(); 401 } 402 if ((this.bits & ASTNode.IsTryBlockExiting) == 0) { 403 int position = codeStream.position; 404 switch(finallyMode) { 405 case FINALLY_SUBROUTINE : 406 case FINALLY_INLINE : 407 requiresNaturalExit = true; 408 if (this.naturalExitMergeInitStateIndex != -1) { 409 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 410 codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 411 } 412 codeStream.goto_(naturalExitLabel); 413 break; 414 case NO_FINALLY : 415 if (this.naturalExitMergeInitStateIndex != -1) { 416 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 417 codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 418 } 419 codeStream.goto_(naturalExitLabel); 420 break; 421 case FINALLY_DOES_NOT_COMPLETE : 422 codeStream.goto_(this.subRoutineStartLabel); 423 break; 424 } 425 codeStream.updateLastRecordedEndPC(this.tryBlock.scope, position); 426 } 428 432 this.exitAnyExceptionHandler(); 433 if (this.catchArguments != null) { 434 postCatchesFinallyLabel = new BranchLabel(codeStream); 435 436 for (int i = 0; i < maxCatches; i++) { 437 enterAnyExceptionHandler(codeStream); 438 if (this.preTryInitStateIndex != -1) { 440 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); 441 codeStream.addDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); 442 } 443 codeStream.pushOnStack(exceptionLabels[i].exceptionType); 444 exceptionLabels[i].place(); 445 LocalVariableBinding catchVar; 447 int varPC = codeStream.position; 448 if ((catchVar = this.catchArguments[i].binding).resolvedPosition != -1) { 449 codeStream.store(catchVar, false); 450 catchVar.recordInitializationStartPC(codeStream.position); 451 codeStream.addVisibleLocalVariable(catchVar); 452 } else { 453 codeStream.pop(); 454 } 455 codeStream.recordPositionsFrom(varPC, this.catchArguments[i].sourceStart); 456 this.catchBlocks[i].generateCode(this.scope, codeStream); 459 this.exitAnyExceptionHandler(); 460 if (!this.catchExits[i]) { 461 switch(finallyMode) { 462 case FINALLY_INLINE : 463 if (isStackMapFrameCodeStream) { 465 ((StackMapFrameCodeStream) codeStream).pushStateIndex(this.naturalExitMergeInitStateIndex); 466 } 467 if (this.catchExitInitStateIndexes[i] != -1) { 468 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.catchExitInitStateIndexes[i]); 469 codeStream.addDefinitelyAssignedVariables(currentScope, this.catchExitInitStateIndexes[i]); 470 } 471 this.finallyBlock.generateCode(this.scope, codeStream); 473 codeStream.goto_(postCatchesFinallyLabel); 474 if (isStackMapFrameCodeStream) { 475 ((StackMapFrameCodeStream) codeStream).popStateIndex(); 476 } 477 break; 478 case FINALLY_SUBROUTINE : 479 requiresNaturalExit = true; 480 case NO_FINALLY : 482 if (this.naturalExitMergeInitStateIndex != -1) { 483 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 484 codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 485 } 486 codeStream.goto_(naturalExitLabel); 487 break; 488 case FINALLY_DOES_NOT_COMPLETE : 489 codeStream.goto_(this.subRoutineStartLabel); 490 break; 491 } 492 } 493 } 494 } 495 ExceptionLabel naturalExitExceptionHandler = requiresNaturalExit && (finallyMode == FINALLY_SUBROUTINE) 497 ? new ExceptionLabel(codeStream, null) 498 : null; 499 500 int finallySequenceStartPC = codeStream.position; 503 if (this.subRoutineStartLabel != null) { 504 codeStream.pushOnStack(this.scope.getJavaLangThrowable()); 505 if (this.preTryInitStateIndex != -1) { 506 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); 508 codeStream.addDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); 509 } 510 this.placeAllAnyExceptionHandler(); 511 if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place(); 512 513 switch(finallyMode) { 514 case FINALLY_SUBROUTINE : 515 codeStream.store(this.anyExceptionVariable, false); 517 codeStream.jsr(this.subRoutineStartLabel); 518 codeStream.recordPositionsFrom(finallySequenceStartPC, this.finallyBlock.sourceStart); 519 int position = codeStream.position; 520 codeStream.throwAnyException(this.anyExceptionVariable); 521 codeStream.recordPositionsFrom(position, this.finallyBlock.sourceEnd); 522 this.subRoutineStartLabel.place(); 524 codeStream.pushOnStack(this.scope.getJavaLangThrowable()); 525 position = codeStream.position; 526 codeStream.store(this.returnAddressVariable, false); 527 codeStream.recordPositionsFrom(position, this.finallyBlock.sourceStart); 528 this.finallyBlock.generateCode(this.scope, codeStream); 529 position = codeStream.position; 530 codeStream.ret(this.returnAddressVariable.resolvedPosition); 531 codeStream.recordPositionsFrom( 532 position, 533 this.finallyBlock.sourceEnd); 534 break; 536 case FINALLY_INLINE : 537 codeStream.store(this.anyExceptionVariable, false); 539 codeStream.recordPositionsFrom(finallySequenceStartPC, this.finallyBlock.sourceStart); 540 this.finallyBlock.generateCode(currentScope, codeStream); 542 position = codeStream.position; 543 codeStream.throwAnyException(this.anyExceptionVariable); 544 if (this.preTryInitStateIndex != -1) { 545 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); 546 } 547 this.subRoutineStartLabel.place(); 548 codeStream.recordPositionsFrom(position, this.finallyBlock.sourceEnd); 549 break; 550 case FINALLY_DOES_NOT_COMPLETE : 551 codeStream.pop(); 553 this.subRoutineStartLabel.place(); 554 codeStream.recordPositionsFrom(finallySequenceStartPC, this.finallyBlock.sourceStart); 555 this.finallyBlock.generateCode(this.scope, codeStream); 557 break; 558 } 559 560 if (requiresNaturalExit) { 562 switch(finallyMode) { 563 case FINALLY_SUBROUTINE : 564 naturalExitLabel.place(); 565 int position = codeStream.position; 566 naturalExitExceptionHandler.placeStart(); 567 codeStream.jsr(this.subRoutineStartLabel); 568 naturalExitExceptionHandler.placeEnd(); 569 codeStream.recordPositionsFrom( 570 position, 571 this.finallyBlock.sourceEnd); 572 break; 573 case FINALLY_INLINE : 574 if (isStackMapFrameCodeStream) { 576 ((StackMapFrameCodeStream) codeStream).pushStateIndex(this.naturalExitMergeInitStateIndex); 577 } 578 if (this.naturalExitMergeInitStateIndex != -1) { 579 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 580 codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 581 } 582 naturalExitLabel.place(); 583 this.finallyBlock.generateCode(this.scope, codeStream); 585 if (postCatchesFinallyLabel != null) { 586 position = codeStream.position; 587 codeStream.goto_(postCatchesFinallyLabel); 589 codeStream.recordPositionsFrom( 590 position, 591 this.finallyBlock.sourceEnd); 592 } 593 if (isStackMapFrameCodeStream) { 594 ((StackMapFrameCodeStream) codeStream).popStateIndex(); 595 } 596 break; 597 case FINALLY_DOES_NOT_COMPLETE : 598 break; 599 default : 600 naturalExitLabel.place(); 601 break; 602 } 603 } 604 if (postCatchesFinallyLabel != null) { 605 postCatchesFinallyLabel.place(); 606 } 607 } else { 608 naturalExitLabel.place(); 610 } 611 } else { 612 if (this.subRoutineStartLabel != null) { 614 this.finallyBlock.generateCode(this.scope, codeStream); 615 } 616 } 617 if (this.mergedInitStateIndex != -1) { 619 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); 620 codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); 621 } 622 codeStream.recordPositionsFrom(pc, this.sourceStart); 623 } 624 625 628 public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) { 629 630 boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream; 631 int finallyMode = finallyMode(); 632 switch(finallyMode) { 633 case FINALLY_DOES_NOT_COMPLETE : 634 codeStream.goto_(this.subRoutineStartLabel); 635 return true; 636 637 case NO_FINALLY : 638 exitDeclaredExceptionHandlers(codeStream); 639 return false; 640 } 641 if (targetLocation != null) { 643 boolean reuseTargetLocation = true; 644 if (this.reusableJSRTargetsCount > 0) { 645 nextReusableTarget: for (int i = 0, count = this.reusableJSRTargetsCount; i < count; i++) { 646 Object reusableJSRTarget = this.reusableJSRTargets[i]; 647 differentTarget: { 648 if (targetLocation == reusableJSRTarget) 649 break differentTarget; 650 if (targetLocation instanceof Constant 651 && reusableJSRTarget instanceof Constant 652 && ((Constant)targetLocation).hasSameValue((Constant) reusableJSRTarget)) { 653 break differentTarget; 654 } 655 continue nextReusableTarget; 657 } 658 if ((this.reusableJSRStateIndexes[i] != stateIndex) && finallyMode == FINALLY_INLINE && isStackMapFrameCodeStream) { 660 reuseTargetLocation = false; 661 break nextReusableTarget; 662 } else { 663 codeStream.goto_(this.reusableJSRSequenceStartLabels[i]); 664 return true; 665 } 666 } 667 } else { 668 this.reusableJSRTargets = new Object [3]; 669 this.reusableJSRSequenceStartLabels = new BranchLabel[3]; 670 this.reusableJSRStateIndexes = new int[3]; 671 } 672 if (reuseTargetLocation) { 673 if (this.reusableJSRTargetsCount == this.reusableJSRTargets.length) { 674 System.arraycopy(this.reusableJSRTargets, 0, this.reusableJSRTargets = new Object [2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount); 675 System.arraycopy(this.reusableJSRSequenceStartLabels, 0, this.reusableJSRSequenceStartLabels = new BranchLabel[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount); 676 System.arraycopy(this.reusableJSRStateIndexes, 0, this.reusableJSRStateIndexes = new int[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount); 677 } 678 this.reusableJSRTargets[this.reusableJSRTargetsCount] = targetLocation; 679 BranchLabel reusableJSRSequenceStartLabel = new BranchLabel(codeStream); 680 reusableJSRSequenceStartLabel.place(); 681 this.reusableJSRStateIndexes[this.reusableJSRTargetsCount] = stateIndex; 682 this.reusableJSRSequenceStartLabels[this.reusableJSRTargetsCount++] = reusableJSRSequenceStartLabel; 683 } 684 } 685 if (finallyMode == FINALLY_INLINE) { 686 if (isStackMapFrameCodeStream) { 687 ((StackMapFrameCodeStream) codeStream).pushStateIndex(stateIndex); 688 if (this.naturalExitMergeInitStateIndex != -1 || stateIndex != -1) { 689 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 691 codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 692 } 693 } else { 694 if (this.naturalExitMergeInitStateIndex != -1) { 695 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 697 codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); 698 } 699 } 700 if (secretLocal != null) { 701 codeStream.addVariable(secretLocal); 702 } 703 exitAnyExceptionHandler(); 706 exitDeclaredExceptionHandlers(codeStream); 707 this.finallyBlock.generateCode(currentScope, codeStream); 708 if (isStackMapFrameCodeStream) { 709 ((StackMapFrameCodeStream) codeStream).popStateIndex(); 710 } 711 } else { 712 codeStream.jsr(this.subRoutineStartLabel); 714 exitAnyExceptionHandler(); 715 exitDeclaredExceptionHandlers(codeStream); 716 } 717 return false; 718 } 719 public boolean isSubRoutineEscaping() { 720 return (this.bits & ASTNode.IsSubRoutineEscaping) != 0; 721 } 722 723 public StringBuffer printStatement(int indent, StringBuffer output) { 724 printIndent(indent, output).append("try \n"); this.tryBlock.printStatement(indent + 1, output); 726 727 if (this.catchBlocks != null) 729 for (int i = 0; i < this.catchBlocks.length; i++) { 730 output.append('\n'); 731 printIndent(indent, output).append("catch ("); this.catchArguments[i].print(0, output).append(") "); this.catchBlocks[i].printStatement(indent + 1, output); 734 } 735 if (this.finallyBlock != null) { 737 output.append('\n'); 738 printIndent(indent, output).append("finally\n"); this.finallyBlock.printStatement(indent + 1, output); 740 } 741 return output; 742 } 743 744 public void resolve(BlockScope upperScope) { 745 this.scope = new BlockScope(upperScope); 747 748 BlockScope tryScope = new BlockScope(this.scope); 749 BlockScope finallyScope = null; 750 751 if (this.finallyBlock != null) { 752 if (this.finallyBlock.isEmptyBlock()) { 753 if ((this.finallyBlock.bits & ASTNode.UndocumentedEmptyBlock) != 0) { 754 this.scope.problemReporter().undocumentedEmptyBlock(this.finallyBlock.sourceStart, this.finallyBlock.sourceEnd); 755 } 756 } else { 757 finallyScope = new BlockScope(this.scope, false); 759 MethodScope methodScope = this.scope.methodScope(); 761 762 if (!upperScope.compilerOptions().inlineJsrBytecode) { 764 this.returnAddressVariable = 765 new LocalVariableBinding(TryStatement.SECRET_RETURN_ADDRESS_NAME, upperScope.getJavaLangObject(), ClassFileConstants.AccDefault, false); 766 finallyScope.addLocalVariable(this.returnAddressVariable); 767 this.returnAddressVariable.setConstant(Constant.NotAConstant); } 769 this.subRoutineStartLabel = new BranchLabel(); 770 771 this.anyExceptionVariable = 772 new LocalVariableBinding(TryStatement.SECRET_ANY_HANDLER_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); 773 finallyScope.addLocalVariable(this.anyExceptionVariable); 774 this.anyExceptionVariable.setConstant(Constant.NotAConstant); 776 if (!methodScope.isInsideInitializer()) { 777 MethodBinding methodBinding = 778 ((AbstractMethodDeclaration) methodScope.referenceContext).binding; 779 if (methodBinding != null) { 780 TypeBinding methodReturnType = methodBinding.returnType; 781 if (methodReturnType.id != TypeIds.T_void) { 782 this.secretReturnValue = 783 new LocalVariableBinding( 784 TryStatement.SECRET_RETURN_VALUE_NAME, 785 methodReturnType, 786 ClassFileConstants.AccDefault, 787 false); 788 finallyScope.addLocalVariable(this.secretReturnValue); 789 this.secretReturnValue.setConstant(Constant.NotAConstant); } 791 } 792 } 793 this.finallyBlock.resolveUsing(finallyScope); 794 finallyScope.shiftScopes = new BlockScope[this.catchArguments == null ? 1 : this.catchArguments.length+1]; 796 finallyScope.shiftScopes[0] = tryScope; 797 } 798 } 799 this.tryBlock.resolveUsing(tryScope); 800 801 if (this.catchBlocks != null) { 803 int length = this.catchArguments.length; 804 TypeBinding[] argumentTypes = new TypeBinding[length]; 805 boolean catchHasError = false; 806 for (int i = 0; i < length; i++) { 807 BlockScope catchScope = new BlockScope(this.scope); 808 if (finallyScope != null){ 809 finallyScope.shiftScopes[i+1] = catchScope; 810 } 811 if ((argumentTypes[i] = this.catchArguments[i].resolveForCatch(catchScope)) == null) { 813 catchHasError = true; 814 } 815 this.catchBlocks[i].resolveUsing(catchScope); 816 } 817 if (catchHasError) { 818 return; 819 } 820 this.caughtExceptionTypes = new ReferenceBinding[length]; 823 for (int i = 0; i < length; i++) { 824 this.caughtExceptionTypes[i] = (ReferenceBinding) argumentTypes[i]; 825 for (int j = 0; j < i; j++) { 826 if (this.caughtExceptionTypes[i].isCompatibleWith(argumentTypes[j])) { 827 this.scope.problemReporter().wrongSequenceOfExceptionTypesError(this, this.caughtExceptionTypes[i], i, argumentTypes[j]); 828 } 829 } 830 } 831 } else { 832 this.caughtExceptionTypes = new ReferenceBinding[0]; 833 } 834 835 if (finallyScope != null){ 836 this.scope.addSubscope(finallyScope); 840 } 841 } 842 843 public void traverse(ASTVisitor visitor, BlockScope blockScope) { 844 if (visitor.visit(this, blockScope)) { 845 this.tryBlock.traverse(visitor, this.scope); 846 if (this.catchArguments != null) { 847 for (int i = 0, max = this.catchBlocks.length; i < max; i++) { 848 this.catchArguments[i].traverse(visitor, this.scope); 849 this.catchBlocks[i].traverse(visitor, this.scope); 850 } 851 } 852 if (this.finallyBlock != null) 853 this.finallyBlock.traverse(visitor, this.scope); 854 } 855 visitor.endVisit(this, blockScope); 856 } 857 } 858 | Popular Tags |