com.android.dx.dex.code.DalvInsnList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of builder Show documentation
Show all versions of builder Show documentation
Library to build Android applications.
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dx.dex.code;
import com.android.dex.util.ExceptionWithContext;
import com.android.dx.io.Opcodes;
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstBaseMethodRef;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.FixedSizeList;
import com.android.dx.util.IndentingWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
/**
* List of {@link DalvInsn} instances.
*/
public final class DalvInsnList extends FixedSizeList {
/**
* The amount of register space, in register units, required for this
* code block. This may be greater than the largest observed register+
* category because the method this code block exists in may
* specify arguments that are unused by the method.
*/
private final int regCount;
/**
* Constructs and returns an immutable instance whose elements are
* identical to the ones in the given list, in the same order.
*
* @param list {@code non-null;} the list to use for elements
* @param regCount count, in register-units, of the number of registers
* this code block requires.
* @return {@code non-null;} an appropriately-constructed instance of this
* class
*/
public static DalvInsnList makeImmutable(ArrayList list,
int regCount) {
int size = list.size();
DalvInsnList result = new DalvInsnList(size, regCount);
for (int i = 0; i < size; i++) {
result.set(i, list.get(i));
}
result.setImmutable();
return result;
}
/**
* Constructs an instance. All indices initially contain {@code null}.
*
* @param size the size of the list
*/
public DalvInsnList(int size, int regCount) {
super(size);
this.regCount = regCount;
}
/**
* Gets the element at the given index. It is an error to call
* this with the index for an element which was never set; if you
* do that, this will throw {@code NullPointerException}.
*
* @param n {@code >= 0, < size();} which index
* @return {@code non-null;} element at that index
*/
public DalvInsn get(int n) {
return (DalvInsn) get0(n);
}
/**
* Sets the instruction at the given index.
*
* @param n {@code >= 0, < size();} which index
* @param insn {@code non-null;} the instruction to set at {@code n}
*/
public void set(int n, DalvInsn insn) {
set0(n, insn);
}
/**
* Gets the size of this instance, in 16-bit code units. This will only
* return a meaningful result if the instructions in this instance all
* have valid addresses.
*
* @return {@code >= 0;} the size
*/
public int codeSize() {
int sz = size();
if (sz == 0) {
return 0;
}
DalvInsn last = get(sz - 1);
return last.getNextAddress();
}
/**
* Writes all the instructions in this instance to the given output
* destination.
*
* @param out {@code non-null;} where to write to
*/
public void writeTo(AnnotatedOutput out) {
int startCursor = out.getCursor();
int sz = size();
if (out.annotates()) {
boolean verbose = out.isVerbose();
for (int i = 0; i < sz; i++) {
DalvInsn insn = (DalvInsn) get0(i);
int codeBytes = insn.codeSize() * 2;
String s;
if ((codeBytes != 0) || verbose) {
s = insn.listingString(" ", out.getAnnotationWidth(),
true);
} else {
s = null;
}
if (s != null) {
out.annotate(codeBytes, s);
} else if (codeBytes != 0) {
out.annotate(codeBytes, "");
}
}
}
for (int i = 0; i < sz; i++) {
DalvInsn insn = (DalvInsn) get0(i);
try {
insn.writeTo(out);
} catch (RuntimeException ex) {
throw ExceptionWithContext.withContext(ex,
"...while writing " + insn);
}
}
// Sanity check of the amount written.
int written = (out.getCursor() - startCursor) / 2;
if (written != codeSize()) {
throw new RuntimeException("write length mismatch; expected " +
codeSize() + " but actually wrote " + written);
}
}
/**
* Gets the minimum required register count implied by this
* instance. This includes any unused parameters that could
* potentially be at the top of the register space.
* @return {@code >= 0;} the required registers size
*/
public int getRegistersSize() {
return regCount;
}
/**
* Gets the size of the outgoing arguments area required by this
* method. This is equal to the largest argument word count of any
* method referred to by this instance.
*
* @return {@code >= 0;} the required outgoing arguments size
*/
public int getOutsSize() {
int sz = size();
int result = 0;
for (int i = 0; i < sz; i++) {
DalvInsn insn = (DalvInsn) get0(i);
if (!(insn instanceof CstInsn)) {
continue;
}
Constant cst = ((CstInsn) insn).getConstant();
if (!(cst instanceof CstBaseMethodRef)) {
continue;
}
boolean isStatic =
(insn.getOpcode().getFamily() == Opcodes.INVOKE_STATIC);
int count =
((CstBaseMethodRef) cst).getParameterWordCount(isStatic);
if (count > result) {
result = count;
}
}
return result;
}
/**
* Does a human-friendly dump of this instance.
*
* @param out {@code non-null;} where to dump
* @param prefix {@code non-null;} prefix to attach to each line of output
* @param verbose whether to be verbose; verbose output includes
* lines for zero-size instructions and explicit constant pool indices
*/
public void debugPrint(Writer out, String prefix, boolean verbose) {
IndentingWriter iw = new IndentingWriter(out, 0, prefix);
int sz = size();
try {
for (int i = 0; i < sz; i++) {
DalvInsn insn = (DalvInsn) get0(i);
String s;
if ((insn.codeSize() != 0) || verbose) {
s = insn.listingString("", 0, verbose);
} else {
s = null;
}
if (s != null) {
iw.write(s);
}
}
iw.flush();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
/**
* Does a human-friendly dump of this instance.
*
* @param out {@code non-null;} where to dump
* @param prefix {@code non-null;} prefix to attach to each line of output
* @param verbose whether to be verbose; verbose output includes
* lines for zero-size instructions
*/
public void debugPrint(OutputStream out, String prefix, boolean verbose) {
Writer w = new OutputStreamWriter(out);
debugPrint(w, prefix, verbose);
try {
w.flush();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy