public static MethodLocation getNextLocation(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation) { int address = location.getCodeAddress(); int nextAddress = address + location.getInstruction().getCodeUnits(); return addressToLocation.get(nextAddress); }
public void addInstruction(int index, BuilderInstruction instruction) { // the end check here is intentially >= rather than >, because the list always includes an "empty" // (null instruction) MethodLocation at the end. To add an instruction to the end of the list, the user would // provide the index of this empty item, which would be size() - 1. if (index >= instructionList.size()) { throw new IndexOutOfBoundsException(); } if (index == instructionList.size() - 1) { addInstruction(instruction); return; } int codeAddress = instructionList.get(index).getCodeAddress(); MethodLocation newLoc = new MethodLocation(instruction, codeAddress, index); instructionList.add(index, newLoc); instruction.location = newLoc; codeAddress += instruction.getCodeUnits(); for (int i = index + 1; i < instructionList.size(); i++) { MethodLocation location = instructionList.get(i); location.index++; location.codeAddress = codeAddress; if (location.instruction != null) { codeAddress += location.instruction.getCodeUnits(); } else { // only the last MethodLocation should have a null instruction assert i == instructionList.size() - 1; } } this.fixInstructions = true; }
@Nonnull public Label newLabelForIndex(int instructionIndex) { if (instructionIndex < 0 || instructionIndex >= instructionList.size()) { throw new IndexOutOfBoundsException(String.format("instruction index %d out of bounds", instructionIndex)); } MethodLocation referent = instructionList.get(instructionIndex); return referent.addNewLabel(); }
public void removeInstruction(int index) { if (index >= instructionList.size() - 1) { throw new IndexOutOfBoundsException(); } MethodLocation toRemove = instructionList.get(index); toRemove.instruction = null; MethodLocation next = instructionList.get(index + 1); toRemove.mergeInto(next); instructionList.remove(index); int codeAddress = toRemove.codeAddress; for (int i = index; i < instructionList.size(); i++) { MethodLocation location = instructionList.get(i); location.index = i; location.codeAddress = codeAddress; Instruction instruction = location.getInstruction(); if (instruction != null) { codeAddress += instruction.getCodeUnits(); } else { assert i == instructionList.size() - 1; } } this.fixInstructions = true; }
public void replaceInstruction(int index, @Nonnull BuilderInstruction replacementInstruction) { if (index >= instructionList.size() - 1) { throw new IndexOutOfBoundsException(); } MethodLocation replaceLocation = instructionList.get(index); replacementInstruction.location = replaceLocation; BuilderInstruction old = replaceLocation.instruction; assert old != null; old.location = null; replaceLocation.instruction = replacementInstruction; // TODO: factor out index/address fix up loop int codeAddress = replaceLocation.codeAddress + replaceLocation.instruction.getCodeUnits(); for (int i = index + 1; i < instructionList.size(); i++) { MethodLocation location = instructionList.get(i); location.codeAddress = codeAddress; Instruction instruction = location.getInstruction(); if (instruction != null) { codeAddress += instruction.getCodeUnits(); } else { assert i == instructionList.size() - 1; } } this.fixInstructions = true; }
public final int getAddress() { return location.getCodeAddress(); }
index++; instructionList.add(new MethodLocation(null, codeAddress, index)); MethodLocation debugLocation = instructionList.get(locationIndex); BuilderDebugItem builderDebugItem = convertDebugItem(debugItem); debugLocation.getDebugItems().add(builderDebugItem); builderDebugItem.location = debugLocation;
@Nullable @Override public Iterable<? extends DebugItem> apply(@Nullable MethodLocation input) { assert input != null; if (fixInstructions) { throw new IllegalStateException("This iterator was invalidated by a change to" + " this MutableMethodImplementation."); } return input.getDebugItems(); } }));
private void doTestMergeIntoKeepsOrderOfDebugItems(int countLocation1, int countLocation2) { MethodLocation location1 = new MethodLocation(null, 123, 1); MethodLocation location2 = new MethodLocation(null, 456, 2); List<BuilderDebugItem> items1 = createItems(countLocation1); List<BuilderDebugItem> items2 = createItems(countLocation2); location1.getDebugItems().addAll(items1); location2.getDebugItems().addAll(items2); location1.mergeInto(location2); Assert.assertEquals(Sets.newHashSet(), location1.getDebugItems()); // items1 appear BEFORE items2 List<BuilderDebugItem> expectedItems = new ArrayList<>(items1); expectedItems.addAll(items2); Assert.assertEquals(expectedItems, new ArrayList<>(location2.getDebugItems())); }
@Nonnull public Label newSwitchPayloadReferenceLabel(@Nonnull MethodLocation switchLocation, @Nonnull int[] codeAddressToIndex, int codeAddress) { MethodLocation referent = instructionList.get(mapCodeAddressToIndex(codeAddressToIndex, codeAddress)); SwitchPayloadReferenceLabel label = new SwitchPayloadReferenceLabel(); label.switchLocation = switchLocation; referent.getLabels().add(label); return label; }
/** * 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 Label addLabel(@Nonnull String name) { Label label = labels.get(name); if (label != null) { if (label.isPlaced()) { throw new IllegalArgumentException("There is already a label with that name."); } else { currentLocation.getLabels().add(label); } } else { label = currentLocation.addNewLabel(); labels.put(name, label); } return label; }
void mergeInto(@Nonnull MethodLocation other) { 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; } 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; } }
public void addInstruction(@Nonnull BuilderInstruction instruction) { MethodLocation last = instructionList.get(instructionList.size() - 1); last.instruction = instruction; instruction.location = last; int nextCodeAddress = last.codeAddress + instruction.getCodeUnits(); instructionList.add(new MethodLocation(null, nextCodeAddress, instructionList.size())); this.fixInstructions = true; }
public void addEndLocal(int registerNumber) { currentLocation.addEndLocal(registerNumber); }
public void addEpilogue() { currentLocation.addEpilogue(); }
public void removeInstruction(int index) { if (index >= instructionList.size() - 1) { throw new IndexOutOfBoundsException(); } MethodLocation toRemove = instructionList.get(index); toRemove.instruction = null; MethodLocation next = instructionList.get(index+1); toRemove.mergeInto(next); instructionList.remove(index); int codeAddress = toRemove.codeAddress; for (int i=index; i<instructionList.size(); i++) { MethodLocation location = instructionList.get(i); location.index = i; location.codeAddress = codeAddress; Instruction instruction = location.getInstruction(); if (instruction != null) { codeAddress += instruction.getCodeUnits(); } else { assert i == instructionList.size() - 1; } } this.fixInstructions = true; }
@Override public Op create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { Instruction11x instr = (Instruction11x) location.getInstruction(); int register = instr.getRegisterA(); return new ThrowOp(location, register); }
@Override public String toString() { StringBuilder sb = new StringBuilder(getName()); sb.append(" r").append(register1); if (!compareToZero) { sb.append(", r").append(register2); } sb.append(", :addr_").append(target.getCodeAddress()); return sb.toString(); }
index++; instructionList.add(new MethodLocation(null, codeAddress, index)); MethodLocation debugLocation = instructionList.get(locationIndex); BuilderDebugItem builderDebugItem = convertDebugItem(debugItem); debugLocation.getDebugItems().add(builderDebugItem); builderDebugItem.location = debugLocation;
@Nullable @Override public Iterable<? extends DebugItem> apply(@Nullable MethodLocation input) { assert input != null; if (fixInstructions) { throw new IllegalStateException("This iterator was invalidated by a change to" + " this MutableMethodImplementation."); } return input.getDebugItems(); } }));