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