/** * This is called for illegal bytecodes. * * @throws InvalidBytecodeException */ private void illegalBytecode(Instruction ins) { throw new InvalidBytecodeException("Illegal bytecode: " + ins); }
/** * Get the number of words consumed by given instruction. */ public int getNumWordsConsumed(Instruction ins) { int numWordsConsumed = ins.consumeStack(cpg); if (numWordsConsumed == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption"); } return numWordsConsumed; }
/** * Get the number of words produced by given instruction. */ public int getNumWordsProduced(Instruction ins) { int numWordsProduced = ins.produceStack(cpg); if (numWordsProduced == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack productions"); } return numWordsProduced; }
/** * This is overridden only to ensure that we don't rely on the base class to * handle instructions that produce stack operands. */ @Override public void modelNormalInstruction(Instruction ins, int numWordsConsumed, int numWordsProduced) { if (VERIFY_INTEGRITY) { if (numWordsProduced > 0) { throw new InvalidBytecodeException("missing visitor method for " + ins); } } super.modelNormalInstruction(ins, numWordsConsumed, numWordsProduced); }
private void checkConsumedAndProducedValues(Instruction ins, ValueNumber[] consumedValueList, ValueNumber[] producedValueList) { int numConsumed = ins.consumeStack(getCPG()); int numProduced = ins.produceStack(getCPG()); if (numConsumed == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins); } if (numProduced == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack production for " + ins); } if (consumedValueList.length != numConsumed) { throw new IllegalStateException("Wrong number of values consumed for " + ins + ": expected " + numConsumed + ", got " + consumedValueList.length); } if (producedValueList.length != numProduced) { throw new IllegalStateException("Wrong number of values produced for " + ins + ": expected " + numProduced + ", got " + producedValueList.length); } }
/** * Consume stack. This is a convenience method for instructions where the * types of popped operands can be ignored. */ protected void consumeStack(Instruction ins) { ConstantPoolGen cpg = getCPG(); TypeFrame frame = getFrame(); int numWordsConsumed = ins.consumeStack(cpg); if (numWordsConsumed == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins); } if (numWordsConsumed > frame.getStackDepth()) { throw new InvalidBytecodeException("Stack underflow for " + ins + ", " + numWordsConsumed + " needed, " + frame.getStackDepth() + " avail, frame is " + frame); } try { while (numWordsConsumed-- > 0) { frame.popValue(); } } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException("Stack underflow for " + ins + ": " + e.getMessage()); } }
/** * Handler for all instructions which pop values from the stack and store * them in a local variable. Note that two locals are stored into for long * and double stores. */ public void handleStoreInstruction(StoreInstruction obj) { try { int numConsumed = obj.consumeStack(cpg); if (numConsumed == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption"); } int index = obj.getIndex(); // Store values into consecutive locals corresponding // to the order in which the values appeared on the stack. while (numConsumed-- > 0) { Value value = frame.popValue(); frame.setValue(index++, value); } } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException(e.toString()); } }
private void handleFieldStore(FieldInstruction ins) { try { // If the resource instance is stored in a field, then it escapes ResourceValueFrame frame = getFrame(); ResourceValue topValue = frame.getTopValue(); if (topValue.equals(ResourceValue.instance())) { frame.setStatus(ResourceValueFrame.ESCAPED); } } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException("Stack underflow", e); } handleNormalInstruction(ins); }
@Override public void visitDUP(DUP obj) { try { Value value = frame.popValue(); frame.pushValue(value); frame.pushValue(value); } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException(e.toString()); } }
@Override public void visitARETURN(ARETURN ins) { try { ResourceValueFrame frame = getFrame(); ResourceValue topValue = frame.getTopValue(); if (topValue.equals(ResourceValue.instance())) { frame.setStatus(ResourceValueFrame.ESCAPED); } } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException("Stack underflow", e); } handleNormalInstruction(ins); }
private void handleArrayStore(ArrayInstruction ins) { try { // If the resource instance is stored in an array, then we consider // it as having escaped. This is conservative; ideally we would // check whether this array is a field or gets passed out of the // method. ResourceValueFrame frame = getFrame(); ResourceValue topValue = frame.getTopValue(); if (topValue.equals(ResourceValue.instance())) { frame.setStatus(ResourceValueFrame.ESCAPED); } } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException("Stack underflow", e); } handleNormalInstruction(ins); }
throw new InvalidBytecodeException("Not enough values on the stack", e);
/** * Pop the input values for the given instruction from the current frame. */ private ValueNumber[] popInputValues(int numWordsConsumed) { ValueNumberFrame frame = getFrame(); ValueNumber[] inputValueList = allocateValueNumberArray(numWordsConsumed); // Pop off the input operands. try { frame.getTopStackWords(inputValueList); while (numWordsConsumed-- > 0) { frame.popValue(); } } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException("Error getting input operands", e); } return inputValueList; }
@Override public void visitSWAP(SWAP obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); frame.pushValue(value1); frame.pushValue(value2); } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException(e.toString()); } }
/** * Handler for all instructions which load values from a local variable and * push them on the stack. Note that two locals are loaded for long and * double loads. */ public void handleLoadInstruction(LoadInstruction obj) { int numProduced = obj.produceStack(cpg); if (numProduced == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack production"); } int index = obj.getIndex() + numProduced; // Load values from locals in reverse order. // This restores them to the stack in a way consistent // with visitStoreInstruction(). while (numProduced-- > 0) { Value value = frame.getValue(--index); frame.pushValue(value); } }
@Override public void visitDUP_X1(DUP_X1 obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); frame.pushValue(value1); frame.pushValue(value2); frame.pushValue(value1); } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException(e.toString()); } }
@Override public void visitDUP2(DUP2 obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); frame.pushValue(value2); frame.pushValue(value1); frame.pushValue(value2); frame.pushValue(value1); } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException(e.toString()); } }
@Override public void visitCHECKCAST(CHECKCAST obj) { try { Type t = getFrame().popValue(); if (t instanceof NullType) { pushValue(t); } else { pushValue(obj.getType(getCPG())); } } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException("Stack underflow for " + obj + ": " + e.getMessage()); } }
throw new InvalidBytecodeException("Error loading from instance field", e);
@Override public void visitDUP_X2(DUP_X2 obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); Value value3 = frame.popValue(); frame.pushValue(value1); frame.pushValue(value3); frame.pushValue(value2); frame.pushValue(value1); } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException(e.toString()); } }