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 org.jetbrains.annotations.Nullable;
020 import org.jetbrains.asm4.Opcodes;
021 import org.jetbrains.asm4.Type;
022 import org.jetbrains.asm4.tree.AbstractInsnNode;
023 import org.jetbrains.asm4.tree.FieldInsnNode;
024 import org.jetbrains.asm4.tree.MethodNode;
025
026 import java.util.Collection;
027 import java.util.List;
028 import java.util.Map;
029
030 public class RegeneratedLambdaFieldRemapper extends LambdaFieldRemapper {
031
032 private final String oldOwnerType;
033
034 private final String newOwnerType;
035
036 private final Parameters parameters;
037
038 private final Map<String, LambdaInfo> recapturedLambdas;
039
040 public RegeneratedLambdaFieldRemapper(
041 String oldOwnerType,
042 String newOwnerType,
043 Parameters parameters,
044 Map<String, LambdaInfo> recapturedLambdas
045 ) {
046 this.oldOwnerType = oldOwnerType;
047 this.newOwnerType = newOwnerType;
048 this.parameters = parameters;
049 this.recapturedLambdas = recapturedLambdas;
050 }
051
052 @Override
053 public AbstractInsnNode doTransform(
054 MethodNode node, FieldInsnNode fieldInsnNode, CapturedParamInfo capturedField
055 ) {
056 boolean isRecaptured = isRecapturedLambdaType(fieldInsnNode.owner);
057
058 if (!isRecaptured && capturedField.getLambda() != null) {
059 //strict inlining
060 return super.doTransform(node, fieldInsnNode, capturedField);
061 }
062
063 AbstractInsnNode loadThis = getPreviousThis(fieldInsnNode);
064
065 int opcode = Opcodes.GETSTATIC;
066
067 String descriptor = Type.getObjectType(newOwnerType).getDescriptor();
068
069 //HACK: it would be reverted again to ALOAD 0 later
070 FieldInsnNode thisStub = new FieldInsnNode(opcode, newOwnerType, "$$$this", descriptor);
071
072 node.instructions.insertBefore(loadThis, thisStub);
073 node.instructions.remove(loadThis);
074
075 fieldInsnNode.owner = newOwnerType;
076 fieldInsnNode.name = isRecaptured || capturedField.getRecapturedFrom() != null ? LambdaTransformer.getNewFieldName(capturedField.getFieldName()) : capturedField.getFieldName();
077
078 return fieldInsnNode;
079 }
080
081 @Override
082 public List<CapturedParamInfo> markRecaptured(List<CapturedParamInfo> originalCaptured, LambdaInfo lambda) {
083 List<CapturedParamInfo> captured = parameters.getCaptured();
084 for (CapturedParamInfo originalField : originalCaptured) {
085 for (CapturedParamInfo capturedParamInfo : captured) {
086 if (capturedParamInfo.getRecapturedFrom() == lambda) {
087 if (capturedParamInfo.getFieldName().equals(LambdaTransformer.getNewFieldName(originalField.getFieldName()))) {
088 originalField.setRecapturedFrom(lambda);//just mark recaptured
089 }
090 }
091 }
092 }
093 return originalCaptured;
094 }
095
096 @Override
097 public boolean canProcess(String owner, String currentLambdaType) {
098 return super.canProcess(owner, currentLambdaType) || isRecapturedLambdaType(owner);
099 }
100
101 private boolean isRecapturedLambdaType(String owner) {
102 return recapturedLambdas.containsKey(owner);
103 }
104
105 @Nullable
106 @Override
107 public CapturedParamInfo findField(FieldInsnNode fieldInsnNode, Collection<CapturedParamInfo> captured) {
108 if (isRecapturedLambdaType(fieldInsnNode.owner)) {
109 LambdaInfo info = recapturedLambdas.get(fieldInsnNode.owner);
110 return super.findField(fieldInsnNode, info.getCapturedVars());
111 }
112 else {
113 return super.findField(fieldInsnNode, captured);
114 }
115 }
116 }