Split off a separate MutableMethodImplementation and implement labels

This commit is contained in:
Ben Gruver 2013-08-31 14:12:58 -07:00
parent e94ee6fe80
commit 160fc1cdba
8 changed files with 199 additions and 31 deletions

View File

@ -0,0 +1,7 @@
package org.jf.dexlib2.builder;
import org.jf.dexlib2.iface.instruction.Instruction;
class InstructionMethodItem extends MethodItem {
public Instruction instruction;
}

View File

@ -0,0 +1,10 @@
package org.jf.dexlib2.builder;
public class LabelMethodItem extends MethodItem {
LabelMethodItem() {
}
LabelMethodItem(MethodLocation location) {
this.location = location;
}
}

View File

@ -1,11 +0,0 @@
package org.jf.dexlib2.builder;
public class LabelRef {
public boolean isResolved() {
return false;
}
public int getCodeAddress() {
return 0;
}
}

View File

@ -1,7 +1,6 @@
package org.jf.dexlib2.builder;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.reference.Reference;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
@ -9,27 +8,80 @@ import org.jf.dexlib2.writer.builder.BuilderStringReference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.List;
public class MethodImplementationBuilder<ReferenceType extends Reference> {
public MethodImplementationBuilder() {
}
public MethodImplementation buildMethodImplementation() {
return null;
}
// Contains all named labels - both placed and unplaced
private final HashMap<String, LabelMethodItem> labels = new HashMap<String, LabelMethodItem>();
@Nonnull
public LabelRef addLabel(@Nonnull String name) {
return null;
private final MutableMethodImplementation<ReferenceType> impl;
// the current instruction index
private int currentIndex;
public MethodImplementationBuilder(@Nonnull MutableMethodImplementation<ReferenceType> impl) {
this.impl = impl;
}
/**
* Adds a new named label at the current location.
*
* Any previous unplaced references to a label of this name will now refer to this label/location
*
* @param name The name of the label to add
* @return A LabelRef representing the label
*/
@Nonnull
public LabelRef getLabel(@Nonnull String name) {
return null;
public LabelMethodItem addLabel(@Nonnull String name) {
MethodLocation location = impl.instructionList.get(currentIndex);
LabelMethodItem label = labels.get(name);
if (label != null) {
if (label.isPlaced()) {
throw new IllegalArgumentException("There is already a label with that name.");
} else {
location.addLabel(label);
}
} else {
label = location.addNewLabel();
labels.put(name, label);
}
return label;
}
public void addCatch(String type, LabelRef from, LabelRef to, LabelRef using) {
/**
* Get a reference to a label with the given name.
*
* If a label with that name has not been added yet, a new one is created, but is left
* in an unplaced state. It is assumed that addLabel(name) will be called at a later
* point to define the location of the label.
*
* @param name The name of the label to get
* @return A LabelRef representing the label
*/
@Nonnull
public LabelMethodItem getLabel(@Nonnull String name) {
LabelMethodItem label = labels.get(name);
if (label == null) {
label = new LabelMethodItem();
labels.put(name, label);
}
return label;
}
public void addCatch(@Nullable TypeReference type, @Nonnull LabelMethodItem from,
@Nonnull LabelMethodItem to, @Nonnull LabelMethodItem handler) {
}
public void addCatch(@Nullable String type, @Nonnull LabelMethodItem from, @Nonnull LabelMethodItem to,
@Nonnull LabelMethodItem handler) {
}
public void addCatch(@Nonnull LabelMethodItem from, @Nonnull LabelMethodItem to, @Nonnull LabelMethodItem handler) {
}
public void addLineNumber(int lineNumber) {
@ -55,7 +107,7 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
}
public void addInstruction10t(@Nonnull Opcode opcode,
@Nonnull LabelRef label) {
@Nonnull LabelMethodItem label) {
}
public void addInstruction10x(@Nonnull Opcode opcode) {
@ -81,7 +133,7 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
}
public void addInstruction20t(@Nonnull Opcode opcode,
@Nonnull LabelRef label) {
@Nonnull LabelMethodItem label) {
}
public void addInstruction21c(@Nonnull Opcode opcode,
@ -106,7 +158,7 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
public void addInstruction21t(@Nonnull Opcode opcode,
int registerA,
@Nonnull LabelRef label) {
@Nonnull LabelMethodItem label) {
}
public void addInstruction22b(@Nonnull Opcode opcode,
@ -130,7 +182,7 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
public void addInstruction22t(@Nonnull Opcode opcode,
int registerA,
int registerB,
@Nonnull LabelRef labelRef) {
@Nonnull LabelMethodItem labelMethodItem) {
}
public void addInstruction22x(@Nonnull Opcode opcode,
@ -145,7 +197,7 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
}
public void addInstruction30t(@Nonnull Opcode opcode,
@Nonnull LabelRef label) {
@Nonnull LabelMethodItem label) {
}
public void addInstruction31c(@Nonnull Opcode opcode,
@ -160,7 +212,7 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
public void addInstruction31t(@Nonnull Opcode opcode,
int registerA,
@Nonnull LabelRef label) {
@Nonnull LabelMethodItem label) {
}
public void addInstruction32x(@Nonnull Opcode opcode,
@ -189,7 +241,7 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
long literal) {
}
public void addPackedSwitchPayload(int startKey, @Nullable List<? extends LabelRef> switchElements) {
public void addPackedSwitchPayload(int startKey, @Nullable List<? extends LabelMethodItem> switchElements) {
}
public void addSparseSwitchPayload(@Nullable List<? extends SwitchLabelElement> switchElements) {

View File

@ -0,0 +1,21 @@
package org.jf.dexlib2.builder;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
class MethodItem {
@Nullable
MethodLocation location;
@Nonnull
public MethodLocation getLocation() {
if (location == null) {
throw new IllegalStateException("Cannot get the address of MethodItem that hasn't been added to a method.");
}
return location;
}
public boolean isPlaced() {
return location != null;
}
}

View File

@ -0,0 +1,65 @@
package org.jf.dexlib2.builder;
import com.google.common.collect.Lists;
import org.jf.dexlib2.iface.instruction.Instruction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class MethodLocation {
@Nullable Instruction instruction;
int codeAddress;
int index;
private List<LabelMethodItem> labels = Lists.newArrayList();
MethodLocation(@Nullable Instruction instruction,
int codeAddress, int index) {
this.instruction = instruction;
this.codeAddress = codeAddress;
this.index = index;
}
@Nullable
public Instruction getInstruction() {
return instruction;
}
public int getCodeAddress() {
return codeAddress;
}
public int getIndex() {
return index;
}
@Nonnull
public Collection<LabelMethodItem> getLabels() {
return Collections.unmodifiableCollection(labels);
}
public void addLabel(@Nonnull LabelMethodItem label) {
if (label.isPlaced()) {
label.getLocation().removeLabel(label);
}
label.location = this;
labels.add(label);
}
@Nonnull
public LabelMethodItem addNewLabel() {
LabelMethodItem label = new LabelMethodItem(this);
labels.add(label);
return label;
}
public void removeLabel(@Nonnull LabelMethodItem label) {
for (int i=0; i<labels.size(); i++) {
labels.remove(label);
}
label.location = null;
}
}

View File

@ -0,0 +1,24 @@
package org.jf.dexlib2.builder;
import com.google.common.collect.Lists;
import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.reference.Reference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MutableMethodImplementation<ReferenceType extends Reference> {
final ArrayList<MethodLocation> instructionList = Lists.newArrayList(new MethodLocation(null, 0, 0));
public MutableMethodImplementation() {
}
public MethodImplementation buildMethodImplementation() {
return null;
}
public List<MethodLocation> getInstruction() {
return Collections.unmodifiableList(instructionList);
}
}

View File

@ -3,6 +3,6 @@ package org.jf.dexlib2.builder;
import javax.annotation.Nonnull;
public class SwitchLabelElement {
public SwitchLabelElement(int key, @Nonnull LabelRef dest) {
public SwitchLabelElement(int key, @Nonnull LabelMethodItem dest) {
}
}