/** * push a type on to the top of the stack */ public StackState push(String type) { StackEntry entry = StackEntry.of(type, constPool); if (entry.getType() == StackEntryType.DOUBLE || entry.getType() == StackEntryType.LONG) { return newStack(entry, new StackEntry(StackEntryType.TOP, type)); } return newStack(entry); }
public LocalVariableState constructorCall(StackEntry entry) { List<StackEntry> newContents = new ArrayList<StackEntry>(contents.size()); if (entry.getType() == StackEntryType.UNINITIALIZED_THIS) { for (int i = 0; i < contents.size(); ++i) { StackEntry stackEntry = contents.get(i); if (stackEntry.getType() == StackEntryType.UNINITIALIZED_THIS) { newContents.add(StackEntry.of(stackEntry.getDescriptor(), constPool)); } else { newContents.add(stackEntry); } } return new LocalVariableState(newContents, constPool); } else if (entry.getType() == StackEntryType.UNITITIALIZED_OBJECT) { for (int i = 0; i < contents.size(); ++i) { StackEntry stackEntry = contents.get(i); if (stackEntry.getType() == StackEntryType.UNITITIALIZED_OBJECT && stackEntry.getNewInstructionLocation() == entry.getNewInstructionLocation()) { newContents.add(StackEntry.of(stackEntry.getDescriptor(), constPool)); } else { newContents.add(stackEntry); } } return new LocalVariableState(newContents, constPool); } else { throw new InvalidBytecodeException("entry is not an unitialized object. " + toString()); } }
/** * checks that the appropriate object type is on top of the stack */ public boolean isOnTop(String descriptor) { if (contents.isEmpty()) { return false; } StackEntry entry = StackEntry.of(descriptor, constPool); StackEntry top = top(); if (entry.isWide()) { if (contents.size() == 1) { return false; } return top_1().getType() == entry.getType(); } if (top.getType() == StackEntryType.NULL && entry.getType() == StackEntryType.OBJECT) { return true; } return top.getType() == entry.getType(); }
/** * push a type on to the top of the stack */ public StackState push(StackEntry entry) { if (entry.getType() == StackEntryType.DOUBLE || entry.getType() == StackEntryType.LONG) { return newStack(entry, new StackEntry(StackEntryType.TOP, entry.getDescriptor())); } return newStack(entry); }
/** * construct the initial local variable state for a method */ public LocalVariableState(ClassMethod method) { this.constPool = method.getClassFile().getConstPool(); contents = new ArrayList<StackEntry>(); if (!method.isStatic()) { if (method.isConstructor()) { contents.add(new StackEntry(StackEntryType.UNINITIALIZED_THIS, method.getClassFile().getDescriptor())); } else { contents.add(StackEntry.of(method.getClassFile().getDescriptor(), method.getClassFile().getConstPool())); } } for (String param : method.getParameters()) { StackEntry entry = StackEntry.of(param, method.getClassFile().getConstPool()); contents.add(entry); if (entry.isWide()) { contents.add(new StackEntry(StackEntryType.TOP, param)); } } }
public StackState(String exceptionType, ConstPool constPool) { this.contents = new ArrayList<StackEntry>(1); this.contents.add(new StackEntry(StackEntryType.OBJECT, "L" + exceptionType + ";", constPool)); this.constPool = constPool; }
public StackState dup() { if (contents.isEmpty()) { throw new InvalidBytecodeException("cannot dup empty stack"); } StackEntry type = top(); if (type.getType() == StackEntryType.TOP) { throw new InvalidBytecodeException("Cannot dup wide type"); } return newStack(type); }
public LocalVariableState storeWide(int index, StackEntry entry) { ArrayList<StackEntry> newContents = new ArrayList<StackEntry>(contents.size()); for (int i = 0; i <= index || i < contents.size(); ++i) { if (index == i) { newContents.add(entry); newContents.add(new StackEntry(StackEntryType.TOP, entry.getDescriptor())); ++i; } else if (i >= contents.size()) { // write a null in unitialised slots // not sure if this is correct newContents.add(new StackEntry(StackEntryType.NULL, null)); } else { newContents.add(contents.get(i)); } } return new LocalVariableState(newContents, constPool); }
/** * writes a full_frame to the stack map table */ private void writeFullFrame(DataOutputStream dstream, int offset, int position, StackFrame value) throws IOException { dstream.writeByte(FULL_FRAME); dstream.writeShort(offset); List<StackEntry> realLocalVars = new ArrayList<StackEntry>(value.getLocalVariableState().getContents().size()); for (StackEntry i : value.getLocalVariableState().getContents()) { if (i.getType() != StackEntryType.TOP) { realLocalVars.add(i); } } dstream.writeShort(realLocalVars.size()); for (StackEntry i : realLocalVars) { i.write(dstream); } // TODO: this is inefficient, the stack should store the number of TOP values in each frame List<StackEntry> realStack = new ArrayList<StackEntry>(value.getStackState().getContents().size()); for (StackEntry i : value.getStackState().getContents()) { if (i.getType() != StackEntryType.TOP) { realStack.add(i); } } dstream.writeShort(realStack.size()); for (StackEntry i : realStack) { i.write(dstream); } }
public void aaload() { assertTypeOnStack(StackEntryType.INT, "aaload requires int on top of stack"); if (!getStack().top_1().getDescriptor().startsWith("[")) { throw new InvalidBytecodeException("aaload needs an array in position 2 on the stack"); } writeByte(Opcode.AALOAD); currentOffset++; advanceFrame(currentFrame.pop2push1("Ljava/lang/Object;")); }
public LocalVariableState(final ConstPool pool, final String ... entries) { this.constPool = pool; contents = new ArrayList<StackEntry>(); for(String c : entries) { final StackEntry entry = StackEntry.of(c, constPool); contents.add(entry); } }
private void writeSameLocals1Stack(DataOutputStream dstream, int offset, int lastPos, StackFrame frame) throws IOException { dstream.writeByte(offset + 64); frame.getStackState().getContents().get(0).write(dstream); }
/** * push a type on to the top of the stack */ public StackState push(StackEntry entry) { if (entry.getType() == StackEntryType.DOUBLE || entry.getType() == StackEntryType.LONG) { return newStack(entry, new StackEntry(StackEntryType.TOP, entry.getDescriptor())); } return newStack(entry); }
/** * construct the initial local variable state for a method */ public LocalVariableState(ClassMethod method) { this.constPool = method.getClassFile().getConstPool(); contents = new ArrayList<StackEntry>(); if (!method.isStatic()) { if (method.isConstructor()) { contents.add(new StackEntry(StackEntryType.UNINITIALIZED_THIS, method.getClassFile().getDescriptor())); } else { contents.add(StackEntry.of(method.getClassFile().getDescriptor(), method.getClassFile().getConstPool())); } } for (String param : method.getParameters()) { StackEntry entry = StackEntry.of(param, method.getClassFile().getConstPool()); contents.add(entry); if (entry.isWide()) { contents.add(new StackEntry(StackEntryType.TOP, param)); } } }
public StackState(String exceptionType, ConstPool constPool) { this.contents = new ArrayList<StackEntry>(1); this.contents.add(new StackEntry(StackEntryType.OBJECT, DescriptorUtils.makeDescriptor(exceptionType), constPool)); this.constPool = constPool; }
public StackState dup() { if (contents.isEmpty()) { throw new InvalidBytecodeException("cannot dup empty stack"); } StackEntry type = top(); if (type.getType() == StackEntryType.TOP) { throw new InvalidBytecodeException("Cannot dup wide type"); } return newStack(type); }
public LocalVariableState storeWide(int index, StackEntry entry) { ArrayList<StackEntry> newContents = new ArrayList<StackEntry>(contents.size()); for (int i = 0; i <= index || i < contents.size(); ++i) { if (index == i) { newContents.add(entry); newContents.add(new StackEntry(StackEntryType.TOP, entry.getDescriptor())); ++i; } else if (i >= contents.size()) { // write a null in unitialised slots // not sure if this is correct newContents.add(new StackEntry(StackEntryType.NULL, null)); } else { newContents.add(contents.get(i)); } } return new LocalVariableState(newContents, constPool); }
/** * writes a full_frame to the stack map table */ private void writeFullFrame(DataOutputStream dstream, int offset, int position, StackFrame value) throws IOException { dstream.writeByte(FULL_FRAME); dstream.writeShort(offset); List<StackEntry> realLocalVars = new ArrayList<StackEntry>(value.getLocalVariableState().getContents().size()); for (StackEntry i : value.getLocalVariableState().getContents()) { if (i.getType() != StackEntryType.TOP) { realLocalVars.add(i); } } dstream.writeShort(realLocalVars.size()); for (StackEntry i : realLocalVars) { i.write(dstream); } // TODO: this is inefficient, the stack should store the number of TOP values in each frame List<StackEntry> realStack = new ArrayList<StackEntry>(value.getStackState().getContents().size()); for (StackEntry i : value.getStackState().getContents()) { if (i.getType() != StackEntryType.TOP) { realStack.add(i); } } dstream.writeShort(realStack.size()); for (StackEntry i : realStack) { i.write(dstream); } }
public void aaload() { assertTypeOnStack(StackEntryType.INT, "aaload requires int on top of stack"); if (!getStack().top_1().getDescriptor().startsWith("[")) { throw new InvalidBytecodeException("aaload needs an array in position 2 on the stack"); } writeByte(Opcode.AALOAD); currentOffset++; advanceFrame(currentFrame.pop2push1("Ljava/lang/Object;")); }
public LocalVariableState(final ConstPool pool, final String ... entries) { this.constPool = pool; contents = new ArrayList<StackEntry>(); for(String c : entries) { final StackEntry entry = StackEntry.of(c, constPool); contents.add(entry); } }