blob: b46df5fdccc1a2085d3ea76f61c2936687d4cf6a [file] [log] [blame]
// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.jar;
import static org.objectweb.asm.Opcodes.ALOAD;
import static com.android.tools.r8.utils.InternalOptions.ASM_VERSION;
import static org.objectweb.asm.Opcodes.DLOAD;
import static org.objectweb.asm.Opcodes.FLOAD;
import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.LLOAD;
import com.android.tools.r8.graph.ArgumentUse;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import org.objectweb.asm.MethodVisitor;
public class JarArgumentUseVisitor extends MethodVisitor {
private final ArgumentUse registry;
private final Int2IntMap slotToArgument;
private final int arguments;
public JarArgumentUseVisitor(DexEncodedMethod method, ArgumentUse registry) {
super(ASM_VERSION);
this.registry = registry;
DexProto proto = method.method.proto;
boolean isStatic = method.accessFlags.isStatic();
boolean hasLongOrDouble = false;
for (DexType value : proto.parameters.values) {
if (value.isLongType() || value.isDoubleType()) {
hasLongOrDouble = true;
break;
}
}
if (hasLongOrDouble) {
this.slotToArgument = new Int2IntArrayMap();
int nextSlot = 0;
int nextArgument = 0;
if (!isStatic) {
slotToArgument.put(nextSlot++, nextArgument++);
}
for (DexType value : proto.parameters.values) {
slotToArgument.put(nextSlot++, nextArgument++);
if (value.isLongType() || value.isDoubleType()) {
nextSlot++;
}
}
this.arguments = nextSlot;
} else {
this.slotToArgument = null;
this.arguments = proto.parameters.values.length + (isStatic ? 0 : 1);
}
}
@Override
public void visitIincInsn(final int var, final int increment) {
if (var < arguments) {
registry.register(slotToArgument == null ? var : slotToArgument.get(var));
}
}
@Override
public void visitVarInsn(final int opcode, final int var) {
switch (opcode) {
case ILOAD:
case LLOAD:
case FLOAD:
case DLOAD:
case ALOAD:
if (var < arguments) {
registry.register(slotToArgument == null ? var : slotToArgument.get(var));
}
break;
default:
// Ignore
}
}
}