mirror of
https://github.com/revanced/smali.git
synced 2025-05-29 12:20:11 +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;
|
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.builder.debug.*;
|
||||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||||
import org.jf.dexlib2.iface.reference.StringReference;
|
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.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.AbstractSet;
|
import java.util.*;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class MethodLocation {
|
public class MethodLocation {
|
||||||
@Nullable BuilderInstruction instruction;
|
@Nullable BuilderInstruction instruction;
|
||||||
int codeAddress;
|
int codeAddress;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
private List<Label> labels = Lists.newArrayList();
|
// We end up creating and keeping around a *lot* of MethodLocation objects
|
||||||
List<BuilderDebugItem> debugItems = Lists.newArrayList();
|
// 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) {
|
MethodLocation(@Nullable BuilderInstruction instruction, int codeAddress, int index) {
|
||||||
this.instruction = instruction;
|
this.instruction = instruction;
|
||||||
@ -71,19 +74,51 @@ public class MethodLocation {
|
|||||||
return index;
|
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) {
|
void mergeInto(@Nonnull MethodLocation other) {
|
||||||
for (Label label: labels) {
|
if (this.labels != null || other.labels != null) {
|
||||||
label.location = other;
|
List<Label> otherLabels = other.getLabels(true);
|
||||||
other.labels.add(label);
|
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
|
if (this.debugItems != null || other.labels != null) {
|
||||||
// the list.
|
// We need to keep the debug items in the same order. We add the other debug items to this list, then reassign
|
||||||
for (BuilderDebugItem debugItem: debugItems) {
|
// the list.
|
||||||
debugItem.location = other;
|
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
|
@Nonnull
|
||||||
@ -91,7 +126,7 @@ public class MethodLocation {
|
|||||||
return new AbstractSet<Label>() {
|
return new AbstractSet<Label>() {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override public Iterator<Label> iterator() {
|
@Override public Iterator<Label> iterator() {
|
||||||
final Iterator<Label> it = labels.iterator();
|
final Iterator<Label> it = getLabels(false).iterator();
|
||||||
|
|
||||||
return new Iterator<Label>() {
|
return new Iterator<Label>() {
|
||||||
private @Nullable Label currentLabel = null;
|
private @Nullable Label currentLabel = null;
|
||||||
@ -115,7 +150,7 @@ public class MethodLocation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int size() {
|
@Override public int size() {
|
||||||
return labels.size();
|
return getLabels(false).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean add(@Nonnull Label label) {
|
@Override public boolean add(@Nonnull Label label) {
|
||||||
@ -124,7 +159,7 @@ public class MethodLocation {
|
|||||||
"it from its current location first.");
|
"it from its current location first.");
|
||||||
}
|
}
|
||||||
label.location = MethodLocation.this;
|
label.location = MethodLocation.this;
|
||||||
labels.add(label);
|
getLabels(true).add(label);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -133,7 +168,7 @@ public class MethodLocation {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
public Label addNewLabel() {
|
public Label addNewLabel() {
|
||||||
Label label = new Label(this);
|
Label label = new Label(this);
|
||||||
labels.add(label);
|
getLabels(true).add(label);
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +177,7 @@ public class MethodLocation {
|
|||||||
return new AbstractSet<BuilderDebugItem>() {
|
return new AbstractSet<BuilderDebugItem>() {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override public Iterator<BuilderDebugItem> iterator() {
|
@Override public Iterator<BuilderDebugItem> iterator() {
|
||||||
final Iterator<BuilderDebugItem> it = debugItems.iterator();
|
final Iterator<BuilderDebugItem> it = getDebugItems(false).iterator();
|
||||||
|
|
||||||
return new Iterator<BuilderDebugItem>() {
|
return new Iterator<BuilderDebugItem>() {
|
||||||
private @Nullable BuilderDebugItem currentDebugItem = null;
|
private @Nullable BuilderDebugItem currentDebugItem = null;
|
||||||
@ -166,7 +201,7 @@ public class MethodLocation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int size() {
|
@Override public int size() {
|
||||||
return labels.size();
|
return getDebugItems(false).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean add(@Nonnull BuilderDebugItem debugItem) {
|
@Override public boolean add(@Nonnull BuilderDebugItem debugItem) {
|
||||||
@ -175,7 +210,7 @@ public class MethodLocation {
|
|||||||
"method. You must remove it from its current location first.");
|
"method. You must remove it from its current location first.");
|
||||||
}
|
}
|
||||||
debugItem.location = MethodLocation.this;
|
debugItem.location = MethodLocation.this;
|
||||||
debugItems.add(debugItem);
|
getDebugItems(true).add(debugItem);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user