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 MemberCodegen<?> parentCodegen = codegen.getParentCodegen(); 191 if (callDefault) { 192 boolean isStatic = AsmUtil.isStaticMethod(context.getContextKind(), functionDescriptor); 193 FunctionCodegen.generateDefaultImplBody( 194 methodContext, jvmSignature, functionDescriptor, isStatic, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, 195 (JetNamedFunction) element, parentCodegen, state 196 ); 197 } 198 else { 199 generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, (JetDeclarationWithBody) element, jvmSignature); 200 } 201 maxCalcAdapter.visitMaxs(-1, -1); 202 maxCalcAdapter.visitEnd(); 203 } 204 return node; 205 } 206 207 private InlineResult inlineCall(MethodNode node) { 208 ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node.instructions); 209 generateClosuresBodies(); 210 211 //through generation captured parameters will be added to invocationParamBuilder 212 putClosureParametersOnStack(); 213 214 addInlineMarker(codegen.v, true); 215 216 Parameters parameters = invocationParamBuilder.buildParameters(); 217 218 InliningContext info = new RootInliningContext(expressionMap, 219 state, 220 codegen.getInlineNameGenerator() 221 .subGenerator(functionDescriptor.getName().asString()), 222 codegen.getContext(), 223 callElement, 224 codegen.getParentCodegen().getClassName(), reifiedTypeInliner); 225 226 MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule, "Method inlining " + callElement.getText()); //with captured 227 228 LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize); 229 230 231 MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode(); 232 InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL); 233 result.getReifiedTypeParametersUsages().mergeAll(reificationResult); 234 235 LabelOwner labelOwner = new LabelOwner() { 236 237 final CallableMemberDescriptor descriptor = codegen.getContext().getContextDescriptor(); 238 239 final boolean isLambda = CodegenBinding.isLocalFunOrLambda(descriptor) && descriptor.getName().isSpecial(); 240 241 @Override 242 public boolean isMyLabel(@NotNull String name) { 243 if (InlineCodegenUtil.ROOT_LABEL.equals(name)) { 244 return !isLambda; 245 } 246 else { 247 return descriptor.getName().asString().equals(name); 248 } 249 } 250 }; 251 List<MethodInliner.PointForExternalFinallyBlocks> infos = MethodInliner.processReturns(adapter, labelOwner, true, null); 252 generateAndInsertFinallyBlocks(adapter, infos); 253 254 adapter.accept(new InliningInstructionAdapter(codegen.v)); 255 256 addInlineMarker(codegen.v, false); 257 258 return result; 259 } 260 261 private void generateClosuresBodies() { 262 for (LambdaInfo info : expressionMap.values()) { 263 info.setNode(generateLambdaBody(info)); 264 } 265 } 266 267 private MethodNode generateLambdaBody(LambdaInfo info) { 268 JetFunctionLiteral declaration = info.getFunctionLiteral(); 269 FunctionDescriptor descriptor = info.getFunctionDescriptor(); 270 271 MethodContext parentContext = codegen.getContext(); 272 273 MethodContext context = parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor); 274 275 JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(descriptor); 276 Method asmMethod = jvmMethodSignature.getAsmMethod(); 277 MethodNode methodNode = new MethodNode(InlineCodegenUtil.API, getMethodAsmFlags(descriptor, context.getContextKind()), asmMethod.getName(), asmMethod.getDescriptor(), jvmMethodSignature.getGenericsSignature(), null); 278 279 MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode); 280 281 generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature); 282 adapter.visitMaxs(-1, -1); 283 284 return methodNode; 285 } 286 287 private void generateMethodBody( 288 @NotNull MethodVisitor adapter, 289 @NotNull FunctionDescriptor descriptor, 290 @NotNull MethodContext context, 291 @NotNull JetDeclarationWithBody declaration, 292 @NotNull JvmMethodSignature jvmMethodSignature 293 ) { 294 FunctionCodegen.generateMethodBody( 295 adapter, descriptor, context, jvmMethodSignature, 296 new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), 297 // Wrapping for preventing marking actual parent codegen as containing reifier markers 298 new FakeMemberCodegen(codegen.getParentCodegen()) 299 ); 300 } 301 302 private static class FakeMemberCodegen extends MemberCodegen { 303 private final MemberCodegen delegate; 304 public FakeMemberCodegen(@NotNull MemberCodegen wrapped) { 305 super(wrapped); 306 delegate = wrapped; 307 } 308 309 @Override 310 protected void generateDeclaration() { 311 throw new IllegalStateException(); 312 } 313 314 @Override 315 protected void generateBody() { 316 throw new IllegalStateException(); 317 } 318 319 @Override 320 protected void generateKotlinAnnotation() { 321 throw new IllegalStateException(); 322 } 323 324 @NotNull 325 @Override 326 public NameGenerator getInlineNameGenerator() { 327 return delegate.getInlineNameGenerator(); 328 } 329 } 330 331 @Override 332 public void afterParameterPut(@NotNull Type type, @Nullable StackValue stackValue, @Nullable ValueParameterDescriptor valueParameterDescriptor) { 333 putCapturedInLocal(type, stackValue, valueParameterDescriptor, -1); 334 } 335 336 private void putCapturedInLocal( 337 @NotNull Type type, @Nullable StackValue stackValue, @Nullable ValueParameterDescriptor valueParameterDescriptor, int capturedParamIndex 338 ) { 339 if (!asFunctionInline && Type.VOID_TYPE != type) { 340 //TODO remap only inlinable closure => otherwise we could get a lot of problem 341 boolean couldBeRemapped = !shouldPutValue(type, stackValue, valueParameterDescriptor); 342 StackValue remappedIndex = couldBeRemapped ? stackValue : null; 343 344 ParameterInfo info; 345 if (capturedParamIndex >= 0) { 346 CapturedParamDesc capturedParamInfoInLambda = activeLambda.getCapturedVars().get(capturedParamIndex); 347 info = invocationParamBuilder.addCapturedParam(capturedParamInfoInLambda, capturedParamInfoInLambda.getFieldName()); 348 info.setRemapValue(remappedIndex); 349 } 350 else { 351 info = invocationParamBuilder.addNextParameter(type, false, remappedIndex); 352 } 353 354 putParameterOnStack(info); 355 } 356 } 357 358 /*descriptor is null for captured vars*/ 359 public boolean shouldPutValue( 360 @NotNull Type type, 361 @Nullable StackValue stackValue, 362 @Nullable ValueParameterDescriptor descriptor 363 ) { 364 365 if (stackValue == null) { 366 //default or vararg 367 return true; 368 } 369 370 //remap only inline functions (and maybe non primitives) 371 //TODO - clean asserion and remapping logic 372 if (isPrimitive(type) != isPrimitive(stackValue.type)) { 373 //don't remap boxing/unboxing primitives - lost identity and perfomance 374 return true; 375 } 376 377 if (stackValue instanceof StackValue.Local) { 378 return false; 379 } 380 381 //skip direct capturing fields 382 StackValue receiver = null; 383 if (stackValue instanceof StackValue.Field) { 384 receiver = ((StackValue.Field) stackValue).receiver; 385 } 386 else if (stackValue instanceof StackValue.FieldForSharedVar) { 387 receiver = ((StackValue.Field) ((StackValue.FieldForSharedVar) stackValue).receiver).receiver; 388 } 389 390 if (!(receiver instanceof StackValue.Local)) { 391 return true; 392 } 393 394 //TODO: check type of context 395 return !(codegen.getContext().isInliningLambda() && descriptor != null && !InlineUtil.hasNoinlineAnnotation(descriptor)); 396 } 397 398 private void putParameterOnStack(ParameterInfo... infos) { 399 int[] index = new int[infos.length]; 400 for (int i = 0; i < infos.length; i++) { 401 ParameterInfo info = infos[i]; 402 if (!info.isSkippedOrRemapped()) { 403 index[i] = codegen.getFrameMap().enterTemp(info.getType()); 404 } 405 else { 406 index[i] = -1; 407 } 408 } 409 410 for (int i = infos.length - 1; i >= 0; i--) { 411 ParameterInfo info = infos[i]; 412 if (!info.isSkippedOrRemapped()) { 413 Type type = info.type; 414 StackValue.local(index[i], type).store(StackValue.onStack(type), codegen.v); 415 } 416 } 417 } 418 419 @Override 420 public void putHiddenParams() { 421 List<JvmMethodParameterSignature> valueParameters = jvmSignature.getValueParameters(); 422 423 if (!isStaticMethod(functionDescriptor, context)) { 424 invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false, null); 425 } 426 427 for (JvmMethodParameterSignature param : valueParameters) { 428 if (param.getKind() == JvmMethodParameterKind.VALUE) { 429 break; 430 } 431 invocationParamBuilder.addNextParameter(param.getAsmType(), false, null); 432 } 433 434 List<ParameterInfo> infos = invocationParamBuilder.listNotCaptured(); 435 putParameterOnStack(infos.toArray(new ParameterInfo[infos.size()])); 436 } 437 438 public void leaveTemps() { 439 FrameMap frameMap = codegen.getFrameMap(); 440 List<ParameterInfo> infos = invocationParamBuilder.listAllParams(); 441 for (ListIterator<? extends ParameterInfo> iterator = infos.listIterator(infos.size()); iterator.hasPrevious(); ) { 442 ParameterInfo param = iterator.previous(); 443 if (!param.isSkippedOrRemapped()) { 444 frameMap.leaveTemp(param.type); 445 } 446 } 447 } 448 449 public static boolean isInliningClosure(JetExpression expression, ValueParameterDescriptor valueParameterDescriptora) { 450 //TODO deparenthisise typed 451 JetExpression deparenthesize = JetPsiUtil.deparenthesize(expression); 452 return deparenthesize instanceof JetFunctionLiteralExpression && 453 !InlineUtil.hasNoinlineAnnotation(valueParameterDescriptora); 454 } 455 456 public void rememberClosure(JetExpression expression, Type type) { 457 JetFunctionLiteralExpression lambda = (JetFunctionLiteralExpression) JetPsiUtil.deparenthesize(expression); 458 assert lambda != null : "Couldn't find lambda in " + expression.getText(); 459 460 String labelNameIfPresent = null; 461 PsiElement parent = lambda.getParent(); 462 if (parent instanceof JetLabeledExpression) { 463 labelNameIfPresent = ((JetLabeledExpression) parent).getLabelName(); 464 } 465 LambdaInfo info = new LambdaInfo(lambda, typeMapper, labelNameIfPresent); 466 467 ParameterInfo closureInfo = invocationParamBuilder.addNextParameter(type, true, null); 468 closureInfo.setLambda(info); 469 expressionMap.put(closureInfo.getIndex(), info); 470 } 471 472 private void putClosureParametersOnStack() { 473 for (LambdaInfo next : expressionMap.values()) { 474 activeLambda = next; 475 codegen.pushClosureOnStack(next.getClassDescriptor(), true, this); 476 } 477 activeLambda = null; 478 } 479 480 public static CodegenContext getContext(DeclarationDescriptor descriptor, GenerationState state) { 481 if (descriptor instanceof PackageFragmentDescriptor) { 482 return new PackageContext((PackageFragmentDescriptor) descriptor, null, null); 483 } 484 485 CodegenContext parent = getContext(descriptor.getContainingDeclaration(), state); 486 487 if (descriptor instanceof ClassDescriptor) { 488 OwnerKind kind = DescriptorUtils.isTrait(descriptor) ? OwnerKind.TRAIT_IMPL : OwnerKind.IMPLEMENTATION; 489 return parent.intoClass((ClassDescriptor) descriptor, kind, state); 490 } 491 else if (descriptor instanceof FunctionDescriptor) { 492 return parent.intoFunction((FunctionDescriptor) descriptor); 493 } 494 495 throw new IllegalStateException("Couldn't build context for " + descriptorName(descriptor)); 496 } 497 498 private static boolean isStaticMethod(FunctionDescriptor functionDescriptor, MethodContext context) { 499 return (getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) != 0; 500 } 501 502 private static String descriptorName(DeclarationDescriptor descriptor) { 503 return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor); 504 } 505 506 @Override 507 public void genValueAndPut( 508 @NotNull ValueParameterDescriptor valueParameterDescriptor, 509 @NotNull JetExpression argumentExpression, 510 @NotNull Type parameterType 511 ) { 512 //TODO deparenthisise 513 if (isInliningClosure(argumentExpression, valueParameterDescriptor)) { 514 rememberClosure(argumentExpression, parameterType); 515 } else { 516 StackValue value = codegen.gen(argumentExpression); 517 putValueIfNeeded(valueParameterDescriptor, parameterType, value); 518 } 519 } 520 521 @Override 522 public void putValueIfNeeded(@Nullable ValueParameterDescriptor valueParameterDescriptor, @NotNull Type parameterType, @NotNull StackValue value) { 523 if (shouldPutValue(parameterType, value, valueParameterDescriptor)) { 524 value.put(parameterType, codegen.v); 525 } 526 afterParameterPut(parameterType, value, valueParameterDescriptor); 527 } 528 529 @Override 530 public void putCapturedValueOnStack( 531 @NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex 532 ) { 533 if (shouldPutValue(stackValue.type, stackValue, null)) { 534 stackValue.put(stackValue.type, codegen.v); 535 } 536 putCapturedInLocal(stackValue.type, stackValue, null, paramIndex); 537 } 538 539 540 public void generateAndInsertFinallyBlocks(MethodNode intoNode, List<MethodInliner.PointForExternalFinallyBlocks> insertPoints) { 541 if (!codegen.hasFinallyBlocks()) return; 542 543 Map<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks> extensionPoints = 544 new HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>(); 545 for (MethodInliner.PointForExternalFinallyBlocks insertPoint : insertPoints) { 546 extensionPoints.put(insertPoint.beforeIns, insertPoint); 547 } 548 549 DefaultProcessor processor = new DefaultProcessor(intoNode); 550 551 AbstractInsnNode curInstr = intoNode.instructions.getFirst(); 552 while (curInstr != null) { 553 processor.updateCoveringTryBlocks(curInstr, true); 554 555 MethodInliner.PointForExternalFinallyBlocks extension = extensionPoints.get(curInstr); 556 if (extension != null) { 557 Label start = new Label(); 558 Label end = new Label(); 559 560 MethodNode finallyNode = InlineCodegenUtil.createEmptyMethodNode(); 561 finallyNode.visitLabel(start); 562 563 ExpressionCodegen finallyCodegen = 564 new ExpressionCodegen(finallyNode, codegen.getFrameMap(), codegen.getReturnType(), 565 codegen.getContext(), codegen.getState(), codegen.getParentCodegen()); 566 finallyCodegen.addBlockStackElementsForNonLocalReturns(codegen.getBlockStackElements()); 567 568 finallyCodegen.generateFinallyBlocksIfNeeded(extension.returnType); 569 finallyNode.visitLabel(end); 570 571 //Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method 572 InlineCodegenUtil.insertNodeBefore(finallyNode, intoNode, curInstr); 573 574 List<TryCatchBlockNodeWrapper> blocks = processor.getCoveringFromInnermost(); 575 ListIterator<TryCatchBlockNodeWrapper> iterator = blocks.listIterator(blocks.size()); 576 while (iterator.hasPrevious()) { 577 TryCatchBlockNodeWrapper previous = iterator.previous(); 578 LabelNode oldStart = previous.getStartLabel(); 579 TryCatchBlockNode node = previous.getNode(); 580 node.start = (LabelNode) end.info; 581 processor.remapStartLabel(oldStart, previous); 582 583 TryCatchBlockNode additionalNode = new TryCatchBlockNode(oldStart, (LabelNode) start.info, node.handler, node.type); 584 processor.addNode(additionalNode); 585 } 586 } 587 588 curInstr = curInstr.getNext(); 589 } 590 591 processor.sortTryCatchBlocks(); 592 Iterable<TryCatchBlockNodeWrapper> nodes = processor.getNonEmptyNodes(); 593 intoNode.tryCatchBlocks.clear(); 594 for (TryCatchBlockNodeWrapper node : nodes) { 595 intoNode.tryCatchBlocks.add(node.getNode()); 596 } 597 } 598 599 }