public static MethodLocation[] getLocations(BuilderInstruction... instructions) { MethodLocation[] locations = new MethodLocation[instructions.length]; for (int i = 0; i < locations.length; i++) { locations[i] = instructions[i].getLocation(); } return locations; }
public List<BuilderTryBlock> getTryBlocks() { return implementation.getTryBlocks(); }
public final BuilderInstruction getInstruction() { return (BuilderInstruction) location.getInstruction(); }
private void setupInstruction(BuilderInstruction instruction, Opcode opcode) { when(location.getInstruction()).thenReturn(instruction); when(instruction.getLocation()).thenReturn(location); when(instruction.getCodeUnits()).thenReturn(0); when(instruction.getOpcode()).thenReturn(opcode); }
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; }
@Override public Op create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); Label target = ((BuilderOffsetInstruction) instruction).getTarget(); int targetAddress = target.getCodeAddress(); MethodLocation child = addressToLocation.get(targetAddress); return new GotoOp(location, child); } }
@Nonnull private BuilderInstruction31t newBuilderInstruction31t(@Nonnull MethodLocation location, int[] codeAddressToIndex, @Nonnull Instruction31t instruction) { int codeAddress = location.getCodeAddress(); Label newLabel; if (instruction.getOpcode() != Opcode.FILL_ARRAY_DATA) { // if it's a sparse switch or packed switch newLabel = newSwitchPayloadReferenceLabel(location, codeAddressToIndex, codeAddress + instruction.getCodeOffset()); } else { newLabel = newLabel(codeAddressToIndex, codeAddress + instruction.getCodeOffset()); } return new BuilderInstruction31t( instruction.getOpcode(), instruction.getRegisterA(), newLabel); }
protected static TIntObjectMap<MethodLocation> buildAddressToLocation(MutableMethodImplementation implementation) { List<BuilderInstruction> instructions = implementation.getInstructions(); TIntObjectMap<MethodLocation> addressToLocation = new TIntObjectHashMap<>(instructions.size()); for (BuilderInstruction instruction : instructions) { MethodLocation location = instruction.getLocation(); int address = location.getCodeAddress(); addressToLocation.put(address, location); } return addressToLocation; }
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; }
@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; }
@Nonnull private BuilderInstruction20t newBuilderInstruction20t(int codeAddress, int[] codeAddressToIndex, @Nonnull Instruction20t instruction) { return new BuilderInstruction20t( instruction.getOpcode(), newLabel(codeAddressToIndex, codeAddress + instruction.getCodeOffset())); }
@Nullable private BuilderInstruction getFirstNonNop(int startIndex) { for (int i = startIndex; i < instructionList.size() - 1; i++) { BuilderInstruction instruction = instructionList.get(i).instruction; assert instruction != null; if (instruction.getOpcode() != Opcode.NOP) { return instruction; } } return null; }
public final int getAddress() { return location.getCodeAddress(); }
@Nonnull private Label newLabel(@Nonnull int[] codeAddressToIndex, int codeAddress) { MethodLocation referent = instructionList.get(mapCodeAddressToIndex(codeAddressToIndex, codeAddress)); return referent.addNewLabel(); }
@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(); } }));
public void addCatch(@Nonnull Label from, @Nonnull Label to, @Nonnull Label handler) { tryBlocks.add(new BuilderTryBlock(from, to, handler)); }
public void removeInstruction(MethodLocation location) { int index = location.getIndex(); implementation.removeInstruction(index); removeEmptyTryCatchBlocks(); rebuildGraph(); }
@Override public BuilderInstruction get(int i) { if (i >= size()) { throw new IndexOutOfBoundsException(); } if (fixInstructions) { fixInstructions(); } return instructionList.get(i).instruction; }
@Nonnull @Override public List<BuilderTryBlock> getTryBlocks() { if (fixInstructions) { fixInstructions(); } return Collections.unmodifiableList(tryBlocks); }
@Nonnull public Label newLabelForAddress(int codeAddress) { if (codeAddress < 0 || codeAddress > instructionList.get(instructionList.size() - 1).codeAddress) { throw new IndexOutOfBoundsException(String.format("codeAddress %d out of bounds", codeAddress)); } MethodLocation referent = instructionList.get(mapCodeAddressToIndex(codeAddress)); return referent.addNewLabel(); }