// first, we grab all the parameters and temporarily store them at the beginning of locals,
// disregarding any wide types
int parameterIndex = 0;
if (!AccessFlags.STATIC.isSet(methodImpl.method.getAccessFlags())) {
// add the local info for the "this" parameter
locals[parameterIndex++] = new LocalInfo() {
@Override public String getName() { return "this"; }
@Override public String getType() { return methodImpl.method.getDefiningClass(); }
@Override public String getSignature() { return null; }
};
}
while (parameterIterator.hasNext()) {
locals[parameterIndex++] = parameterIterator.next();
}
if (parameterIndex < registerCount) {
// now, we push the parameter locals back to their appropriate register, starting from the end
int localIndex = registerCount-1;
while(--parameterIndex > -1) {
LocalInfo currentLocal = locals[parameterIndex];
String type = currentLocal.getType();
if (type != null && (type.equals("J") || type.equals("D"))) {
localIndex--;
if (localIndex == parameterIndex) {
// there's no more room to push, the remaining registers are already in the correct place
break;
}
}
locals[localIndex] = currentLocal;
locals[parameterIndex] = EMPTY_LOCAL_INFO;
localIndex--;
}
}
return new VariableSizeLookaheadIterator<DebugItem>(dexFile, reader.getOffset()) {
private int codeAddress = 0;
private int lineNumber = lineNumberStart;
@Nullable
protected DebugItem readNextItem(@Nonnull DexReader reader) {
while (true) {
int next = reader.readUbyte();
switch (next) {
case DebugItemType.END_SEQUENCE: {
return null;
}
case DebugItemType.ADVANCE_PC: {
int addressDiff = reader.readSmallUleb128();
codeAddress += addressDiff;
continue;
}
case DebugItemType.ADVANCE_LINE: {
int lineDiff = reader.readSleb128();
lineNumber += lineDiff;
continue;
}
case DebugItemType.START_LOCAL: {
int register = reader.readSmallUleb128();
String name = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1);
ImmutableStartLocal startLocal =
new ImmutableStartLocal(codeAddress, register, name, type, null);
locals[register] = startLocal;
return startLocal;
}
case DebugItemType.START_LOCAL_EXTENDED: {
int register = reader.readSmallUleb128();
String name = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1);
String signature = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
ImmutableStartLocal startLocal =
new ImmutableStartLocal(codeAddress, register, name, type, signature);
locals[register] = startLocal;
return startLocal;
}
case DebugItemType.END_LOCAL: {
int register = reader.readSmallUleb128();
LocalInfo localInfo = locals[register];
boolean replaceLocalInTable = true;
if (localInfo instanceof EndLocal) {
localInfo = EMPTY_LOCAL_INFO;
// don't replace the local info in locals. The new EndLocal won't have any info at all,
// and we dont want to wipe out what's there, so that it is available for a subsequent
// RestartLocal
replaceLocalInTable = false;
}
ImmutableEndLocal endLocal =
new ImmutableEndLocal(codeAddress, register, localInfo.getName(),
localInfo.getType(), localInfo.getSignature());
if (replaceLocalInTable) {
locals[register] = endLocal;
}
return endLocal;
}
case DebugItemType.RESTART_LOCAL: {
int register = reader.readSmallUleb128();
LocalInfo localInfo = locals[register];
ImmutableRestartLocal restartLocal =
new ImmutableRestartLocal(codeAddress, register, localInfo.getName(),
localInfo.getType(), localInfo.getSignature());
locals[register] = restartLocal;
return restartLocal;
}
case DebugItemType.PROLOGUE_END: {
return new ImmutablePrologueEnd(codeAddress);