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.NotNull; 020 import org.jetbrains.annotations.Nullable; 021 import org.jetbrains.asm4.MethodVisitor; 022 import org.jetbrains.asm4.Opcodes; 023 import org.jetbrains.asm4.commons.InstructionAdapter; 024 import org.jetbrains.jet.codegen.StackValue; 025 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; 026 027 public abstract class VarRemapper { 028 029 public static class ParamRemapper extends VarRemapper { 030 031 private final int allParamsSize; 032 private final Parameters params; 033 private final int actualParamsSize; 034 035 private final StackValue [] remapValues; 036 037 private final int additionalShift; 038 039 public ParamRemapper(Parameters params, int additionalShift) { 040 this.additionalShift = additionalShift; 041 this.allParamsSize = params.totalSize(); 042 this.params = params; 043 044 int realSize = 0; 045 remapValues = new StackValue [params.totalSize()]; 046 047 int index = 0; 048 for (ParameterInfo info : params) { 049 if (!info.isSkippedOrRemapped()) { 050 remapValues[index] = StackValue.local(realSize, AsmTypeConstants.OBJECT_TYPE); 051 realSize += info.getType().getSize(); 052 } else { 053 remapValues[index] = info.isRemapped() ? info.getRemapValue() : null; 054 } 055 index++; 056 } 057 058 actualParamsSize = realSize; 059 } 060 061 @Override 062 public RemapInfo doRemap(int index) { 063 int remappedIndex; 064 065 if (index < allParamsSize) { 066 ParameterInfo info = params.get(index); 067 StackValue remapped = remapValues[index]; 068 if (info.isSkipped || remapped == null) { 069 throw new RuntimeException("Trying to access skipped parameter: " + info.type + " at " +index); 070 } 071 if (info.isRemapped()) { 072 return new RemapInfo(remapped, info); 073 } else { 074 remappedIndex = ((StackValue.Local)remapped).index; 075 } 076 } else { 077 remappedIndex = actualParamsSize - params.totalSize() + index; //captured params not used directly in this inlined method, they used in closure 078 } 079 080 return new RemapInfo(StackValue.local(remappedIndex + additionalShift, AsmTypeConstants.OBJECT_TYPE), null); 081 } 082 } 083 084 public RemapInfo remap(int index) { 085 return doRemap(index); 086 } 087 088 public void visitIincInsn(int var, int increment, MethodVisitor mv) { 089 RemapInfo remap = remap(var); 090 assert remap.value instanceof StackValue.Local; 091 mv.visitIincInsn(((StackValue.Local) remap.value).index, increment); 092 } 093 094 public void visitVarInsn(int opcode, int var, InstructionAdapter mv) { 095 RemapInfo remapInfo = remap(var); 096 StackValue value = remapInfo.value; 097 if (value instanceof StackValue.Local) { 098 if (remapInfo.parameterInfo != null) { 099 opcode = value.type.getOpcode(Opcodes.ILOAD); 100 } 101 mv.visitVarInsn(opcode, ((StackValue.Local) value).index); 102 if (remapInfo.parameterInfo != null) { 103 StackValue.coerce(value.type, remapInfo.parameterInfo.type, mv); 104 } 105 } else { 106 assert remapInfo.parameterInfo != null : "Non local value should have parameter info"; 107 value.put(remapInfo.parameterInfo.type, mv); 108 } 109 } 110 111 abstract public RemapInfo doRemap(int index); 112 113 public static class RemapInfo { 114 115 public final StackValue value; 116 117 public final ParameterInfo parameterInfo; 118 119 public RemapInfo(@NotNull StackValue value, @Nullable ParameterInfo info) { 120 this.value = value; 121 parameterInfo = info; 122 } 123 } 124 }