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 }