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