001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.codegen.inline; 018 019 import com.intellij.openapi.vfs.VirtualFile; 020 import com.intellij.psi.PsiElement; 021 import org.jetbrains.annotations.NotNull; 022 import org.jetbrains.annotations.Nullable; 023 import org.jetbrains.kotlin.builtins.InlineStrategy; 024 import org.jetbrains.kotlin.builtins.InlineUtil; 025 import org.jetbrains.kotlin.codegen.*; 026 import org.jetbrains.kotlin.codegen.binding.CodegenBinding; 027 import org.jetbrains.kotlin.codegen.context.CodegenContext; 028 import org.jetbrains.kotlin.codegen.context.MethodContext; 029 import org.jetbrains.kotlin.codegen.context.PackageContext; 030 import org.jetbrains.kotlin.codegen.state.GenerationState; 031 import org.jetbrains.kotlin.codegen.state.JetTypeMapper; 032 import org.jetbrains.kotlin.descriptors.*; 033 import org.jetbrains.kotlin.psi.*; 034 import org.jetbrains.kotlin.renderer.DescriptorRenderer; 035 import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; 036 import org.jetbrains.kotlin.resolve.DescriptorUtils; 037 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; 038 import org.jetbrains.kotlin.resolve.jvm.AsmTypes; 039 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind; 040 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; 041 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; 042 import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor; 043 import org.jetbrains.org.objectweb.asm.Label; 044 import org.jetbrains.org.objectweb.asm.MethodVisitor; 045 import org.jetbrains.org.objectweb.asm.Opcodes; 046 import org.jetbrains.org.objectweb.asm.Type; 047 import org.jetbrains.org.objectweb.asm.commons.Method; 048 import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; 049 import org.jetbrains.org.objectweb.asm.tree.LabelNode; 050 import org.jetbrains.org.objectweb.asm.tree.MethodNode; 051 import org.jetbrains.org.objectweb.asm.tree.TryCatchBlockNode; 052 053 import java.io.IOException; 054 import java.util.HashMap; 055 import java.util.List; 056 import java.util.ListIterator; 057 import java.util.Map; 058 059 import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags; 060 import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; 061 import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.addInlineMarker; 062 063 public class InlineCodegen extends CallGenerator { 064 private final GenerationState state; 065 private final JetTypeMapper typeMapper; 066 067 private final SimpleFunctionDescriptor functionDescriptor; 068 private final JvmMethodSignature jvmSignature; 069 private final JetElement callElement; 070 private final MethodContext context; 071 private final ExpressionCodegen codegen; 072 073 private final boolean asFunctionInline; 074 private final int initialFrameSize; 075 private final boolean isSameModule; 076 077 protected final ParametersBuilder invocationParamBuilder = ParametersBuilder.newBuilder(); 078 protected final Map<Integer, LambdaInfo> expressionMap = new HashMap<Integer, LambdaInfo>(); 079 080 private final ReifiedTypeInliner reifiedTypeInliner; 081 082 private LambdaInfo activeLambda; 083 084 public InlineCodegen( 085 @NotNull ExpressionCodegen codegen, 086 @NotNull GenerationState state, 087 @NotNull SimpleFunctionDescriptor functionDescriptor, 088 @NotNull JetElement callElement, 089 @Nullable ReifiedTypeParameterMappings typeParameterMappings 090 ) { 091 assert functionDescriptor.getInlineStrategy().isInline() : "InlineCodegen could inline only inline function but " + functionDescriptor; 092 093 this.state = state; 094 this.typeMapper = state.getTypeMapper(); 095 this.codegen = codegen; 096 this.callElement = callElement; 097 this.functionDescriptor = functionDescriptor.getOriginal(); 098 099 reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings); 100 101 initialFrameSize = codegen.getFrameMap().getCurrentSize(); 102 103 context = (MethodContext) getContext(functionDescriptor, state); 104 jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind()); 105 106 InlineStrategy inlineStrategy = 107 codegen.getContext().isInlineFunction() ? InlineStrategy.IN_PLACE : functionDescriptor.getInlineStrategy(); 108 this.asFunctionInline = false; 109 110 isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.getOutDirectory()); 111 } 112 113 @Override 114 public void genCallWithoutAssertions( 115 @NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen 116 ) { 117 genCall(callableMethod, null, false, codegen); 118 } 119 120 @Override 121 public void genCallInner(@NotNull CallableMethod callableMethod, @Nullable ResolvedCall<?> resolvedCall, boolean callDefault, @NotNull ExpressionCodegen codegen) { 122 MethodNode node = null; 123 124 try { 125 node = createMethodNode(callDefault); 126 endCall(inlineCall(node)); 127 } 128 catch (CompilationException e) { 129 throw e; 130 } 131 catch (Exception e) { 132 boolean generateNodeText = !(e instanceof InlineException); 133 PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(this.codegen.getContext().getContextDescriptor()); 134 throw new CompilationException("Couldn't inline method call '" + 135 functionDescriptor.getName() + 136 "' into \n" + (element != null ? element.getText() : "null psi element " + this.codegen.getContext().getContextDescriptor()) + 137 (generateNodeText ? ("\ncause: " + InlineCodegenUtil.getNodeText(node)) : ""), 138 e, callElement); 139 } 140 141 142 } 143 144 private void endCall(@NotNull InlineResult result) { 145 leaveTemps(); 146 147 codegen.propagateChildReifiedTypeParametersUsages(result.getReifiedTypeParametersUsages()); 148 149 state.getFactory().removeInlinedClasses(result.getClassesToRemove()); 150 } 151 152 @NotNull 153 private MethodNode createMethodNode(boolean callDefault) throws ClassNotFoundException, IOException { 154 JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind()); 155 156 Method asmMethod; 157 if (callDefault) { 158 asmMethod = typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind(), context); 159 } 160 else { 161 asmMethod = jvmSignature.getAsmMethod(); 162 } 163 164 MethodNode node; 165 if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) { 166 VirtualFile file = InlineCodegenUtil.getVirtualFileForCallable((DeserializedSimpleFunctionDescriptor) functionDescriptor, state); 167 node = InlineCodegenUtil.getMethodNode(file.contentsToByteArray(), asmMethod.getName(), asmMethod.getDescriptor()); 168 169 if (node == null) { 170 throw new RuntimeException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor)); 171 } 172 } 173 else { 174 PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor); 175 176 if (element == null) { 177 throw new RuntimeException("Couldn't find declaration for function " + descriptorName(functionDescriptor)); 178 } 179 180 node = new MethodNode(InlineCodegenUtil.API, 181 getMethodAsmFlags(functionDescriptor, context.getContextKind()) | (callDefault ? Opcodes.ACC_STATIC : 0), 182 asmMethod.getName(), 183 asmMethod.getDescriptor(), 184 jvmSignature.getGenericsSignature(), 185 null); 186 187 //for maxLocals calculation 188 MethodVisitor maxCalcAdapter = InlineCodegenUtil.wrapWithMaxLocalCalc(node); 189 MethodContext methodContext = context.getParentContext().intoFunction(functionDescriptor); 190 if (callDefault) { 191 FunctionCodegen.generateDefaultImplBody( 192 methodContext, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, 193 (JetNamedFunction) element, codegen.getParentCodegen() 194 ); 195 } 196 else { 197 generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, (JetDeclarationWithBody) element, jvmSignature); 198 } 199 maxCalcAdapter.visitMaxs(-1, -1); 200 maxCalcAdapter.visitEnd(); 201 } 202 return node; 203 } 204 205 private InlineResult inlineCall(MethodNode node) { 206 ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node.instructions); 207 generateClosuresBodies(); 208 209 //through generation captured parameters will be added to invocationParamBuilder 210 putClosureParametersOnStack(); 211 212 addInlineMarker(codegen.v, true); 213 214 Parameters parameters = invocationParamBuilder.buildParameters(); 215 216 InliningContext info = new RootInliningContext(expressionMap, 217 state, 218 codegen.getInlineNameGenerator() 219 .subGenerator(functionDescriptor.getName().asString()), 220 codegen.getContext(), 221 callElement, 222 codegen.getParentCodegen().getClassName(), reifiedTypeInliner); 223 224 MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule, "Method inlining " + callElement.getText()); //with captured 225 226 LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize); 227 228 229 MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode(); 230 InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL); 231 result.getReifiedTypeParametersUsages().mergeAll(reificationResult); 232 233 LabelOwner labelOwner = new LabelOwner() { 234 235 final CallableMemberDescriptor descriptor = codegen.getContext().getContextDescriptor(); 236 237 final boolean isLambda = CodegenBinding.isLocalFunOrLambda(descriptor) && descriptor.getName().isSpecial(); 238 239 @Override 240 public boolean isMyLabel(@NotNull String name) { 241 if (InlineCodegenUtil.ROOT_LABEL.equals(name)) { 242 return !isLambda; 243 } 244 else { 245 return descriptor.getName().asString().equals(name); 246 } 247 } 248 }; 249 List<MethodInliner.PointForExternalFinallyBlocks> infos = MethodInliner.processReturns(adapter, labelOwner, true, null); 250 generateAndInsertFinallyBlocks(adapter, infos); 251 252 adapter.accept(new InliningInstructionAdapter(codegen.v)); 253 254 addInlineMarker(codegen.v, false); 255 256 return result; 257 } 258 259 private void generateClosuresBodies() { 260 for (LambdaInfo info : expressionMap.values()) { 261 info.setNode(generateLambdaBody(info)); 262 } 263 } 264 265 private MethodNode generateLambdaBody(LambdaInfo info) { 266 JetFunctionLiteral declaration = info.getFunctionLiteral(); 267 FunctionDescriptor descriptor = info.getFunctionDescriptor(); 268 269 MethodContext parentContext = codegen.getContext(); 270 271 MethodContext context = parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor); 272 273 JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(descriptor); 274 Method asmMethod = jvmMethodSignature.getAsmMethod(); 275 MethodNode methodNode = new MethodNode(InlineCodegenUtil.API, getMethodAsmFlags(descriptor, context.getContextKind()), asmMethod.getName(), asmMethod.getDescriptor(), jvmMethodSignature.getGenericsSignature(), null); 276 277 MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode); 278 279 generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature); 280 adapter.visitMaxs(-1, -1); 281 282 return methodNode; 283 } 284 285 private void generateMethodBody( 286 @NotNull MethodVisitor adapter, 287 @NotNull FunctionDescriptor descriptor, 288 @NotNull MethodContext context, 289 @NotNull JetDeclarationWithBody declaration, 290 @NotNull JvmMethodSignature jvmMethodSignature 291 ) { 292 FunctionCodegen.generateMethodBody( 293 adapter, descriptor, context, jvmMethodSignature, 294 new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), 295 // Wrapping for preventing marking actual parent codegen as containing reifier markers 296 new FakeMemberCodegen(codegen.getParentCodegen()) 297 ); 298 } 299 300 private static class FakeMemberCodegen extends MemberCodegen { 301 private final MemberCodegen delegate; 302 public FakeMemberCodegen(@NotNull MemberCodegen wrapped) { 303 super(wrapped); 304 delegate = wrapped; 305 } 306 307 @Override 308 protected void generateDeclaration() { 309 throw new IllegalStateException(); 310 } 311 312 @Override 313 protected void generateBody() { 314 throw new IllegalStateException(); 315 } 316 317 @Override 318 protected void generateKotlinAnnotation() { 319 throw new IllegalStateException(); 320 } 321 322 @NotNull 323 @Override 324 public NameGenerator getInlineNameGenerator() { 325 return delegate.getInlineNameGenerator(); 326 } 327 } 328 329 @Override 330 public void afterParameterPut(@NotNull Type type, @Nullable StackValue stackValue, @Nullable ValueParameterDescriptor valueParameterDescriptor) { 331 putCapturedInLocal(type, stackValue, valueParameterDescriptor, -1); 332 } 333 334 private void putCapturedInLocal( 335 @NotNull Type type, @Nullable StackValue stackValue, @Nullable ValueParameterDescriptor valueParameterDescriptor, int capturedParamIndex 336 ) { 337 if (!asFunctionInline && Type.VOID_TYPE != type) { 338 //TODO remap only inlinable closure => otherwise we could get a lot of problem 339 boolean couldBeRemapped = !shouldPutValue(type, stackValue, valueParameterDescriptor); 340 StackValue remappedIndex = couldBeRemapped ? stackValue : null; 341 342 ParameterInfo info; 343 if (capturedParamIndex >= 0) { 344 CapturedParamDesc capturedParamInfoInLambda = activeLambda.getCapturedVars().get(capturedParamIndex); 345 info = invocationParamBuilder.addCapturedParam(capturedParamInfoInLambda, capturedParamInfoInLambda.getFieldName()); 346 info.setRemapValue(remappedIndex); 347 } 348 else { 349 info = invocationParamBuilder.addNextParameter(type, false, remappedIndex); 350 } 351 352 putParameterOnStack(info); 353 } 354 } 355 356 /*descriptor is null for captured vars*/ 357 public boolean shouldPutValue( 358 @NotNull Type type, 359 @Nullable StackValue stackValue, 360 @Nullable ValueParameterDescriptor descriptor 361 ) { 362 363 if (stackValue == null) { 364 //default or vararg 365 return true; 366 } 367 368 //remap only inline functions (and maybe non primitives) 369 //TODO - clean asserion and remapping logic 370 if (isPrimitive(type) != isPrimitive(stackValue.type)) { 371 //don't remap boxing/unboxing primitives - lost identity and perfomance 372 return true; 373 } 374 375 if (stackValue instanceof StackValue.Local) { 376 return false; 377 } 378 379 //skip direct capturing fields 380 StackValue receiver = null; 381 if (stackValue instanceof StackValue.Field) { 382 receiver = ((StackValue.Field) stackValue).receiver; 383 } 384 else if (stackValue instanceof StackValue.FieldForSharedVar) { 385 receiver = ((StackValue.Field) ((StackValue.FieldForSharedVar) stackValue).receiver).receiver; 386 } 387 388 if (!(receiver instanceof StackValue.Local)) { 389 return true; 390 } 391 392 //TODO: check type of context 393 return !(codegen.getContext().isInliningLambda() && descriptor != null && !InlineUtil.hasNoinlineAnnotation(descriptor)); 394 } 395 396 private void putParameterOnStack(ParameterInfo... infos) { 397 int[] index = new int[infos.length]; 398 for (int i = 0; i < infos.length; i++) { 399 ParameterInfo info = infos[i]; 400 if (!info.isSkippedOrRemapped()) { 401 index[i] = codegen.getFrameMap().enterTemp(info.getType()); 402 } 403 else { 404 index[i] = -1; 405 } 406 } 407 408 for (int i = infos.length - 1; i >= 0; i--) { 409 ParameterInfo info = infos[i]; 410 if (!info.isSkippedOrRemapped()) { 411 Type type = info.type; 412 StackValue.local(index[i], type).store(StackValue.onStack(type), codegen.v); 413 } 414 } 415 } 416 417 @Override 418 public void putHiddenParams() { 419 List<JvmMethodParameterSignature> valueParameters = jvmSignature.getValueParameters(); 420 421 if (!isStaticMethod(functionDescriptor, context)) { 422 invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false, null); 423 } 424 425 for (JvmMethodParameterSignature param : valueParameters) { 426 if (param.getKind() == JvmMethodParameterKind.VALUE) { 427 break; 428 } 429 invocationParamBuilder.addNextParameter(param.getAsmType(), false, null); 430 } 431 432 List<ParameterInfo> infos = invocationParamBuilder.listNotCaptured(); 433 putParameterOnStack(infos.toArray(new ParameterInfo[infos.size()])); 434 } 435 436 public void leaveTemps() { 437 FrameMap frameMap = codegen.getFrameMap(); 438 List<ParameterInfo> infos = invocationParamBuilder.listAllParams(); 439 for (ListIterator<? extends ParameterInfo> iterator = infos.listIterator(infos.size()); iterator.hasPrevious(); ) { 440 ParameterInfo param = iterator.previous(); 441 if (!param.isSkippedOrRemapped()) { 442 frameMap.leaveTemp(param.type); 443 } 444 } 445 } 446 447 public static boolean isInliningClosure(JetExpression expression, ValueParameterDescriptor valueParameterDescriptora) { 448 //TODO deparenthisise typed 449 JetExpression deparenthesize = JetPsiUtil.deparenthesize(expression); 450 return deparenthesize instanceof JetFunctionLiteralExpression && 451 !InlineUtil.hasNoinlineAnnotation(valueParameterDescriptora); 452 } 453 454 public void rememberClosure(JetExpression expression, Type type) { 455 JetFunctionLiteralExpression lambda = (JetFunctionLiteralExpression) JetPsiUtil.deparenthesize(expression); 456 assert lambda != null : "Couldn't find lambda in " + expression.getText(); 457 458 String labelNameIfPresent = null; 459 PsiElement parent = lambda.getParent(); 460 if (parent instanceof JetLabeledExpression) { 461 labelNameIfPresent = ((JetLabeledExpression) parent).getLabelName(); 462 } 463 LambdaInfo info = new LambdaInfo(lambda, typeMapper, labelNameIfPresent); 464 465 ParameterInfo closureInfo = invocationParamBuilder.addNextParameter(type, true, null); 466 closureInfo.setLambda(info); 467 expressionMap.put(closureInfo.getIndex(), info); 468 } 469 470 private void putClosureParametersOnStack() { 471 for (LambdaInfo next : expressionMap.values()) { 472 activeLambda = next; 473 codegen.pushClosureOnStack(next.getClassDescriptor(), true, this); 474 } 475 activeLambda = null; 476 } 477 478 public static CodegenContext getContext(DeclarationDescriptor descriptor, GenerationState state) { 479 if (descriptor instanceof PackageFragmentDescriptor) { 480 return new PackageContext((PackageFragmentDescriptor) descriptor, null, null); 481 } 482 483 CodegenContext parent = getContext(descriptor.getContainingDeclaration(), state); 484 485 if (descriptor instanceof ClassDescriptor) { 486 OwnerKind kind = DescriptorUtils.isTrait(descriptor) ? OwnerKind.TRAIT_IMPL : OwnerKind.IMPLEMENTATION; 487 return parent.intoClass((ClassDescriptor) descriptor, kind, state); 488 } 489 else if (descriptor instanceof FunctionDescriptor) { 490 return parent.intoFunction((FunctionDescriptor) descriptor); 491 } 492 493 throw new IllegalStateException("Couldn't build context for " + descriptorName(descriptor)); 494 } 495 496 private static boolean isStaticMethod(FunctionDescriptor functionDescriptor, MethodContext context) { 497 return (getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) != 0; 498 } 499 500 private static String descriptorName(DeclarationDescriptor descriptor) { 501 return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor); 502 } 503 504 @Override 505 public void genValueAndPut( 506 @NotNull ValueParameterDescriptor valueParameterDescriptor, 507 @NotNull JetExpression argumentExpression, 508 @NotNull Type parameterType 509 ) { 510 //TODO deparenthisise 511 if (isInliningClosure(argumentExpression, valueParameterDescriptor)) { 512 rememberClosure(argumentExpression, parameterType); 513 } else { 514 StackValue value = codegen.gen(argumentExpression); 515 putValueIfNeeded(valueParameterDescriptor, parameterType, value); 516 } 517 } 518 519 @Override 520 public void putValueIfNeeded(@Nullable ValueParameterDescriptor valueParameterDescriptor, @NotNull Type parameterType, @NotNull StackValue value) { 521 if (shouldPutValue(parameterType, value, valueParameterDescriptor)) { 522 value.put(parameterType, codegen.v); 523 } 524 afterParameterPut(parameterType, value, valueParameterDescriptor); 525 } 526 527 @Override 528 public void putCapturedValueOnStack( 529 @NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex 530 ) { 531 if (shouldPutValue(stackValue.type, stackValue, null)) { 532 stackValue.put(stackValue.type, codegen.v); 533 } 534 putCapturedInLocal(stackValue.type, stackValue, null, paramIndex); 535 } 536 537 538 public void generateAndInsertFinallyBlocks(MethodNode intoNode, List<MethodInliner.PointForExternalFinallyBlocks> insertPoints) { 539 if (!codegen.hasFinallyBlocks()) return; 540 541 Map<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks> extensionPoints = 542 new HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>(); 543 for (MethodInliner.PointForExternalFinallyBlocks insertPoint : insertPoints) { 544 extensionPoints.put(insertPoint.beforeIns, insertPoint); 545 } 546 547 DefaultProcessor processor = new DefaultProcessor(intoNode); 548 549 AbstractInsnNode curInstr = intoNode.instructions.getFirst(); 550 while (curInstr != null) { 551 processor.updateCoveringTryBlocks(curInstr, true); 552 553 MethodInliner.PointForExternalFinallyBlocks extension = extensionPoints.get(curInstr); 554 if (extension != null) { 555 Label start = new Label(); 556 Label end = new Label(); 557 558 MethodNode finallyNode = InlineCodegenUtil.createEmptyMethodNode(); 559 finallyNode.visitLabel(start); 560 561 ExpressionCodegen finallyCodegen = 562 new ExpressionCodegen(finallyNode, codegen.getFrameMap(), codegen.getReturnType(), 563 codegen.getContext(), codegen.getState(), codegen.getParentCodegen()); 564 finallyCodegen.addBlockStackElementsForNonLocalReturns(codegen.getBlockStackElements()); 565 566 finallyCodegen.generateFinallyBlocksIfNeeded(extension.returnType); 567 finallyNode.visitLabel(end); 568 569 //Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method 570 InlineCodegenUtil.insertNodeBefore(finallyNode, intoNode, curInstr); 571 572 List<TryCatchBlockNodeWrapper> blocks = processor.getCoveringFromInnermost(); 573 ListIterator<TryCatchBlockNodeWrapper> iterator = blocks.listIterator(blocks.size()); 574 while (iterator.hasPrevious()) { 575 TryCatchBlockNodeWrapper previous = iterator.previous(); 576 LabelNode oldStart = previous.getStartLabel(); 577 TryCatchBlockNode node = previous.getNode(); 578 node.start = (LabelNode) end.info; 579 processor.remapStartLabel(oldStart, previous); 580 581 TryCatchBlockNode additionalNode = new TryCatchBlockNode(oldStart, (LabelNode) start.info, node.handler, node.type); 582 processor.addNode(additionalNode); 583 } 584 } 585 586 curInstr = curInstr.getNext(); 587 } 588 589 processor.sortTryCatchBlocks(); 590 Iterable<TryCatchBlockNodeWrapper> nodes = processor.getNonEmptyNodes(); 591 intoNode.tryCatchBlocks.clear(); 592 for (TryCatchBlockNodeWrapper node : nodes) { 593 intoNode.tryCatchBlocks.add(node.getNode()); 594 } 595 } 596 597 }