Example usage for org.objectweb.asm Opcodes GOTO

List of usage examples for org.objectweb.asm Opcodes GOTO

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes GOTO.

Prototype

int GOTO

To view the source code for org.objectweb.asm Opcodes GOTO.

Click Source Link

Usage

From source file:org.spongepowered.asm.mixin.injection.points.JumpInsnPoint.java

License:MIT License

public JumpInsnPoint(InjectionPointData data) {
    this.opCode = data.getOpcode(-1, Opcodes.IFEQ, Opcodes.IFNE, Opcodes.IFLT, Opcodes.IFGE, Opcodes.IFGT,
            Opcodes.IFLE, Opcodes.IF_ICMPEQ, Opcodes.IF_ICMPNE, Opcodes.IF_ICMPLT, Opcodes.IF_ICMPGE,
            Opcodes.IF_ICMPGT, Opcodes.IF_ICMPLE, Opcodes.IF_ACMPEQ, Opcodes.IF_ACMPNE, Opcodes.GOTO,
            Opcodes.JSR, Opcodes.IFNULL, Opcodes.IFNONNULL, -1);
    this.ordinal = data.getOrdinal();
}

From source file:org.teavm.flavour.regex.bytecode.MatcherClassBuilder.java

License:Apache License

private void buildEndMethod(ClassVisitor cv, String className, Dfa dfa) {
    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "end", "()" + Type.getDescriptor(Matcher.class), null,
            null);//from www  .j ava 2s  .co  m

    stateLabels = new Label[dfa.getStates().size()];
    Arrays.setAll(stateLabels, i -> new Label());
    int[] keys = new int[dfa.getStates().size()];
    Arrays.setAll(keys, IntUnaryOperator.identity());

    saveLabel = new Label();
    errorLabel = new Label();

    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, className, "state", "I");
    mv.visitLookupSwitchInsn(errorLabel, keys, stateLabels);

    for (int i = 0; i < dfa.getStates().size(); ++i) {
        mv.visitLabel(stateLabels[i]);
        DfaTransition transition = dfa.getStates().get(i).getTransition(-1);
        if (transition == null) {
            mv.visitJumpInsn(Opcodes.GOTO, errorLabel);
        } else {
            DfaState target = transition.getTarget();
            mv.visitIntInsn(Opcodes.SIPUSH, transition.getTarget().getIndex());
            mv.visitVarInsn(Opcodes.ISTORE, 1);
            mv.visitIntInsn(Opcodes.SIPUSH, !target.isTerminal() ? -1 : target.getDomains()[0]);
            mv.visitVarInsn(Opcodes.ISTORE, 2);
            debug(mv, "DFA: " + i + " .-> " + target.getIndex() + " " + Arrays.toString(target.getDomains()));
            mv.visitJumpInsn(Opcodes.GOTO, saveLabel);
        }
    }

    mv.visitLabel(errorLabel);
    debug(mv, "DFA: error");
    mv.visitInsn(Opcodes.ICONST_M1);
    mv.visitVarInsn(Opcodes.ISTORE, 1);
    mv.visitInsn(Opcodes.ICONST_M1);
    mv.visitVarInsn(Opcodes.ISTORE, 2);
    mv.visitLabel(saveLabel);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ILOAD, 1);
    mv.visitFieldInsn(Opcodes.PUTFIELD, className, "state", "I");
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ILOAD, 2);
    mv.visitFieldInsn(Opcodes.PUTFIELD, className, "domain", "I");
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitInsn(Opcodes.ARETURN);

    mv.visitMaxs(3, 3);
    mv.visitEnd();
}

From source file:org.teavm.flavour.regex.bytecode.MatcherClassBuilder.java

License:Apache License

private void buildWorkerMethod(ClassVisitor cv, String className, Dfa dfa) {
    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "feed",
            "(Ljava/lang/String;IIZ)" + Type.getDescriptor(Matcher.class), null, null);
    mv.visitCode();/*from w  w w .j  a v  a2s  .  co m*/

    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, className, "state", "I");
    mv.visitVarInsn(Opcodes.ISTORE, 5);

    errorLabel = new Label();
    saveLabel = new Label();
    loopLabel = new Label();
    continueLabel = new Label();

    mv.visitLabel(loopLabel);
    generateLengthGuard(mv);

    stateLabels = new Label[dfa.getStates().size()];
    Arrays.setAll(stateLabels, i -> new Label());
    int[] keys = new int[dfa.getStates().size()];
    Arrays.setAll(keys, IntUnaryOperator.identity());

    mv.visitVarInsn(Opcodes.ILOAD, 5);
    mv.visitLookupSwitchInsn(errorLabel, keys, stateLabels);

    mv.visitLabel(continueLabel);
    mv.visitIincInsn(2, 1);
    mv.visitJumpInsn(Opcodes.GOTO, loopLabel);

    mv.visitLabel(errorLabel);
    debug(mv, "DFA: error");
    mv.visitInsn(Opcodes.ICONST_M1);
    mv.visitVarInsn(Opcodes.ISTORE, 5);

    mv.visitLabel(saveLabel);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ILOAD, 5);
    mv.visitFieldInsn(Opcodes.PUTFIELD, className, "state", "I");
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ILOAD, 2);
    mv.visitFieldInsn(Opcodes.PUTFIELD, className, "index", "I");
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitInsn(Opcodes.ARETURN);

    for (int i = 0; i < dfa.getStates().size(); ++i) {
        mv.visitLabel(stateLabels[i]);
        DfaState state = dfa.getStates().get(i);
        generateTransitions(state, mv);
    }

    mv.visitMaxs(3, 6);
    mv.visitEnd();
}

From source file:org.teavm.flavour.regex.bytecode.MatcherClassBuilder.java

License:Apache License

private void generateBinaryMatcher(MethodVisitor mv, DfaState source, MapOfChars<DfaState> targets) {
    int[] toggleIndexes = targets.getToggleIndexes();
    if (toggleIndexes.length == 0) {
        debug(mv, "DFA: " + source.getIndex() + " -> error");
        mv.visitJumpInsn(Opcodes.GOTO, errorLabel);
    } else {/*from  w ww .j av a2  s .  c  o  m*/
        generateBinaryMatcher(mv, source, targets, toggleIndexes, 0, toggleIndexes.length - 1);
    }
}

From source file:org.teavm.flavour.regex.bytecode.MatcherClassBuilder.java

License:Apache License

private void generateBinaryMatcher(MethodVisitor mv, DfaState source, MapOfChars<DfaState> targets,
        int[] indexes, int l, int u) {
    int mid = (l + u) / 2;
    mv.visitVarInsn(Opcodes.ILOAD, 6);//from   ww w  . j  a va 2  s  . c o  m
    mv.visitLdcInsn(indexes[mid]);
    mv.visitInsn(Opcodes.ISUB);
    Label less = new Label();
    mv.visitJumpInsn(Opcodes.IFLT, less);

    if (mid + 1 > u) {
        DfaState target = targets.get(indexes[mid]);
        if (target == null) {
            debug(mv, "DFA: " + source.getIndex() + " -> error");
            mv.visitJumpInsn(Opcodes.GOTO, errorLabel);
        } else {
            generateTransition(mv, source, target);
        }
    } else {
        generateBinaryMatcher(mv, source, targets, indexes, mid + 1, u);
    }

    mv.visitLabel(less);

    if (mid - 1 < l) {
        DfaState target = targets.get(indexes[mid] - 1);
        if (target == null) {
            debug(mv, "DFA: " + source.getIndex() + " -> error");
            mv.visitJumpInsn(Opcodes.GOTO, errorLabel);
        } else {
            generateTransition(mv, source, target);
        }
    } else {
        generateBinaryMatcher(mv, source, targets, indexes, l, mid - 1);
    }
}

From source file:org.teavm.flavour.regex.bytecode.MatcherClassBuilder.java

License:Apache License

private void generateTransition(MethodVisitor mv, DfaState source, DfaState target) {
    if (source.isTerminal() && source != target) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitInsn(Opcodes.ICONST_M1);
        mv.visitFieldInsn(Opcodes.PUTFIELD, className, "domain", "I");
    }/* w  w w . j ava 2s. c  o  m*/
    mv.visitIntInsn(Opcodes.SIPUSH, target.getIndex());
    mv.visitVarInsn(Opcodes.ISTORE, 5);
    if (target.isTerminal() && source != target) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitIntInsn(Opcodes.SIPUSH, target.getDomains()[0]);
        mv.visitFieldInsn(Opcodes.PUTFIELD, className, "domain", "I");
    }

    debug(mv, "DFA: " + source.getIndex() + " -> " + target.getIndex() + " "
            + Arrays.toString(target.getDomains()));
    if (target.isTerminal()) {
        Label noReluctant = new Label();
        mv.visitVarInsn(Opcodes.ILOAD, 4);
        mv.visitJumpInsn(Opcodes.IFEQ, noReluctant);
        mv.visitIincInsn(2, 1);
        debug(mv, "DFA reached terminal state");
        mv.visitJumpInsn(Opcodes.GOTO, saveLabel);
        mv.visitLabel(noReluctant);
    }
    if (source.getIndex() + 1 == target.getIndex()) {
        mv.visitIincInsn(2, 1);
        generateLengthGuard(mv);
        mv.visitJumpInsn(Opcodes.GOTO, stateLabels[target.getIndex()]);
    } else {
        mv.visitJumpInsn(Opcodes.GOTO, continueLabel);
    }
}

From source file:org.testeoa.estatica.AdapterDUG.java

License:Open Source License

@Override
public void visitJumpInsn(int opcode, Label label) {
    addInstrucao(getInstrucao(opcode) + " " + label);
    novoAlvo(label);//from  w  w  w .ja  v  a  2 s.co  m
    if (opcode == Opcodes.GOTO) {
        adjacente = false;
    }
    inserirVerticeAtual();
    super.visitJumpInsn(opcode, label);
}

From source file:pku.sei.checkedcoverage.dependenceAnalysis.DependencesExtractor.java

License:Creative Commons License

/**
 * Go backwards through the execution trace of the given threadId and extract
 * all dependences. {@link DependencesVisitor}s should have been added before
 * by calling {@link #registerVisitor(DependencesVisitor, VisitorCapability...)}.
 *
 * @param threadId identifies the thread whose trace should be analyzed
 * @param multithreaded use an extra thread to traverse the trace
 * @throws InterruptedException if the thread was interrupted during traversal
 * @throws IllegalArgumentException if the trace contains no thread with this id
 *///from   w ww . ja v a  2s  .  c  o m
public void processBackwardTrace(ThreadId threadId, boolean multithreaded) throws InterruptedException {

    final BackwardTraceIterator<InstanceType> backwardInsnItr = this.trace.getBackwardIterator(threadId, null,
            this.instanceFactory);

    if (backwardInsnItr == null)
        throw new IllegalArgumentException("No such thread");

    // store the current set of visitors of each capability in an array for better
    // performance and faster empty-check (null reference if empty)
    final DependencesVisitor<? super InstanceType>[] dataDependenceVisitorsReadAfterWrite0 = this.dataDependenceVisitorsReadAfterWrite
            .isEmpty() ? null
                    : this.dataDependenceVisitorsReadAfterWrite.toArray(
                            newDependencesVisitorArray(this.dataDependenceVisitorsReadAfterWrite.size()));
    final DependencesVisitor<? super InstanceType>[] dataDependenceVisitorsWriteAfterRead0 = this.dataDependenceVisitorsWriteAfterRead
            .isEmpty() ? null
                    : this.dataDependenceVisitorsWriteAfterRead.toArray(
                            newDependencesVisitorArray(this.dataDependenceVisitorsWriteAfterRead.size()));
    final DependencesVisitor<? super InstanceType>[] controlDependenceVisitors0 = this.controlDependenceVisitors
            .isEmpty() ? null
                    : this.controlDependenceVisitors
                            .toArray(newDependencesVisitorArray(this.controlDependenceVisitors.size()));
    final DependencesVisitor<? super InstanceType>[] instructionVisitors0 = this.instructionVisitors.isEmpty()
            ? null
            : this.instructionVisitors.toArray(newDependencesVisitorArray(this.instructionVisitors.size()));
    final DependencesVisitor<? super InstanceType>[] pendingDataDependenceVisitorsReadAfterWrite0 = this.pendingDataDependenceVisitorsReadAfterWrite
            .isEmpty() ? null
                    : this.pendingDataDependenceVisitorsReadAfterWrite.toArray(newDependencesVisitorArray(
                            this.pendingDataDependenceVisitorsReadAfterWrite.size()));
    final DependencesVisitor<? super InstanceType>[] pendingDataDependenceVisitorsWriteAfterRead0 = this.pendingDataDependenceVisitorsWriteAfterRead
            .isEmpty() ? null
                    : this.pendingDataDependenceVisitorsWriteAfterRead.toArray(newDependencesVisitorArray(
                            this.pendingDataDependenceVisitorsWriteAfterRead.size()));
    final DependencesVisitor<? super InstanceType>[] pendingControlDependenceVisitors0 = this.pendingControlDependenceVisitors
            .isEmpty() ? null
                    : this.pendingControlDependenceVisitors
                            .toArray(newDependencesVisitorArray(this.pendingControlDependenceVisitors.size()));
    final DependencesVisitor<? super InstanceType>[] methodEntryLeaveVisitors0 = this.methodEntryLeaveVisitors
            .isEmpty() ? null
                    : this.methodEntryLeaveVisitors
                            .toArray(newDependencesVisitorArray(this.methodEntryLeaveVisitors.size()));
    final DependencesVisitor<? super InstanceType>[] objectCreationVisitors0 = this.objectCreationVisitors
            .isEmpty() ? null
                    : this.objectCreationVisitors
                            .toArray(newDependencesVisitorArray(this.objectCreationVisitors.size()));

    @SuppressWarnings("unchecked")
    DependencesVisitor<? super InstanceType>[] allVisitors = union(dataDependenceVisitorsReadAfterWrite0,
            dataDependenceVisitorsWriteAfterRead0, controlDependenceVisitors0, instructionVisitors0,
            pendingDataDependenceVisitorsReadAfterWrite0, pendingDataDependenceVisitorsWriteAfterRead0,
            pendingControlDependenceVisitors0, methodEntryLeaveVisitors0, objectCreationVisitors0);

    IntegerMap<Set<Instruction>> controlDependences = new IntegerMap<Set<Instruction>>();

    Iterator<InstanceType> instanceIterator;
    ProgressInformationProvider progressInfoProv;
    Thread iteratorThread = null;
    final AtomicReference<Throwable> iteratorException = new AtomicReference<Throwable>(null);
    if (multithreaded) {
        final AtomicLong percentPerInstance = this.progressMonitors.isEmpty() ? null
                : new AtomicLong(Double.doubleToLongBits(0)); // this AtomicLong holds a double value!!

        final BlockwiseSynchronizedBuffer<InstanceType> buffer = new BlockwiseSynchronizedBuffer<InstanceType>(
                1 << 16, 1 << 20);
        final InstanceType firstInstance = backwardInsnItr.hasNext() ? backwardInsnItr.next() : null;
        iteratorThread = new Thread("Trace iterator") {
            @Override
            public void run() {
                try {
                    int num = 0;
                    while (backwardInsnItr.hasNext()) {
                        buffer.put(backwardInsnItr.next());
                        if ((++num & ((1 << 16) - 1)) == 0 && percentPerInstance != null) {
                            double percentPerInstance0 = backwardInsnItr.getPercentageDone() / num;
                            percentPerInstance.set(Double.doubleToLongBits(percentPerInstance0));
                        }
                    }
                } catch (Throwable t) {
                    iteratorException.compareAndSet(null, t);
                } finally {
                    try {
                        buffer.put(firstInstance); // to signal that this is the end of the trace
                        buffer.flush();
                    } catch (InterruptedException e) {
                        iteratorException.compareAndSet(null, e);
                    }
                }
            }
        };
        iteratorThread.start();
        final AtomicLong numInstancesSeen = percentPerInstance == null ? null : new AtomicLong(0);
        instanceIterator = new Iterator<InstanceType>() {

            private InstanceType next = firstInstance;

            public boolean hasNext() {
                if (this.next == null) {
                    while (true) {
                        try {
                            this.next = buffer.take();
                            if (this.next == firstInstance) {
                                this.next = null;
                            }
                            break;
                        } catch (InterruptedException e) {
                            // this.next stays null
                            assert this.next == null;
                            Thread.currentThread().interrupt();
                        }
                    }
                }
                return this.next != null;
            }

            public InstanceType next() {
                if (!hasNext())
                    throw new NoSuchElementException();
                InstanceType ret = this.next;
                this.next = null;
                if (numInstancesSeen != null)
                    numInstancesSeen.incrementAndGet();
                return ret;
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }

        };
        progressInfoProv = percentPerInstance == null ? null : new ProgressInformationProvider() {
            public double getPercentageDone() {
                return Double.longBitsToDouble(percentPerInstance.get()) * numInstancesSeen.get();
            }
        };
    } else {
        instanceIterator = backwardInsnItr;
        progressInfoProv = backwardInsnItr;
    }

    // the lastWriter is needed for WAR data dependences
    Map<Variable, InstanceType> lastWriter = new HashMap<Variable, InstanceType>();
    // lastReaders are needed for RAW data dependences
    Map<Variable, List<InstanceType>> lastReaders = new HashMap<Variable, List<InstanceType>>();

    /*
    HashSet<Long> createdObjects = new HashSet<Long>();
    HashSet<Long> seenObjects = new HashSet<Long>();
    */

    InstanceType instance = null;
    Instruction instruction = null;

    for (ProgressMonitor mon : this.progressMonitors)
        mon.start(progressInfoProv);

    try {

        long nextFrameNr = 0;
        int stackDepth = 0;

        List<ReadMethod> initialStackMethods = backwardInsnItr.getInitialStackMethods();

        int allocStack = initialStackMethods.size() + 1;
        allocStack = Integer.highestOneBit(allocStack) * 2;

        @SuppressWarnings("unchecked")
        InstanceType[] atCatchBlockStart = (InstanceType[]) (new InstructionInstance[allocStack]);
        boolean[] throwsException = new boolean[allocStack];
        boolean[] interruptedControlFlow = new boolean[allocStack];
        /**
         * <code>true</code> iff this frame was aborted abnormally (NOT by a RETURN
         * instruction)
         */
        boolean[] abnormalTermination = new boolean[allocStack];
        /**
         * is set to true if the methods entry label has been passed
         */
        boolean[] finished = new boolean[allocStack];
        int[] opStack = new int[allocStack];
        int[] minOpStack = new int[allocStack];
        long[] frames = new long[allocStack];
        Instruction[] lastInstruction = new Instruction[allocStack];
        @SuppressWarnings("unchecked")
        HashSet<InstanceType>[] interestingInstances = (HashSet<InstanceType>[]) new HashSet<?>[allocStack];
        StackEntry[][] cachedStackEntries = new StackEntry[allocStack][];
        LocalVariable[][] cachedLocalVariables = new LocalVariable[allocStack][];
        ReadMethod[] method = new ReadMethod[allocStack];

        for (ReadMethod method0 : initialStackMethods) {
            ++stackDepth;
            method[stackDepth] = method0;
            interruptedControlFlow[stackDepth] = true;
            frames[stackDepth] = nextFrameNr++;
            if (methodEntryLeaveVisitors0 != null)
                for (DependencesVisitor<? super InstanceType> vis : methodEntryLeaveVisitors0)
                    vis.visitMethodLeave(method0, stackDepth);
        }

        for (int i = 1; i < allocStack; ++i) {
            interestingInstances[i] = new HashSet<InstanceType>();
            cachedStackEntries[i] = new StackEntry[8];
            cachedLocalVariables[i] = new LocalVariable[8];
        }

        SimulationEnvironment simEnv = new SimulationEnvironment(frames, opStack, minOpStack,
                cachedStackEntries, cachedLocalVariables, throwsException, lastInstruction, method,
                interruptedControlFlow);

        while (instanceIterator.hasNext()) {

            instance = instanceIterator.next();
            instruction = instance.getInstruction();

            if ((instance.getInstanceNr() & ((1 << 16) - 1)) == 0 && Thread.interrupted())
                throw new InterruptedException();

            int newStackDepth = instance.getStackDepth();
            assert newStackDepth > 0;

            simEnv.removedMethod = null;
            boolean reenter = false;
            if (newStackDepth != stackDepth
                    || (reenter = finished[stackDepth] || method[stackDepth] != instruction.getMethod())) {
                if (newStackDepth >= stackDepth) {
                    // in all steps, the stackDepth can change by at most 1 (except for the very first instruction)
                    assert newStackDepth == stackDepth + 1 || stackDepth == 0 || reenter;
                    if (newStackDepth >= atCatchBlockStart.length) {
                        int oldLen = atCatchBlockStart.length;
                        int newLen = oldLen == 0 ? 8 : 2 * oldLen;
                        atCatchBlockStart = Arrays.copyOf(atCatchBlockStart, newLen);
                        throwsException = Arrays.copyOf(throwsException, newLen);
                        interruptedControlFlow = Arrays.copyOf(interruptedControlFlow, newLen);
                        abnormalTermination = Arrays.copyOf(abnormalTermination, newLen);
                        finished = Arrays.copyOf(finished, newLen);
                        opStack = Arrays.copyOf(opStack, newLen);
                        minOpStack = Arrays.copyOf(minOpStack, newLen);
                        frames = Arrays.copyOf(frames, newLen);
                        interestingInstances = Arrays.copyOf(interestingInstances, newLen);
                        lastInstruction = Arrays.copyOf(lastInstruction, newLen);
                        cachedStackEntries = Arrays.copyOf(cachedStackEntries, newLen);
                        cachedLocalVariables = Arrays.copyOf(cachedLocalVariables, newLen);
                        method = Arrays.copyOf(method, newLen);
                        for (int i = oldLen; i < newLen; ++i) {
                            interestingInstances[i] = new HashSet<InstanceType>();
                            cachedStackEntries[i] = new StackEntry[8];
                            cachedLocalVariables[i] = new LocalVariable[8];
                        }
                        simEnv = new SimulationEnvironment(frames, opStack, minOpStack, cachedStackEntries,
                                cachedLocalVariables, throwsException, lastInstruction, method,
                                interruptedControlFlow);
                    }
                    frames[newStackDepth] = nextFrameNr++;
                    ReadMethod oldMethod = method[newStackDepth];
                    method[newStackDepth] = instruction.getMethod();
                    if (methodEntryLeaveVisitors0 != null) {
                        for (DependencesVisitor<? super InstanceType> vis : methodEntryLeaveVisitors0) {
                            if (reenter)
                                vis.visitMethodEntry(oldMethod, newStackDepth);
                            vis.visitMethodLeave(method[newStackDepth], newStackDepth);
                        }
                    }

                    if (reenter) {
                        cleanUpExecutionFrame(simEnv, stackDepth, lastReaders, lastWriter,
                                pendingDataDependenceVisitorsWriteAfterRead0,
                                pendingDataDependenceVisitorsReadAfterWrite0,
                                dataDependenceVisitorsWriteAfterRead0, dataDependenceVisitorsReadAfterWrite0);
                    }

                    atCatchBlockStart[newStackDepth] = null;
                    if (instruction == method[newStackDepth].getAbnormalTerminationLabel()) {
                        throwsException[newStackDepth] = interruptedControlFlow[newStackDepth] = abnormalTermination[newStackDepth] = true;
                        interruptedControlFlow[stackDepth] = true;
                    } else {
                        throwsException[newStackDepth] = interruptedControlFlow[newStackDepth] = abnormalTermination[newStackDepth] = false;
                    }
                    finished[newStackDepth] = false;
                    opStack[newStackDepth] = 0;
                    minOpStack[newStackDepth] = 0;
                    interestingInstances[newStackDepth].clear();
                    if (cachedLocalVariables[newStackDepth].length > 128)
                        cachedLocalVariables[newStackDepth] = new LocalVariable[8];
                    else
                        Arrays.fill(cachedLocalVariables[newStackDepth], null);
                    if (cachedStackEntries[newStackDepth].length > 128)
                        cachedStackEntries[newStackDepth] = new StackEntry[8];
                    else
                        Arrays.fill(cachedStackEntries[newStackDepth], null);

                } else {
                    assert newStackDepth == stackDepth - 1;
                    if (methodEntryLeaveVisitors0 != null) {
                        for (DependencesVisitor<? super InstanceType> vis : methodEntryLeaveVisitors0) {
                            vis.visitMethodEntry(method[stackDepth], stackDepth);
                        }
                    }
                    simEnv.removedMethod = method[stackDepth];
                }
            }
            stackDepth = newStackDepth;

            if (simEnv.removedMethod == null && (this.untracedMethodsVisitors != null)
                    && (instruction.getType() == InstructionType.METHODINVOCATION)) {
                for (DependencesVisitor<? super InstanceType> vis : this.untracedMethodsVisitors)
                    vis.visitUntracedMethodCall(instance);
            }

            if (instruction == instruction.getMethod().getMethodEntryLabel())
                finished[stackDepth] = true;
            lastInstruction[stackDepth] = instruction;

            if (atCatchBlockStart[stackDepth] != null)
                throwsException[stackDepth] = true;

            DynamicInformation dynInfo = this.simulator.simulateInstruction(instance, simEnv);

            if (instructionVisitors0 != null)
                for (DependencesVisitor<? super InstanceType> vis : instructionVisitors0)
                    vis.visitInstructionExecution(instance);

            // the computation of control dependences only has to be performed
            // if there are any controlDependenceVisitors
            if (controlDependenceVisitors0 != null) {
                if (simEnv.removedMethod != null && !interestingInstances[stackDepth + 1].isEmpty()) {
                    // ok, we have a control dependence since the method was called by (or for) this instruction
                    // checking if this is the instr. that directly called the method is impossible
                    for (InstanceType depend : interestingInstances[stackDepth + 1]) {
                        for (DependencesVisitor<? super InstanceType> vis : controlDependenceVisitors0) {
                            vis.visitControlDependence(depend, instance);
                        }
                    }
                    interestingInstances[stackDepth].add(instance);
                }

                Set<Instruction> instrControlDependences = controlDependences.get(instruction.getIndex());
                if (instrControlDependences == null) {
                    computeControlDependences(instruction.getMethod(), controlDependences);
                    instrControlDependences = controlDependences.get(instruction.getIndex());
                    assert instrControlDependences != null;
                }
                boolean isExceptionsThrowingInstruction = throwsException[stackDepth]
                        && (instruction.getType() != InstructionType.LABEL
                                || !((LabelMarker) instruction).isAdditionalLabel())
                        && (instruction.getOpcode() != Opcodes.GOTO);
                // assert: every ATHROW must be an exception throwing instance
                assert (instruction.getOpcode() != Opcodes.ATHROW || isExceptionsThrowingInstruction);
                // get all interesting instructions, that are dependent on the current one
                Set<InstanceType> dependantInterestingInstances = getInstanceIntersection(
                        instrControlDependences, interestingInstances[stackDepth]);
                if (isExceptionsThrowingInstruction) {
                    throwsException[stackDepth] = false;
                    // in this case, we have an additional control dependence from the catching to
                    // the throwing instruction, and a data dependence on the thrown instruction
                    for (int i = stackDepth; i > 0; --i) {
                        if (atCatchBlockStart[i] != null) {
                            if (interestingInstances[i].contains(atCatchBlockStart[i])) {
                                if (dependantInterestingInstances.isEmpty())
                                    dependantInterestingInstances = Collections.singleton(atCatchBlockStart[i]);
                                else
                                    dependantInterestingInstances.add(atCatchBlockStart[i]);
                            }
                            atCatchBlockStart[i] = null;

                            // data dependence:
                            // (the stack height has already been decremented when entering the catch block)
                            Variable definedException = simEnv.getOpStackEntry(i, opStack[i]);
                            dynInfo = AdditionalDataDependence.annotate(dynInfo, definedException,
                                    dynInfo.getUsedVariables());

                            break;
                        }
                    }
                }
                if (!dependantInterestingInstances.isEmpty()) {
                    for (InstanceType depend : dependantInterestingInstances) {
                        for (DependencesVisitor<? super InstanceType> vis : controlDependenceVisitors0) {
                            vis.visitControlDependence(depend, instance);
                        }
                    }
                    interestingInstances[stackDepth].removeAll(dependantInterestingInstances);
                }
                interestingInstances[stackDepth].add(instance);
            }
            // TODO check this:
            if (pendingControlDependenceVisitors0 != null) {
                interestingInstances[stackDepth].add(instance);
                for (DependencesVisitor<? super InstanceType> vis : pendingControlDependenceVisitors0)
                    vis.visitPendingControlDependence(instance);
            }

            Collection<? extends Variable> definedVariables = dynInfo.getDefinedVariables();
            if (!definedVariables.isEmpty()) {
                /*
                for (Variable definedVariable: dynInfo.getDefinedVariables()) {
                if (definedVariable instanceof ObjectField) {
                    seenObjects.add(((ObjectField)definedVariable).getObjectId());
                    assert !createdObjects.contains(((ObjectField)definedVariable).getObjectId());
                }
                if (definedVariable instanceof ArrayElement) {
                    seenObjects.add(((ArrayElement)definedVariable).getArrayId());
                    assert !createdObjects.contains(((ArrayElement)definedVariable).getArrayId());
                }
                }
                */
                if (dataDependenceVisitorsReadAfterWrite0 != null
                        || dataDependenceVisitorsWriteAfterRead0 != null
                        || pendingDataDependenceVisitorsWriteAfterRead0 != null) {
                    for (Variable definedVariable : definedVariables) {
                        if (!(definedVariable instanceof StackEntry)) {
                            // we ignore WAR dependences over the stack!
                            if (pendingDataDependenceVisitorsWriteAfterRead0 != null) {
                                // for each defined variable, we have a pending WAR dependence
                                // if the lastWriter is not null, we first discard old pending dependences
                                InstanceType varLastWriter = lastWriter.put(definedVariable, instance);
                                for (DependencesVisitor<? super InstanceType> vis : pendingDataDependenceVisitorsWriteAfterRead0) {
                                    if (varLastWriter != null)
                                        vis.discardPendingDataDependence(varLastWriter, definedVariable,
                                                DataDependenceType.WRITE_AFTER_READ);
                                    vis.visitPendingDataDependence(instance, definedVariable,
                                            DataDependenceType.WRITE_AFTER_READ);
                                }
                                // otherwise, if there are WAR visitors, we only update the lastWriter
                            } else if (dataDependenceVisitorsWriteAfterRead0 != null) {
                                lastWriter.put(definedVariable, instance);
                            }
                        }
                        // if we have RAW visitors, we need to analyse the lastReaders
                        if (dataDependenceVisitorsReadAfterWrite0 != null
                                || pendingDataDependenceVisitorsReadAfterWrite0 != null) {
                            List<InstanceType> readers = lastReaders.remove(definedVariable);
                            if (readers != null) {
                                Collection<? extends Variable> usedVariables = dataDependenceVisitorsReadAfterWrite0 != null
                                        ? dynInfo.getUsedVariables(definedVariable)
                                        : null;
                                for (InstanceType reader : readers) {
                                    if (dataDependenceVisitorsReadAfterWrite0 != null) {
                                        for (DependencesVisitor<? super InstanceType> vis : dataDependenceVisitorsReadAfterWrite0)
                                            vis.visitDataDependence(reader, instance, usedVariables,
                                                    definedVariable, DataDependenceType.READ_AFTER_WRITE);
                                    }
                                    if (pendingDataDependenceVisitorsReadAfterWrite0 != null)
                                        for (DependencesVisitor<? super InstanceType> vis : pendingDataDependenceVisitorsReadAfterWrite0)
                                            vis.discardPendingDataDependence(reader, definedVariable,
                                                    DataDependenceType.READ_AFTER_WRITE);
                                }
                            }
                        }
                    }
                }
            }

            Collection<? extends Variable> usedVariables = dynInfo.getUsedVariables();
            if (!usedVariables.isEmpty()) {
                /*
                for (Variable usedVariable: dynInfo.getUsedVariables()) {
                if (usedVariable instanceof ObjectField) {
                    seenObjects.add(((ObjectField)usedVariable).getObjectId());
                    assert !createdObjects.contains(((ObjectField)usedVariable).getObjectId());
                }
                if (usedVariable instanceof ArrayElement) {
                    seenObjects.add(((ArrayElement)usedVariable).getArrayId());
                    assert !createdObjects.contains(((ArrayElement)usedVariable).getArrayId());
                }
                }
                */

                if (dataDependenceVisitorsWriteAfterRead0 != null
                        || dataDependenceVisitorsReadAfterWrite0 != null
                        || pendingDataDependenceVisitorsReadAfterWrite0 != null) {
                    for (Variable usedVariable : usedVariables) {
                        // if we have WAR visitors, we inform them about a new dependence
                        if (dataDependenceVisitorsWriteAfterRead0 != null
                                && !(usedVariable instanceof StackEntry)) {
                            InstanceType lastWriterInst = lastWriter.get(usedVariable);

                            // avoid self-loops in the DDG (e.g. for IINC, which reads and writes to the same variable)
                            if (lastWriterInst != null && lastWriterInst != instance) {
                                for (DependencesVisitor<? super InstanceType> vis : dataDependenceVisitorsWriteAfterRead0)
                                    vis.visitDataDependence(lastWriterInst, instance, null, usedVariable,
                                            DataDependenceType.WRITE_AFTER_READ);
                            }
                        }

                        // for RAW visitors, update the lastReaders
                        if (dataDependenceVisitorsReadAfterWrite0 != null
                                || pendingDataDependenceVisitorsReadAfterWrite0 != null) {
                            List<InstanceType> readers = lastReaders.get(usedVariable);
                            if (readers == null) {
                                readers = new ArrayList<InstanceType>(4);
                                lastReaders.put(usedVariable, readers);
                            }
                            readers.add(instance);
                            // for each used variable, we have a pending RAW dependence
                            if (pendingDataDependenceVisitorsReadAfterWrite0 != null) {
                                for (DependencesVisitor<? super InstanceType> vis : pendingDataDependenceVisitorsReadAfterWrite0)
                                    vis.visitPendingDataDependence(instance, usedVariable,
                                            DataDependenceType.READ_AFTER_WRITE);
                            }
                        }
                    }
                }
            }

            for (Entry<Long, Collection<? extends Variable>> e : dynInfo.getCreatedObjects().entrySet()) {
                /*
                boolean added = createdObjects.add(e.getKey());
                assert added;
                */

                for (Variable var : e.getValue()) {
                    assert var instanceof ObjectField || var instanceof ArrayElement;
                    // clean up lastWriter if we have any WAR visitors
                    if (pendingDataDependenceVisitorsWriteAfterRead0 != null) {
                        InstanceType inst;
                        if ((inst = lastWriter.remove(var)) != null)
                            for (DependencesVisitor<? super InstanceType> vis : pendingDataDependenceVisitorsWriteAfterRead0)
                                vis.discardPendingDataDependence(inst, var,
                                        DataDependenceType.WRITE_AFTER_READ);
                    } else if (dataDependenceVisitorsWriteAfterRead0 != null)
                        lastWriter.remove(var);
                    // clean up lastReaders if we have any RAW visitors
                    if (dataDependenceVisitorsReadAfterWrite0 != null
                            || pendingDataDependenceVisitorsReadAfterWrite0 != null) {
                        List<InstanceType> instList;
                        if ((instList = lastReaders.remove(var)) != null) {
                            if (dataDependenceVisitorsReadAfterWrite0 != null)
                                for (DependencesVisitor<? super InstanceType> vis : dataDependenceVisitorsReadAfterWrite0)
                                    for (InstanceType instrInst : instList)
                                        vis.visitDataDependence(instrInst, instance,
                                                Collections.<Variable>emptySet(), var,
                                                DataDependenceType.READ_AFTER_WRITE);
                            if (pendingDataDependenceVisitorsReadAfterWrite0 != null)
                                for (DependencesVisitor<? super InstanceType> vis : pendingDataDependenceVisitorsReadAfterWrite0)
                                    for (InstanceType instrInst : instList)
                                        vis.discardPendingDataDependence(instrInst, var,
                                                DataDependenceType.READ_AFTER_WRITE);
                        }
                    }
                }
                if (objectCreationVisitors0 != null)
                    for (DependencesVisitor<? super InstanceType> vis : objectCreationVisitors0)
                        vis.visitObjectCreation(e.getKey(), instance);
            }

            if (dynInfo.isCatchBlock()) {
                atCatchBlockStart[stackDepth] = instance;
                interruptedControlFlow[stackDepth] = true;
            } else if (atCatchBlockStart[stackDepth] != null) {
                atCatchBlockStart[stackDepth] = null;
            }

            if (simEnv.removedMethod != null) {
                cleanUpExecutionFrame(simEnv, stackDepth + 1, lastReaders, lastWriter,
                        pendingDataDependenceVisitorsWriteAfterRead0,
                        pendingDataDependenceVisitorsReadAfterWrite0, dataDependenceVisitorsWriteAfterRead0,
                        dataDependenceVisitorsReadAfterWrite0);
            }

            /*
            if (instance.getInstanceNr() % 1000000 == 0) {
            for (Variable var: lastReaders.keySet()) {
                if (var instanceof ObjectField) {
                    assert seenObjects.contains(((ObjectField)var).getObjectId());
                    assert !createdObjects.contains(((ObjectField)var).getObjectId());
                }
                if (var instanceof ArrayElement) {
                    assert seenObjects.contains(((ArrayElement)var).getArrayId());
                    assert !createdObjects.contains(((ArrayElement)var).getArrayId());
                }
                if (var instanceof StackEntry)
                    assert frames.contains(((StackEntry)var).getFrame());
                if (var instanceof LocalVariable) {
                    assert frames.contains(((LocalVariable)var).getFrame());
                }
            }
            for (Variable var: lastWriter.keySet()) {
                if (var instanceof ObjectField) {
                    assert seenObjects.contains(((ObjectField)var).getObjectId());
                    assert !createdObjects.contains(((ObjectField)var).getObjectId());
                }
                if (var instanceof ArrayElement) {
                    assert seenObjects.contains(((ArrayElement)var).getArrayId());
                    assert !createdObjects.contains(((ArrayElement)var).getArrayId());
                }
                // we do not store the last writer of a stack entry
                assert !(var instanceof StackEntry);
                if (var instanceof LocalVariable) {
                    assert frames.contains(((LocalVariable)var).getFrame());
                }
            }
            }
            */
        }
        Throwable t = iteratorException.get();
        if (t != null) {
            if (t instanceof RuntimeException)
                throw (RuntimeException) t;
            if (t instanceof Error)
                throw (Error) t;
            if (t instanceof InterruptedException)
                throw (InterruptedException) t;
            throw new TracerException("Iterator should not throw anything but RuntimeExceptions", t);
        }

        if (Thread.interrupted())
            throw new InterruptedException();

        cleanUpMaps(lastWriter, lastReaders, pendingDataDependenceVisitorsWriteAfterRead0,
                pendingDataDependenceVisitorsReadAfterWrite0);

        for (DependencesVisitor<? super InstanceType> vis : allVisitors)
            vis.visitEnd(instance == null ? 0 : instance.getInstanceNr());

        if (Thread.interrupted())
            throw new InterruptedException();
    } catch (InterruptedException e) {
        for (DependencesVisitor<? super InstanceType> vis : allVisitors)
            vis.interrupted();
        throw e;
    } finally {
        if (iteratorThread != null)
            iteratorThread.interrupt();
        for (ProgressMonitor mon : this.progressMonitors)
            mon.end();
    }
}

From source file:pku.sei.checkedcoverage.slicing.DirectSlicer.java

License:Creative Commons License

public Set<Instruction> getDynamicSlice(ThreadId threadId, List<SlicingCriterion> sc) {
    BackwardTraceIterator<InstructionInstance> backwardInsnItr = this.trace.getBackwardIterator(threadId, null);

    IntegerMap<Set<Instruction>> controlDependences = new IntegerMap<Set<Instruction>>();

    Set<Variable> interestingVariables = new HashSet<Variable>();
    Set<Instruction> dynamicSlice = new HashSet<Instruction>();

    long nextFrameNr = 0;
    int stackDepth = 0;

    List<ReadMethod> initialStackMethods = backwardInsnItr.getInitialStackMethods();

    int allocStack = initialStackMethods.size() + 1;
    allocStack = Integer.highestOneBit(allocStack) * 2;

    Instruction[] atCatchBlockStart = new Instruction[allocStack];
    boolean[] throwsException = new boolean[allocStack];
    boolean[] interruptedControlFlow = new boolean[allocStack];
    /**/*w  ww .  j a  v  a  2  s . co  m*/
     * <code>true</code> iff this frame was aborted abnormally (NOT by a RETURN
     * instruction)
     */
    boolean[] abnormalTermination = new boolean[allocStack];
    /**
     * is set to true if the methods entry label has been passed
     */
    boolean[] finished = new boolean[allocStack];
    int[] opStack = new int[allocStack];
    int[] minOpStack = new int[allocStack];
    long[] frames = new long[allocStack];
    Instruction[] lastInstruction = new Instruction[allocStack];
    @SuppressWarnings("unchecked")
    HashSet<Instruction>[] interestingInstructions = (HashSet<Instruction>[]) new HashSet<?>[allocStack];
    StackEntry[][] cachedStackEntries = new StackEntry[allocStack][];
    LocalVariable[][] cachedLocalVariables = new LocalVariable[allocStack][];
    ReadMethod[] method = new ReadMethod[allocStack];

    for (ReadMethod method0 : initialStackMethods) {
        ++stackDepth;
        method[stackDepth] = method0;
        interruptedControlFlow[stackDepth] = true;
        frames[stackDepth] = nextFrameNr++;
    }

    for (int i = 1; i < allocStack; ++i) {
        interestingInstructions[i] = new HashSet<Instruction>();
        cachedStackEntries[i] = new StackEntry[8];
        cachedLocalVariables[i] = new LocalVariable[8];
    }

    SimulationEnvironment simEnv = new SimulationEnvironment(frames, opStack, minOpStack, cachedStackEntries,
            cachedLocalVariables, throwsException, lastInstruction, method, interruptedControlFlow);

    List<SlicingCriterionInstance> slicingCriteria;
    if (sc.isEmpty())
        slicingCriteria = Collections.emptyList();
    else if (sc.size() == 1)
        slicingCriteria = Collections.singletonList(sc.get(0).getInstance());
    else {
        slicingCriteria = new ArrayList<SlicingCriterionInstance>(sc.size());
        for (SlicingCriterion crit : sc)
            slicingCriteria.add(crit.getInstance());
    }

    for (ProgressMonitor mon : this.progressMonitors)
        mon.start(backwardInsnItr);
    try {
        @SuppressWarnings("unchecked")
        Set<Variable>[] matchedCriterionVariables = (Set<Variable>[]) new Set<?>[8];

        while (backwardInsnItr.hasNext()) {
            InstructionInstance instance = backwardInsnItr.next();
            Instruction instruction = instance.getInstruction();

            int newStackDepth = instance.getStackDepth();
            assert newStackDepth > 0;

            simEnv.removedMethod = null;
            boolean reenter = false;
            if (newStackDepth != stackDepth
                    || (reenter = finished[stackDepth] || method[stackDepth] != instruction.getMethod())) {
                if (newStackDepth >= stackDepth) {
                    // in all steps, the stackDepth can change by at most 1 (except for the very first instruction)
                    assert newStackDepth == stackDepth + 1 || stackDepth == 0 || reenter;
                    if (newStackDepth >= atCatchBlockStart.length) {
                        int oldLen = atCatchBlockStart.length;
                        int newLen = oldLen == 0 ? 8 : 2 * oldLen;
                        atCatchBlockStart = Arrays.copyOf(atCatchBlockStart, newLen);
                        throwsException = Arrays.copyOf(throwsException, newLen);
                        interruptedControlFlow = Arrays.copyOf(interruptedControlFlow, newLen);
                        abnormalTermination = Arrays.copyOf(abnormalTermination, newLen);
                        finished = Arrays.copyOf(finished, newLen);
                        opStack = Arrays.copyOf(opStack, newLen);
                        minOpStack = Arrays.copyOf(minOpStack, newLen);
                        frames = Arrays.copyOf(frames, newLen);
                        interestingInstructions = Arrays.copyOf(interestingInstructions, newLen);
                        lastInstruction = Arrays.copyOf(lastInstruction, newLen);
                        cachedStackEntries = Arrays.copyOf(cachedStackEntries, newLen);
                        cachedLocalVariables = Arrays.copyOf(cachedLocalVariables, newLen);
                        method = Arrays.copyOf(method, newLen);
                        for (int i = oldLen; i < newLen; ++i) {
                            interestingInstructions[i] = new HashSet<Instruction>();
                            cachedStackEntries[i] = new StackEntry[8];
                            cachedLocalVariables[i] = new LocalVariable[8];
                        }
                        simEnv = new SimulationEnvironment(frames, opStack, minOpStack, cachedStackEntries,
                                cachedLocalVariables, throwsException, lastInstruction, method,
                                interruptedControlFlow);
                    }
                    frames[newStackDepth] = nextFrameNr++;
                    method[newStackDepth] = instruction.getMethod();

                    atCatchBlockStart[newStackDepth] = null;
                    if (instruction == method[newStackDepth].getAbnormalTerminationLabel()) {
                        throwsException[newStackDepth] = interruptedControlFlow[newStackDepth] = abnormalTermination[newStackDepth] = true;
                        interruptedControlFlow[stackDepth] = true;
                    } else {
                        throwsException[newStackDepth] = interruptedControlFlow[newStackDepth] = abnormalTermination[newStackDepth] = false;
                    }
                    finished[newStackDepth] = false;
                    opStack[newStackDepth] = 0;
                    minOpStack[newStackDepth] = 0;
                    interestingInstructions[newStackDepth].clear();
                    if (cachedLocalVariables[newStackDepth].length > 128)
                        cachedLocalVariables[newStackDepth] = new LocalVariable[8];
                    else
                        Arrays.fill(cachedLocalVariables[newStackDepth], null);
                    if (cachedStackEntries[newStackDepth].length > 128)
                        cachedStackEntries[newStackDepth] = new StackEntry[8];
                    else
                        Arrays.fill(cachedStackEntries[newStackDepth], null);
                } else {
                    assert newStackDepth == stackDepth - 1;
                    simEnv.removedMethod = method[stackDepth];
                }
            }
            stackDepth = newStackDepth;

            if (atCatchBlockStart[stackDepth] != null)
                throwsException[stackDepth] = true;

            if (instruction == instruction.getMethod().getMethodEntryLabel())
                finished[stackDepth] = true;
            lastInstruction[stackDepth] = instruction;

            DynamicInformation dynInfo = this.simulator.simulateInstruction(instance, simEnv);

            if (simEnv.removedMethod != null && !interestingInstructions[stackDepth + 1].isEmpty()) {
                // ok, we have a control dependence since the method was called by (or for) this instruction
                // checking if this is the instr. that directly called the method is impossible
                dynamicSlice.add(instruction);
                interestingInstructions[stackDepth].add(instruction);
            }

            if (matchedCriterionVariables.length <= stackDepth) {
                @SuppressWarnings("unchecked")
                Set<Variable>[] newMatchedCriterionVariables = (Set<Variable>[]) new Set<?>[2
                        * Math.max(stackDepth, matchedCriterionVariables.length)];
                System.arraycopy(matchedCriterionVariables, 0, newMatchedCriterionVariables, 0,
                        matchedCriterionVariables.length);
                matchedCriterionVariables = newMatchedCriterionVariables;
            }
            for (SlicingCriterionInstance crit : slicingCriteria) {
                if (crit.matches(instance)) {
                    if (matchedCriterionVariables[stackDepth] == null)
                        matchedCriterionVariables[stackDepth] = new HashSet<Variable>();
                    if (crit.matchAllData()) {
                        matchedCriterionVariables[stackDepth].removeAll(dynInfo.getDefinedVariables());
                        matchedCriterionVariables[stackDepth].addAll(dynInfo.getUsedVariables());
                    } else if (crit.hasLocalVariables()) {
                        for (pku.sei.checkedcoverage.common.classRepresentation.LocalVariable var : crit
                                .getLocalVariables())
                            interestingVariables.add(simEnv.getLocalVariable(stackDepth, var.getIndex()));
                    } else {
                        interestingInstructions[stackDepth].add(instance.getInstruction());
                        dynamicSlice.add(instruction);
                    }
                } else if (matchedCriterionVariables[stackDepth] != null) {
                    interestingVariables.addAll(matchedCriterionVariables[stackDepth]);
                    matchedCriterionVariables[stackDepth] = null;
                }
            }

            boolean isExceptionsThrowingInstance = throwsException[stackDepth]
                    && (instruction.getType() != InstructionType.LABEL
                            || !((LabelMarker) instruction).isAdditionalLabel())
                    && (instruction.getOpcode() != Opcodes.GOTO);
            if (!interestingInstructions[stackDepth].isEmpty() || isExceptionsThrowingInstance) {
                Set<Instruction> instrControlDependences = controlDependences.get(instruction.getIndex());
                if (instrControlDependences == null) {
                    computeControlDependences(instruction.getMethod(), controlDependences);
                    instrControlDependences = controlDependences.get(instruction.getIndex());
                    assert instrControlDependences != null;
                }
                // get all interesting instructions, that are dependent on the current one
                Set<Instruction> dependantInterestingInstructions = intersect(instrControlDependences,
                        interestingInstructions[stackDepth]);
                if (isExceptionsThrowingInstance) {
                    throwsException[stackDepth] = false;
                    // in this case, we have an additional control dependence from the catching to
                    // the throwing instruction, and a data dependence on the thrown instruction
                    for (int i = stackDepth; i > 0; --i) {
                        if (atCatchBlockStart[i] != null) {
                            if (interestingInstructions[i].contains(atCatchBlockStart[i])) {
                                if (dependantInterestingInstructions.isEmpty())
                                    dependantInterestingInstructions = Collections
                                            .singleton(atCatchBlockStart[i]);
                                else
                                    dependantInterestingInstructions.add(atCatchBlockStart[i]);
                            }
                            atCatchBlockStart[i] = null;

                            // data dependence:
                            // (the stack height has already been decremented when entering the catch block)
                            Variable definedException = simEnv.getOpStackEntry(i, opStack[i]);
                            if (interestingVariables.contains(definedException)) {
                                interestingInstructions[stackDepth].add(instruction);
                                dynamicSlice.add(instruction);
                                interestingVariables.remove(definedException);
                                interestingVariables.addAll(dynInfo.getUsedVariables());
                            }

                            break;
                        }
                    }
                }
                if (!dependantInterestingInstructions.isEmpty()) {
                    dynamicSlice.add(instruction);
                    interestingInstructions[stackDepth].removeAll(dependantInterestingInstructions);
                    interestingInstructions[stackDepth].add(instruction);
                    interestingVariables.addAll(dynInfo.getUsedVariables());
                }
            }

            if (!interestingVariables.isEmpty()) {
                for (Variable definedVariable : dynInfo.getDefinedVariables()) {
                    if (interestingVariables.contains(definedVariable)) {
                        interestingInstructions[stackDepth].add(instruction);
                        dynamicSlice.add(instruction);
                        interestingVariables.remove(definedVariable);
                        interestingVariables.addAll(dynInfo.getUsedVariables(definedVariable));
                    }
                }
            }

            if (dynInfo.isCatchBlock()) {
                atCatchBlockStart[stackDepth] = instance.getInstruction();
                interruptedControlFlow[stackDepth] = true;
            } else if (atCatchBlockStart[stackDepth] != null) {
                atCatchBlockStart[stackDepth] = null;
            }

        }
    } finally {
        for (ProgressMonitor mon : this.progressMonitors)
            mon.end();
    }

    for (Iterator<Instruction> it = dynamicSlice.iterator(); it.hasNext();) {
        Instruction instr = it.next();
        if (instr.getType() == InstructionType.LABEL || instr.getOpcode() == Opcodes.GOTO)
            it.remove();
    }

    return dynamicSlice;
}

From source file:pku.sei.checkedcoverage.slicing.Slicer.java

License:Creative Commons License

public void process(ThreadId threadId, final List<SlicingCriterion> sc, boolean multithreaded)
        throws InterruptedException {
    DependencesExtractor<SlicerInstance> depExtractor = DependencesExtractor.forTrace(this.trace,
            SlicerInstanceFactory.instance);
    for (ProgressMonitor mon : this.progressMonitors)
        depExtractor.addProgressMonitor(mon);

    VisitorCapability[] capabilities = { VisitorCapability.CONTROL_DEPENDENCES,
            VisitorCapability.DATA_DEPENDENCES_READ_AFTER_WRITE, VisitorCapability.INSTRUCTION_EXECUTIONS,
            VisitorCapability.METHOD_ENTRY_LEAVE, VisitorCapability.CONTROL_DEPENDENCES };
    if (this.untracedCallVisitors.size() > 0)
        capabilities[capabilities.length - 1] = VisitorCapability.UNTRACED_METHOD_CALLS;

    final List<SliceVisitor> sliceVisitors0 = Slicer.this.sliceVisitors;
    final List<UntracedCallVisitor> untracedCallVisitors0 = Slicer.this.untracedCallVisitors;
    depExtractor.registerVisitor(new DependencesVisitorAdapter<SlicerInstance>() {
        private final List<SlicingCriterionInstance> slicingCritInst = instantiateSlicingCriteria(sc);
        @SuppressWarnings("unchecked")
        private IntegerMap<Object>[] interestingLocalVariables = (IntegerMap<Object>[]) new IntegerMap<?>[0];
        private long[] critOccurenceNumbers = new long[2]; // 0 if not in a criterion
        private final SliceVisitor[] sliceVisitorsArray = sliceVisitors0
                .toArray(new SliceVisitor[sliceVisitors0.size()]);
        private final UntracedCallVisitor[] untracedCallsVisitorsArray = untracedCallVisitors0
                .toArray(new UntracedCallVisitor[untracedCallVisitors0.size()]);

        private ReadMethod enteredMethod;

        private List<SlicingCriterionInstance> instantiateSlicingCriteria(List<SlicingCriterion> criteria) {
            if (criteria.isEmpty())
                return Collections.emptyList();
            else if (criteria.size() == 1)
                return Collections.singletonList(criteria.get(0).getInstance());
            else {
                List<SlicingCriterionInstance> instances = new ArrayList<SlicingCriterionInstance>(
                        criteria.size());
                for (SlicingCriterion crit : criteria)
                    instances.add(crit.getInstance());
                return instances;
            }//from www .j a v a2  s . c o  m
        }

        @Override
        public void visitInstructionExecution(SlicerInstance instance) {
            int stackDepth = instance.getStackDepth();
            if (this.critOccurenceNumbers.length <= stackDepth) {
                long[] newCritOccurenceNumbers = new long[2
                        * Math.max(this.critOccurenceNumbers.length, stackDepth)];
                System.arraycopy(this.critOccurenceNumbers, 0, newCritOccurenceNumbers, 0,
                        this.critOccurenceNumbers.length);
                this.critOccurenceNumbers = newCritOccurenceNumbers;
            }
            Instruction instruction = instance.getInstruction();
            for (SlicingCriterionInstance crit : this.slicingCritInst) {
                if (crit.matches(instance)) {
                    this.critOccurenceNumbers[stackDepth] = crit.getOccurenceNumber();
                    assert (this.critOccurenceNumbers[stackDepth] > 0);
                    // for each criterion, there are three cases:
                    //  - track all data read in this line
                    //  - track a given set of local variables
                    //  - track the control dependences of this instruction
                    // only in the last case, the instructions from that line are added to the dynamic slice
                    if (crit.matchAllData()) {
                        instance.allDataInteresting = true;
                        instance.onlyIfAfterCriterion = true;
                        instance.onDynamicSlice = true; // it's not really on the dynamic slice, but we have to set this
                        instance.criterionDistance = 0;
                    } else {
                        if (crit.hasLocalVariables()) {
                            if (this.interestingLocalVariables.length <= stackDepth) {
                                @SuppressWarnings("unchecked")
                                IntegerMap<Object>[] newInterestingLocalVariables = (IntegerMap<Object>[]) new IntegerMap<?>[Math
                                        .max(stackDepth + 1, this.interestingLocalVariables.length * 3 / 2)];
                                System.arraycopy(this.interestingLocalVariables, 0,
                                        newInterestingLocalVariables, 0, this.interestingLocalVariables.length);
                                this.interestingLocalVariables = newInterestingLocalVariables;
                            }
                            List<LocalVariable> localVariables = crit.getLocalVariables();
                            if (this.interestingLocalVariables[stackDepth] == null)
                                this.interestingLocalVariables[stackDepth] = new IntegerMap<Object>(
                                        localVariables.size() * 4 / 3 + 1);
                            for (LocalVariable i : localVariables)
                                this.interestingLocalVariables[stackDepth].put(i.getIndex(), null);
                        } else {
                            Instruction insn = instruction;
                            if (insn.getType() != InstructionType.LABEL)
                                for (SliceVisitor vis : this.sliceVisitorsArray)
                                    vis.visitMatchedInstance(instance);
                            instance.onDynamicSlice = true;
                            instance.criterionDistance = 0;
                        }
                    }
                } else if (this.critOccurenceNumbers[stackDepth] != 0) {
                    this.critOccurenceNumbers[stackDepth] = 0;
                }
            }
            if (this.interestingLocalVariables.length > stackDepth
                    && this.interestingLocalVariables[stackDepth] != null) {
                switch (instruction.getOpcode()) {
                case Opcodes.ISTORE:
                case Opcodes.ASTORE:
                case Opcodes.LSTORE:
                case Opcodes.FSTORE:
                case Opcodes.DSTORE:
                    VarInstruction varInsn = (VarInstruction) instruction;
                    if (this.interestingLocalVariables[stackDepth].containsKey(varInsn.getLocalVarIndex())) {
                        this.interestingLocalVariables[stackDepth].remove(varInsn.getLocalVarIndex());
                        if (this.interestingLocalVariables[stackDepth].isEmpty())
                            this.interestingLocalVariables[stackDepth] = null;
                        for (SliceVisitor vis : this.sliceVisitorsArray)
                            vis.visitMatchedInstance(instance);
                        instance.onDynamicSlice = true;
                        // and we want to know where the data comes from...
                        instance.allDataInteresting = true;
                        instance.criterionDistance = 0;
                    }
                    break;
                case Opcodes.INVOKEINTERFACE:
                case Opcodes.INVOKESPECIAL:
                case Opcodes.INVOKESTATIC:
                case Opcodes.INVOKEVIRTUAL:
                    if (this.enteredMethod != null) {
                        MethodInvocationInstruction mtdInvInsn = (MethodInvocationInstruction) instruction;
                        int paramCount = instruction.getOpcode() == INVOKESTATIC ? 0 : 1;
                        for (int param = mtdInvInsn.getParameterCount() - 1; param >= 0; --param)
                            paramCount += mtdInvInsn.parameterIsLong(param) ? 2 : 1;
                        boolean enteredMethodMatches = this.enteredMethod.getName()
                                .equals(mtdInvInsn.getInvokedMethodName())
                                && this.enteredMethod.getDesc().equals(mtdInvInsn.getInvokedMethodDesc());
                        if (enteredMethodMatches) {
                            boolean localVarsMatched = false;
                            for (int varNr = 0; varNr < paramCount; ++varNr) {
                                if (this.interestingLocalVariables[stackDepth].containsKey(varNr)) {
                                    this.interestingLocalVariables[stackDepth].remove(varNr);
                                    if (this.interestingLocalVariables[stackDepth].isEmpty())
                                        this.interestingLocalVariables[stackDepth] = null;
                                    localVarsMatched = true;
                                    instance.onDynamicSlice = true;
                                    // and we want to know where the data comes from...
                                    // TODO
                                    instance.allDataInteresting = true;
                                    instance.criterionDistance = 0;
                                }
                            }
                            if (localVarsMatched)
                                for (SliceVisitor vis : this.sliceVisitorsArray)
                                    vis.visitMatchedInstance(instance);
                        }
                    }
                }
            }
            this.enteredMethod = null;
        }

        @Override
        public void visitControlDependence(SlicerInstance from, SlicerInstance to) {
            if (from.onDynamicSlice) {
                Instruction insn = to.getInstruction();
                if (insn.getType() == InstructionType.LABEL || insn.getOpcode() == Opcodes.GOTO) {
                    if (to.predecessors == null)
                        to.predecessors = Collections.singleton(from);
                    else {
                        if (to.predecessors.size() == 1)
                            to.predecessors = new HashSet<SlicerInstance>(to.predecessors);
                        to.predecessors.add(from);
                    }
                    if (from.criterionDistance < to.criterionDistance)
                        to.criterionDistance = from.criterionDistance;
                } else if (from.predecessors != null) {
                    assert (!from.predecessors.isEmpty());
                    for (SlicerInstance pred : from.predecessors) {
                        int distance = pred.criterionDistance + 1;
                        delegateControlSliceDependence(pred, to, distance);
                        if (distance < to.criterionDistance)
                            to.criterionDistance = distance;
                    }
                } else {
                    int distance = from.criterionDistance + 1;
                    delegateControlSliceDependence(from, to, distance);
                    if (distance < to.criterionDistance)
                        to.criterionDistance = distance;
                }
                to.onDynamicSlice = true;
            }
        }

        private void delegateControlSliceDependence(SlicerInstance from, SlicerInstance to, int distance) {

            for (SliceVisitor vis : this.sliceVisitorsArray)
                vis.visitSliceDependence(from, to, null, distance);

            // since "to" controls the execution of "from", we want to track all data dependences of "to"
            // to find out why it took this decision
            // exception: method invocations; here we only want to track why the method was executed,
            // but not the data that it consumed
            // important to check that "from" comes from inside the method which is called by "from"
            boolean calledMethodDependence = false;
            if (to.getInstruction().getType() == InstructionType.METHODINVOCATION) {
                MethodInvocationInstruction mtdInv = (MethodInvocationInstruction) to.getInstruction();
                ReadMethod calledMethod = from.getInstruction().getMethod();
                if (mtdInv.getInvokedMethodName().equals(calledMethod.getName())
                        && mtdInv.getInvokedMethodDesc().equals(calledMethod.getDesc())) {
                    calledMethodDependence = true;
                }
            }
            if (!calledMethodDependence) {
                to.allDataInteresting = true;
            }
        }

        @Override
        public void visitDataDependence(SlicerInstance from, SlicerInstance to,
                Collection<? extends Variable> fromVars, Variable toVar, DataDependenceType type)
                throws InterruptedException {
            assert type == DataDependenceType.READ_AFTER_WRITE;

            if (from.onDynamicSlice && // from must definitively be on the dynamic slice
            ((from.allDataInteresting
                    && (!from.onlyIfAfterCriterion || this.critOccurenceNumbers[to.getStackDepth()] == 0)) || // and either we want to track all data dependencies
            (from.interestingVariable != null && ( // or (if the interestingVariable is set) ...
            from.interestingVariable.equals(toVar) || // the interestingVariable must be the one we are just visiting
            (from.moreInterestingVariables != null && from.moreInterestingVariables.contains(toVar)))))) { // or it must be in the set of more variables
                Instruction insn = to.getInstruction();
                assert insn.getType() != InstructionType.LABEL;
                if (from.onlyIfAfterCriterion) {
                    to.criterionDistance = 0;
                    for (SliceVisitor vis : this.sliceVisitorsArray)
                        vis.visitMatchedInstance(to);
                } else {
                    int distance = from.criterionDistance + 1;
                    if (distance < to.criterionDistance)
                        to.criterionDistance = distance;
                    for (SliceVisitor vis : this.sliceVisitorsArray)
                        vis.visitSliceDependence(from, to, toVar, distance);
                }
                if (!fromVars.isEmpty()) {
                    Iterator<? extends Variable> varIt = fromVars.iterator();
                    assert varIt
                            .hasNext() : "Iterator of a non-empty collection should have at least one element";
                    Variable first = varIt.next();
                    if (to.interestingVariable == null || to.interestingVariable.equals(first)) {
                        to.interestingVariable = first;
                        first = varIt.hasNext() ? varIt.next() : null;
                    }
                    if (first != null) {
                        if (to.moreInterestingVariables == null)
                            to.moreInterestingVariables = new HashSet<Variable>(8);
                        to.moreInterestingVariables.add(first);
                        while (varIt.hasNext())
                            to.moreInterestingVariables.add(varIt.next());
                    }
                }
                to.onDynamicSlice = true;
            }
        }

        @Override
        public void visitMethodLeave(ReadMethod method, int stackDepth) throws InterruptedException {
            if (this.interestingLocalVariables.length > stackDepth
                    && this.interestingLocalVariables[stackDepth] != null) {
                this.interestingLocalVariables[stackDepth] = null;
            }
        }

        @Override
        public void visitMethodEntry(ReadMethod method, int stackDepth) throws InterruptedException {
            if (this.interestingLocalVariables.length > stackDepth
                    && this.interestingLocalVariables[stackDepth] != null) {
                this.enteredMethod = method;
                this.interestingLocalVariables[stackDepth] = null;
            }
        }

        @Override
        public void visitUntracedMethodCall(SlicerInstance instrInstance) throws InterruptedException {
            for (UntracedCallVisitor vis : this.untracedCallsVisitorsArray)
                vis.visitUntracedMethodCall(instrInstance);
        }

    }, capabilities);

    depExtractor.processBackwardTrace(threadId, multithreaded);
}