List of usage examples for org.objectweb.asm Opcodes GOTO
int GOTO
To view the source code for org.objectweb.asm Opcodes GOTO.
Click Source Link
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); }