mirror of
https://github.com/revanced/smali.git
synced 2025-05-28 03:40:12 +02:00
Lazily create the lists in MethodLocation
Millions of MethodLocations can be created and kept in memory when using the Builder interface to build a large dex file. The arrays backing these lists were taking up a large amount of memory.
This commit is contained in:
parent
532c04b27d
commit
90db3a16b7
@ -31,7 +31,7 @@
|
||||
|
||||
package org.jf.dexlib2.builder;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.jf.dexlib2.builder.debug.*;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.reference.StringReference;
|
||||
@ -39,18 +39,21 @@ import org.jf.dexlib2.iface.reference.TypeReference;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class MethodLocation {
|
||||
@Nullable BuilderInstruction instruction;
|
||||
int codeAddress;
|
||||
int index;
|
||||
|
||||
private List<Label> labels = Lists.newArrayList();
|
||||
List<BuilderDebugItem> debugItems = Lists.newArrayList();
|
||||
// We end up creating and keeping around a *lot* of MethodLocation objects
|
||||
// when building a new dex file, so it's worth the trouble of lazily creating
|
||||
// the labels and debugItems lists only when they are needed
|
||||
|
||||
@Nullable
|
||||
private List<Label> labels = null;
|
||||
@Nullable
|
||||
private List<BuilderDebugItem> debugItems = null;
|
||||
|
||||
MethodLocation(@Nullable BuilderInstruction instruction, int codeAddress, int index) {
|
||||
this.instruction = instruction;
|
||||
@ -71,19 +74,51 @@ public class MethodLocation {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private List<Label> getLabels(boolean mutable) {
|
||||
if (labels == null) {
|
||||
if (mutable) {
|
||||
labels = new ArrayList<Label>(1);
|
||||
return labels;
|
||||
}
|
||||
return ImmutableList.of();
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private List<BuilderDebugItem> getDebugItems(boolean mutable) {
|
||||
if (debugItems == null) {
|
||||
if (mutable) {
|
||||
debugItems = new ArrayList<BuilderDebugItem>(1);
|
||||
return debugItems;
|
||||
}
|
||||
return ImmutableList.of();
|
||||
}
|
||||
return debugItems;
|
||||
}
|
||||
|
||||
void mergeInto(@Nonnull MethodLocation other) {
|
||||
for (Label label: labels) {
|
||||
label.location = other;
|
||||
other.labels.add(label);
|
||||
if (this.labels != null || other.labels != null) {
|
||||
List<Label> otherLabels = other.getLabels(true);
|
||||
for (Label label: this.getLabels(false)) {
|
||||
label.location = other;
|
||||
otherLabels.add(label);
|
||||
}
|
||||
this.labels = null;
|
||||
}
|
||||
|
||||
// We need to keep the debug items in the same order. We add the other debug items to this list, then reassign
|
||||
// the list.
|
||||
for (BuilderDebugItem debugItem: debugItems) {
|
||||
debugItem.location = other;
|
||||
if (this.debugItems != null || other.labels != null) {
|
||||
// We need to keep the debug items in the same order. We add the other debug items to this list, then reassign
|
||||
// the list.
|
||||
List<BuilderDebugItem> debugItems = getDebugItems(true);
|
||||
for (BuilderDebugItem debugItem: debugItems) {
|
||||
debugItem.location = other;
|
||||
}
|
||||
debugItems.addAll(other.getDebugItems(false));
|
||||
other.debugItems = debugItems;
|
||||
this.debugItems = null;
|
||||
}
|
||||
debugItems.addAll(other.debugItems);
|
||||
other.debugItems = debugItems;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -91,7 +126,7 @@ public class MethodLocation {
|
||||
return new AbstractSet<Label>() {
|
||||
@Nonnull
|
||||
@Override public Iterator<Label> iterator() {
|
||||
final Iterator<Label> it = labels.iterator();
|
||||
final Iterator<Label> it = getLabels(false).iterator();
|
||||
|
||||
return new Iterator<Label>() {
|
||||
private @Nullable Label currentLabel = null;
|
||||
@ -115,7 +150,7 @@ public class MethodLocation {
|
||||
}
|
||||
|
||||
@Override public int size() {
|
||||
return labels.size();
|
||||
return getLabels(false).size();
|
||||
}
|
||||
|
||||
@Override public boolean add(@Nonnull Label label) {
|
||||
@ -124,7 +159,7 @@ public class MethodLocation {
|
||||
"it from its current location first.");
|
||||
}
|
||||
label.location = MethodLocation.this;
|
||||
labels.add(label);
|
||||
getLabels(true).add(label);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -133,7 +168,7 @@ public class MethodLocation {
|
||||
@Nonnull
|
||||
public Label addNewLabel() {
|
||||
Label label = new Label(this);
|
||||
labels.add(label);
|
||||
getLabels(true).add(label);
|
||||
return label;
|
||||
}
|
||||
|
||||
@ -142,7 +177,7 @@ public class MethodLocation {
|
||||
return new AbstractSet<BuilderDebugItem>() {
|
||||
@Nonnull
|
||||
@Override public Iterator<BuilderDebugItem> iterator() {
|
||||
final Iterator<BuilderDebugItem> it = debugItems.iterator();
|
||||
final Iterator<BuilderDebugItem> it = getDebugItems(false).iterator();
|
||||
|
||||
return new Iterator<BuilderDebugItem>() {
|
||||
private @Nullable BuilderDebugItem currentDebugItem = null;
|
||||
@ -166,7 +201,7 @@ public class MethodLocation {
|
||||
}
|
||||
|
||||
@Override public int size() {
|
||||
return labels.size();
|
||||
return getDebugItems(false).size();
|
||||
}
|
||||
|
||||
@Override public boolean add(@Nonnull BuilderDebugItem debugItem) {
|
||||
@ -175,7 +210,7 @@ public class MethodLocation {
|
||||
"method. You must remove it from its current location first.");
|
||||
}
|
||||
debugItem.location = MethodLocation.this;
|
||||
debugItems.add(debugItem);
|
||||
getDebugItems(true).add(debugItem);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user