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.tree.AbstractInsnNode; 022 import org.jetbrains.asm4.tree.FieldInsnNode; 023 import org.jetbrains.asm4.tree.MethodNode; 024 import org.jetbrains.asm4.tree.VarInsnNode; 025 026 import java.util.Collection; 027 import java.util.List; 028 029 import static org.jetbrains.jet.codegen.inline.MethodInliner.getPreviousNoLabelNoLine; 030 031 public class LambdaFieldRemapper { 032 033 public AbstractInsnNode doTransform(MethodNode node, FieldInsnNode fieldInsnNode, CapturedParamInfo capturedField) { 034 AbstractInsnNode loadThis = getPreviousThis(fieldInsnNode); 035 036 int opcode = fieldInsnNode.getOpcode() == Opcodes.GETFIELD ? capturedField.getType().getOpcode(Opcodes.ILOAD) : capturedField.getType().getOpcode(Opcodes.ISTORE); 037 VarInsnNode newInstruction = new VarInsnNode(opcode, capturedField.getIndex()); 038 039 node.instructions.remove(loadThis); //remove aload this 040 node.instructions.insertBefore(fieldInsnNode, newInstruction); 041 node.instructions.remove(fieldInsnNode); //remove aload field 042 043 return newInstruction; 044 } 045 046 protected static AbstractInsnNode getPreviousThis(FieldInsnNode fieldInsnNode) { 047 AbstractInsnNode loadThis = getPreviousNoLabelNoLine(fieldInsnNode); 048 049 assert loadThis.getType() == AbstractInsnNode.VAR_INSN || loadThis.getType() == AbstractInsnNode.FIELD_INSN : 050 "Field access instruction should go after load this but goes after " + loadThis; 051 assert loadThis.getOpcode() == Opcodes.ALOAD || loadThis.getOpcode() == Opcodes.GETSTATIC : 052 "This should be loaded by ALOAD or GETSTATIC but " + loadThis.getOpcode(); 053 return loadThis; 054 } 055 056 public List<CapturedParamInfo> markRecaptured(List<CapturedParamInfo> originalCaptured, LambdaInfo lambda) { 057 return originalCaptured; 058 } 059 060 061 public boolean canProcess(String owner, String currentLambdaType) { 062 return owner.equals(currentLambdaType); 063 } 064 065 @Nullable 066 public CapturedParamInfo findField(FieldInsnNode fieldInsnNode, Collection<CapturedParamInfo> captured) { 067 for (CapturedParamInfo valueDescriptor : captured) { 068 if (valueDescriptor.getFieldName().equals(fieldInsnNode.name)) { 069 return valueDescriptor; 070 } 071 } 072 return null; 073 } 074 }