Example usage for org.objectweb.asm Opcodes ATHROW

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

Introduction

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

Prototype

int ATHROW

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

Click Source Link

Usage

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

License:Open Source License

@Override
public void visitInsn(int opcode) {
    if (opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) {
        inserirRetorno();//from   w  w w.j a  va  2  s  .  c om
    }
    if (opcode == Opcodes.ATHROW) {
        //TODO O ATHROW S PODE RETORNAR SE ESTIVER FORA DO TRY-CATCH
        //inserirRetorno();
    }
    super.visitInsn(opcode);
}

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  w  w .j  a v  a 2s .  com*/
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:pt.minha.kernel.instrument.SyncToMonitorClassVisitor.java

License:Open Source License

public void makeStub(int access, String name, String desc, String signature, String[] exceptions) {
    Method m = new Method(name, desc);

    MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    mv.visitCode();// w  ww .  j a  v  a2s  .c o  m

    Label begin = new Label();
    Label pre_invoke = new Label();
    Label pos_leave = new Label();
    Label in_catch = new Label();
    Label pre_rethrow = new Label();
    Label end = new Label();

    mv.visitTryCatchBlock(pre_invoke, pos_leave, in_catch, null);
    mv.visitTryCatchBlock(in_catch, pre_rethrow, in_catch, null);

    mv.visitLabel(begin);

    int offset;
    if ((access & Opcodes.ACC_STATIC) == 0) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        offset = 1;
    } else {
        mv.visitFieldInsn(Opcodes.GETSTATIC, clz, "_fake_class",
                "L" + ClassConfig.fake_prefix + "java/lang/Object;");
        offset = 0;
    }

    int length = 0;
    for (Type t : m.getArgumentTypes())
        length += t.getSize();

    mv.visitInsn(Opcodes.DUP);
    mv.visitVarInsn(Opcodes.ASTORE, offset + length);
    mv.visitInsn(Opcodes.MONITORENTER);

    mv.visitLabel(pre_invoke);

    if ((access & Opcodes.ACC_STATIC) == 0)
        mv.visitVarInsn(Opcodes.ALOAD, 0);

    int i = offset;
    for (Type t : m.getArgumentTypes()) {
        // t.getOpcode() should work for long and double too... :-( 
        if (t.getClassName().equals("long"))
            mv.visitVarInsn(Opcodes.LLOAD, i);
        else if (t.getClassName().equals("double"))
            mv.visitVarInsn(Opcodes.DLOAD, i);
        else
            mv.visitVarInsn(t.getOpcode(Opcodes.ILOAD), i);
        i += t.getSize();
    }

    boolean itf = (access & Opcodes.ACC_INTERFACE) != 0;
    if ((access & Opcodes.ACC_STATIC) == 0)
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, clz, "_" + name, desc, itf);
    else
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, clz, "_" + name, desc, itf);

    mv.visitVarInsn(Opcodes.ALOAD, offset + length);
    mv.visitInsn(Opcodes.MONITOREXIT);

    mv.visitLabel(pos_leave);

    if (m.getReturnType().equals(Type.VOID_TYPE))
        mv.visitInsn(Opcodes.RETURN);
    else
        mv.visitInsn(m.getReturnType().getOpcode(Opcodes.IRETURN));

    mv.visitLabel(in_catch);

    mv.visitVarInsn(Opcodes.ALOAD, offset + length);
    mv.visitInsn(Opcodes.MONITOREXIT);

    mv.visitLabel(pre_rethrow);
    mv.visitInsn(Opcodes.ATHROW);

    mv.visitLabel(end);

    i = 0;
    if ((access & Opcodes.ACC_STATIC) == 0)
        mv.visitLocalVariable("this", "L" + clz + ";", null, begin, end, i++);
    for (Type t : m.getArgumentTypes())
        mv.visitLocalVariable("arg" + i, t.getDescriptor(), null, begin, end, i++);

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

From source file:serianalyzer.JVMImpl.java

License:Open Source License

/**
 * @param opcode/*from   w  w  w.  java  2  s .c om*/
 * @param s
 */
static void handleJVMInsn(int opcode, JVMStackState s) {
    BaseType o1;
    BaseType o2;
    BaseType o3;
    List<BaseType> l1;
    List<BaseType> l2;
    switch (opcode) {
    case Opcodes.NOP:
        break;

    case Opcodes.ARRAYLENGTH:
        o1 = s.pop();
        s.push(new BasicConstant(Type.INT_TYPE, 0, !(o1 != null && !o1.isTainted())));
        break;
    case Opcodes.ACONST_NULL:
        s.push(new BasicConstant(Type.VOID_TYPE, "<null>")); //$NON-NLS-1$
        break;
    case Opcodes.ICONST_M1:
    case Opcodes.ICONST_0:
    case Opcodes.ICONST_1:
    case Opcodes.ICONST_2:
    case Opcodes.ICONST_3:
    case Opcodes.ICONST_4:
    case Opcodes.ICONST_5:
        s.push(new BasicConstant(Type.INT_TYPE, opcode - 3));
        break;
    case Opcodes.LCONST_0:
    case Opcodes.LCONST_1:
        s.push(new BasicConstant(Type.LONG_TYPE, opcode - 9L));
        break;
    case Opcodes.FCONST_0:
    case Opcodes.FCONST_1:
    case Opcodes.FCONST_2:
        s.push(new BasicConstant(Type.FLOAT_TYPE, opcode - 11f));
        break;
    case Opcodes.DCONST_0:
    case Opcodes.DCONST_1:
        s.push(new BasicConstant(Type.DOUBLE_TYPE, opcode - 14d));
        break;
    case Opcodes.IALOAD:
    case Opcodes.LALOAD:
    case Opcodes.FALOAD:
    case Opcodes.DALOAD:
    case Opcodes.BALOAD:
    case Opcodes.CALOAD:
    case Opcodes.SALOAD:
        o1 = s.pop();
        o2 = s.pop();
        s.push(new BasicVariable(toType(opcode), "primitive array elem", //$NON-NLS-1$
                (o1 == null || o1.isTainted()) | (o2 == null || o2.isTainted())));
        break;

    case Opcodes.AALOAD:
        o1 = s.pop();
        o2 = s.pop();
        if (o1 != null && o2 instanceof SimpleType && ((SimpleType) o2).getType().toString().startsWith("[")) { //$NON-NLS-1$
            Type atype = Type.getType(((SimpleType) o2).getType().toString().substring(1));
            if (o2.getAlternativeTypes() != null && !o2.getAlternativeTypes().isEmpty()) {
                s.clear();
                break;
            }
            s.push(new BasicVariable(atype, "array elem " + atype, o1.isTainted() | o2.isTainted())); //$NON-NLS-1$
        } else {
            s.clear();
        }
        break;

    case Opcodes.IASTORE:
    case Opcodes.LASTORE:
    case Opcodes.FASTORE:
    case Opcodes.DASTORE:
    case Opcodes.AASTORE:
    case Opcodes.BASTORE:
    case Opcodes.CASTORE:
    case Opcodes.SASTORE:
        s.pop(3);
        break;

    case Opcodes.POP2:
        s.pop();
    case Opcodes.MONITORENTER:
    case Opcodes.MONITOREXIT:
    case Opcodes.POP:
        s.pop();
        break;

    case Opcodes.DUP:
        if (!s.isEmpty()) {
            o1 = s.pop();
            s.push(o1);
            s.push(o1);
        }
        break;
    case Opcodes.DUP_X1:
        o1 = s.pop();
        o2 = s.pop();
        s.push(o1);
        s.push(o2);
        s.push(o1);
        break;
    case Opcodes.DUP_X2:
        o1 = s.pop();
        o2 = s.pop();
        o3 = s.pop();
        s.push(o1);
        s.push(o3);
        s.push(o2);
        s.push(o1);
        break;
    case Opcodes.DUP2:
        l1 = s.popWord();
        if (l1.isEmpty()) {
            log.trace("DUP2 with unknown operand"); //$NON-NLS-1$
            s.clear();
        } else {
            s.pushWord(l1);
            s.pushWord(l1);
        }
        break;
    case Opcodes.DUP2_X1:
        l1 = s.popWord();
        o1 = s.pop();
        if (l1.isEmpty()) {
            log.trace("DUP2 with unknown operand"); //$NON-NLS-1$
            s.clear();
        } else {
            s.pushWord(l1);
            s.push(o1);
            s.pushWord(l1);
        }
        break;
    case Opcodes.DUP2_X2:
        l1 = s.popWord();
        l2 = s.popWord();
        if (l1.isEmpty() || l2.isEmpty()) {
            log.trace("DUP2 with unknown operand"); //$NON-NLS-1$
            s.clear();
        } else {
            s.pushWord(l1);
            s.pushWord(l2);
            s.pushWord(l1);
        }
        break;

    case Opcodes.SWAP:
        o1 = s.pop();
        o2 = s.pop();
        s.push(o1);
        s.push(o2);
        break;

    case Opcodes.IADD:
    case Opcodes.LADD:
    case Opcodes.FADD:
    case Opcodes.DADD:
    case Opcodes.ISUB:
    case Opcodes.LSUB:
    case Opcodes.FSUB:
    case Opcodes.DSUB:
    case Opcodes.IMUL:
    case Opcodes.LMUL:
    case Opcodes.FMUL:
    case Opcodes.DMUL:
    case Opcodes.IDIV:
    case Opcodes.LDIV:
    case Opcodes.FDIV:
    case Opcodes.DDIV:
    case Opcodes.IREM:
    case Opcodes.LREM:
    case Opcodes.FREM:
    case Opcodes.DREM:
    case Opcodes.IAND:
    case Opcodes.LAND:
    case Opcodes.IOR:
    case Opcodes.LOR:
    case Opcodes.IXOR:
    case Opcodes.LXOR:
    case Opcodes.LCMP:
    case Opcodes.FCMPL:
    case Opcodes.FCMPG:
    case Opcodes.DCMPL:
    case Opcodes.DCMPG:
        s.merge(2);
        break;

    case Opcodes.ISHL:
    case Opcodes.LSHL:
    case Opcodes.ISHR:
    case Opcodes.LSHR:
    case Opcodes.IUSHR:
    case Opcodes.LUSHR:
        s.pop(); // amount
        // ignore value
        break;

    case Opcodes.INEG:
    case Opcodes.F2I:
    case Opcodes.D2I:
    case Opcodes.L2I:
        s.push(cast(s.pop(), Type.INT_TYPE));
        break;

    case Opcodes.LNEG:
    case Opcodes.I2L:
    case Opcodes.F2L:
    case Opcodes.D2L:
        s.push(cast(s.pop(), Type.LONG_TYPE));
        break;

    case Opcodes.FNEG:
    case Opcodes.I2F:
    case Opcodes.L2F:
    case Opcodes.D2F:
        s.push(cast(s.pop(), Type.FLOAT_TYPE));

    case Opcodes.DNEG:
    case Opcodes.I2D:
    case Opcodes.L2D:
    case Opcodes.F2D:
        s.push(cast(s.pop(), Type.DOUBLE_TYPE));

    case Opcodes.I2B:
        s.push(cast(s.pop(), Type.BYTE_TYPE));
        break;
    case Opcodes.I2C:
        s.push(cast(s.pop(), Type.CHAR_TYPE));
        break;
    case Opcodes.I2S:
        s.push(cast(s.pop(), Type.SHORT_TYPE));
        break;

    case Opcodes.ARETURN:
        s.clear();
        break;

    case Opcodes.IRETURN:
    case Opcodes.LRETURN:
    case Opcodes.FRETURN:
    case Opcodes.DRETURN:
    case Opcodes.RETURN:
        if (log.isTraceEnabled()) {
            log.trace("Found return " + s.pop()); //$NON-NLS-1$
        }
        s.clear();
        break;

    case Opcodes.ATHROW:
        Object thrw = s.pop();
        log.trace("Found throw " + thrw); //$NON-NLS-1$
        s.clear();
        break;

    default:
        log.warn("Unsupported instruction code " + opcode); //$NON-NLS-1$
    }
}

From source file:serianalyzer.SerianalyzerMethodVisitor.java

License:Open Source License

/**
 * {@inheritDoc}// w w  w . j  av  a 2s  . co m
 *
 * @see org.objectweb.asm.MethodVisitor#visitInsn(int)
 */
@Override
public void visitInsn(int opcode) {

    switch (opcode) {
    case Opcodes.ARETURN:
        Object ret = this.stack.pop();
        Type sigType = Type.getReturnType(this.ref.getSignature());
        Type retType = null;
        Set<Type> altTypes = null;
        if (ret != null) {
            if (ret instanceof SimpleType) {
                retType = ((SimpleType) ret).getType();
                altTypes = ((SimpleType) ret).getAlternativeTypes();
            } else if (ret instanceof MultiAlternatives) {
                retType = ((MultiAlternatives) ret).getCommonType();
            }
        }

        if (retType != null) {
            this.returnTypes.add(retType);
            if (altTypes != null) {
                this.returnTypes.addAll(altTypes);
            }
        } else {
            this.returnTypes.add(sigType);
        }
        this.stack.clear();
        break;

    case Opcodes.IRETURN:
    case Opcodes.LRETURN:
    case Opcodes.FRETURN:
    case Opcodes.DRETURN:
    case Opcodes.RETURN:
        if (this.log.isTraceEnabled()) {
            this.log.trace("Found return " + this.stack.pop()); //$NON-NLS-1$
        }
        this.stack.clear();
        break;

    case Opcodes.ATHROW:
        Object thrw = this.stack.pop();
        this.log.trace("Found throw " + thrw); //$NON-NLS-1$
        this.stack.clear();
        break;

    default:
        JVMImpl.handleJVMInsn(opcode, this.stack);
    }

    super.visitInsn(opcode);
}

From source file:sg.atom.core.actor.internal.codegenerator.ActorProxyCreator.java

License:Apache License

/**
 * Writes a proxy method for messages./*from  www . j  a v a 2  s  .c  o m*/
 *
 * @param classNameInternal the internal class name
 * @param classNameDescriptor the class name descriptor
 * @param cw the ClassWriter
 * @param index the message index
 * @param type the ActorState type to use
 * @param concurrencyModel the concurrency model of the message
 * @param messageDescriptor the message's descriptor
 * @param method the method to override
 * @param simpleDescriptor a simple descriptor of the message
 * @param genericSignature the signature of the message
 */
private static void writeProxyMethod(String classNameInternal, String classNameDescriptor, ClassWriter cw,
        int index, Type actorState, ConcurrencyModel concurrencyModel, MessageImplDescriptor messageDescriptor,
        Method method, String simpleDescriptor, String genericSignature) throws NoSuchMethodException {
    MethodVisitor mv;
    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), simpleDescriptor, genericSignature, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitIntInsn(Opcodes.BIPUSH, method.getParameterTypes().length);
        mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
        for (int j = 0; j < method.getParameterTypes().length; j++) {
            mv.visitInsn(Opcodes.DUP);
            mv.visitIntInsn(Opcodes.BIPUSH, j);
            Class<?> paraType = method.getParameterTypes()[j];
            if (paraType.isPrimitive()) {
                String wrapperClass = GenerationUtils.getWrapperInternalName(paraType);
                Type primType = Type.getType(paraType);
                mv.visitVarInsn(primType.getOpcode(Opcodes.ILOAD), j + 1);
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, wrapperClass, "valueOf",
                        "(" + primType.getDescriptor() + ")" + "L" + wrapperClass + ";");
            } else if (isArgumentFreezingRequired(method, j, paraType)) {
                mv.visitVarInsn(Opcodes.ALOAD, j + 1);
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(SerializableFreezer.class),
                        "freeze",
                        Type.getMethodDescriptor(SerializableFreezer.class.getMethod("freeze", Object.class)));
            } else if (paraType.isInterface()) {
                mv.visitVarInsn(Opcodes.ALOAD, j + 1);
                mv.visitInsn(Opcodes.DUP);
                mv.visitTypeInsn(Opcodes.INSTANCEOF, "org/actorsguildframework/Actor");
                Label lEndif = new Label();
                mv.visitJumpInsn(Opcodes.IFNE, lEndif);
                mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(ActorRuntimeException.class));
                mv.visitInsn(Opcodes.DUP);
                mv.visitLdcInsn(String.format(
                        "Argument %d is an non-Serializable interface, but you did not give an Actor. If a message's argument type is an interface that does not extend Serializable, only Actors are acceptable as argument.",
                        j));
                mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(ActorRuntimeException.class),
                        "<init>", "(Ljava/lang/String;)V");
                mv.visitInsn(Opcodes.ATHROW);
                mv.visitLabel(lEndif);
            } else {
                mv.visitVarInsn(Opcodes.ALOAD, j + 1);
            }

            mv.visitInsn(Opcodes.AASTORE);
        }
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitVarInsn(Opcodes.ASTORE, method.getParameterTypes().length + 1); // method.getParameterTypes().length+1 ==> 'args' local variable
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitFieldInsn(Opcodes.GETFIELD, classNameInternal, "actorState__ACTORPROXY",
                actorState.getDescriptor());
        mv.visitFieldInsn(Opcodes.GETSTATIC, classNameInternal,
                String.format(MESSAGE_CALLER_NAME_FORMAT, index),
                "Lorg/actorsguildframework/internal/MessageCaller;");
        mv.visitFieldInsn(Opcodes.GETSTATIC, "org/actorsguildframework/annotations/ThreadUsage",
                messageDescriptor.getThreadUsage().name(),
                "Lorg/actorsguildframework/annotations/ThreadUsage;");
        mv.visitVarInsn(Opcodes.ALOAD, method.getParameterTypes().length + 1);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, actorState.getInternalName(), "queueMessage",
                "(Lorg/actorsguildframework/internal/MessageCaller;Lorg/actorsguildframework/annotations/ThreadUsage;[Ljava/lang/Object;)Lorg/actorsguildframework/internal/AsyncResultImpl;");
        mv.visitInsn(Opcodes.ARETURN);
        Label l4 = new Label();
        mv.visitLabel(l4);
        mv.visitLocalVariable("this", classNameDescriptor, null, l0, l4, 0);
        for (int j = 0; j < method.getParameterTypes().length; j++) {
            mv.visitLocalVariable("arg" + j, Type.getDescriptor(method.getParameterTypes()[j]),
                    GenericTypeHelper.getSignatureIfGeneric(method.getGenericParameterTypes()[j]), l0, l4,
                    j + 1);
        }
        mv.visitLocalVariable("args", "[Ljava/lang/Object;", null, l1, l4,
                method.getParameterTypes().length + 1);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }
}

From source file:sg.atom.core.actor.internal.codegenerator.BeanCreator.java

License:Apache License

/**
 * Writes the bean constructor to the given ClassWriter.
 *
 * @param beanClass the original bean class to extend
 * @param bcd the descriptor of the bean
 * @param classNameInternal the internal name of the new class
 * @param cw the ClassWriter to write to
 * @param snippetWriter if not null, this will be invoked to add a snippet
 * after the invocation of the super constructor
 *//* ww  w  .  j  a  va2 s . c o m*/
public static void writeConstructor(Class<?> beanClass, BeanClassDescriptor bcd, String classNameInternal,
        ClassWriter cw, SnippetWriter snippetWriter) {
    String classNameDescriptor = "L" + classNameInternal + ";";

    int localPropertySize = 0;
    ArrayList<PropertyDescriptor> localVarProperties = new ArrayList<PropertyDescriptor>();
    for (int i = 0; i < bcd.getPropertyCount(); i++) {
        PropertyDescriptor pd = bcd.getProperty(i);
        if (pd.getPropertySource().isGenerating() || (pd.getDefaultValue() != null)) {
            localVarProperties.add(pd);
            localPropertySize += Type.getType(pd.getPropertyClass()).getSize();
        }
    }

    final int locVarThis = 0;
    final int locVarController = 1;
    final int locVarProps = 2;
    final int locVarPropertiesOffset = 3;
    final int locVarP = 3 + localPropertySize;
    final int locVarK = 4 + localPropertySize;
    final int locVarV = 5 + localPropertySize;

    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
            "(Lorg/actorsguildframework/internal/Controller;Lorg/actorsguildframework/Props;)V", null, null);
    mv.visitCode();
    Label lTry = new Label();
    Label lCatch = new Label();
    mv.visitTryCatchBlock(lTry, lCatch, lCatch, "java/lang/ClassCastException");

    Label lBegin = new Label();
    mv.visitLabel(lBegin);
    mv.visitVarInsn(Opcodes.ALOAD, locVarThis);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(beanClass), "<init>", "()V");

    if (snippetWriter != null) {
        snippetWriter.write(mv);
    }

    Label lPropertyInit = new Label();
    mv.visitLabel(lPropertyInit);
    // load default values into the local variables for each property that must be set
    int varCount = 0;
    for (PropertyDescriptor pd : localVarProperties) {
        Type pt = Type.getType(pd.getPropertyClass());
        if (pd.getDefaultValue() != null) {
            mv.visitFieldInsn(Opcodes.GETSTATIC, Type.getInternalName(pd.getDefaultValue().getDeclaringClass()),
                    pd.getDefaultValue().getName(), Type.getDescriptor(pd.getDefaultValue().getType()));
        } else {
            GenerationUtils.generateLoadDefault(mv, pd.getPropertyClass());
        }
        mv.visitVarInsn(pt.getOpcode(Opcodes.ISTORE), locVarPropertiesOffset + varCount);
        varCount += pt.getSize();
    }

    // loop through the props argument's list
    mv.visitVarInsn(Opcodes.ALOAD, locVarProps);
    mv.visitVarInsn(Opcodes.ASTORE, locVarP);
    Label lWhile = new Label();
    Label lEndWhile = new Label();
    Label lWhileBody = new Label();
    mv.visitLabel(lWhile);
    mv.visitJumpInsn(Opcodes.GOTO, lEndWhile);
    mv.visitLabel(lWhileBody);

    mv.visitVarInsn(Opcodes.ALOAD, locVarP);
    mv.visitInsn(Opcodes.DUP);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/actorsguildframework/Props", "getKey",
            "()Ljava/lang/String;");
    mv.visitVarInsn(Opcodes.ASTORE, locVarK);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/actorsguildframework/Props", "getValue",
            "()Ljava/lang/Object;");
    mv.visitVarInsn(Opcodes.ASTORE, locVarV);

    mv.visitLabel(lTry);
    // write an if for each property
    Label lEndIf = new Label();
    varCount = 0;
    int ifCount = 0;
    for (int i = 0; i < bcd.getPropertyCount(); i++) {
        PropertyDescriptor pd = bcd.getProperty(i);
        boolean usesLocal = pd.getPropertySource().isGenerating() || (pd.getDefaultValue() != null);
        Class<?> propClass = pd.getPropertyClass();
        Type pt = Type.getType(propClass);
        mv.visitVarInsn(Opcodes.ALOAD, locVarK);
        mv.visitLdcInsn(pd.getName());
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
        Label lElse = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, lElse);

        if (!usesLocal) {
            mv.visitVarInsn(Opcodes.ALOAD, locVarThis); // for setter invocation, load 'this'
        }
        if (propClass.isPrimitive()) {
            mv.visitLdcInsn(pd.getName());
            mv.visitVarInsn(Opcodes.ALOAD, locVarV);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(BeanHelper.class),
                    String.format("get%s%sFromPropValue",
                            propClass.getName().substring(0, 1).toUpperCase(Locale.US),
                            propClass.getName().substring(1)),
                    "(Ljava/lang/String;Ljava/lang/Object;)" + pt.getDescriptor());
        } else if (!propClass.equals(Object.class)) {
            mv.visitVarInsn(Opcodes.ALOAD, locVarV);
            mv.visitTypeInsn(Opcodes.CHECKCAST, pt.getInternalName());
        } else {
            mv.visitVarInsn(Opcodes.ALOAD, locVarV);
        }

        if (!usesLocal) {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameInternal, pd.getSetter().getName(),
                    Type.getMethodDescriptor(pd.getSetter()));
        } else {
            mv.visitVarInsn(pt.getOpcode(Opcodes.ISTORE), varCount + locVarPropertiesOffset);
        }

        mv.visitJumpInsn(Opcodes.GOTO, lEndIf);
        mv.visitLabel(lElse);

        ifCount++;
        if (usesLocal) {
            varCount += pt.getSize();
        }
    }

    // else (==> if not prop matched) throw IllegalArgumentException
    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(IllegalArgumentException.class));
    mv.visitInsn(Opcodes.DUP);
    mv.visitLdcInsn("Unknown property \"%s\".");
    mv.visitInsn(Opcodes.ICONST_1);
    mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
    mv.visitInsn(Opcodes.DUP);
    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitVarInsn(Opcodes.ALOAD, locVarK);
    mv.visitInsn(Opcodes.AASTORE);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "format",
            "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;");
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(IllegalArgumentException.class), "<init>",
            "(Ljava/lang/String;)V");
    mv.visitInsn(Opcodes.ATHROW);

    mv.visitLabel(lCatch);
    mv.visitInsn(Opcodes.POP); // pop the exception object (not needed)
    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(IllegalArgumentException.class));
    mv.visitInsn(Opcodes.DUP);
    mv.visitLdcInsn("Incompatible type for property \"%s\". Got %s.");
    mv.visitInsn(Opcodes.ICONST_2);
    mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
    mv.visitInsn(Opcodes.DUP);
    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitVarInsn(Opcodes.ALOAD, locVarK);
    mv.visitInsn(Opcodes.AASTORE);
    mv.visitInsn(Opcodes.DUP);
    mv.visitInsn(Opcodes.ICONST_1);
    mv.visitVarInsn(Opcodes.ALOAD, locVarV);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;");
    mv.visitInsn(Opcodes.AASTORE);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "format",
            "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;");
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(IllegalArgumentException.class), "<init>",
            "(Ljava/lang/String;)V");
    mv.visitInsn(Opcodes.ATHROW);

    mv.visitLabel(lEndIf);
    mv.visitVarInsn(Opcodes.ALOAD, locVarP);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/actorsguildframework/Props", "tail",
            "()Lorg/actorsguildframework/Props;");
    mv.visitVarInsn(Opcodes.ASTORE, locVarP);

    mv.visitLabel(lEndWhile);
    mv.visitVarInsn(Opcodes.ALOAD, locVarP);
    mv.visitJumpInsn(Opcodes.IFNONNULL, lWhileBody);

    // write local variables back into properties 
    varCount = 0;
    for (PropertyDescriptor pd : localVarProperties) {
        Type pt = Type.getType(pd.getPropertyClass());
        mv.visitVarInsn(Opcodes.ALOAD, locVarThis);
        if (pd.getPropertySource() == PropertySource.ABSTRACT_METHOD) {
            mv.visitVarInsn(pt.getOpcode(Opcodes.ILOAD), locVarPropertiesOffset + varCount);
            mv.visitFieldInsn(Opcodes.PUTFIELD, classNameInternal,
                    String.format(PROP_FIELD_NAME_TEMPLATE, pd.getName()), pt.getDescriptor());
        } else if (pd.getPropertySource() == PropertySource.USER_WRITTEN) {
            mv.visitVarInsn(pt.getOpcode(Opcodes.ILOAD), locVarPropertiesOffset + varCount);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameInternal, pd.getSetter().getName(),
                    Type.getMethodDescriptor(pd.getSetter()));
        } else {
            throw new RuntimeException("Internal error");
        }
        varCount += pt.getSize();
    }

    // if bean is thread-safe, publish all writes now
    if (bcd.isThreadSafe()) {
        mv.visitVarInsn(Opcodes.ALOAD, locVarThis);
        mv.visitInsn(Opcodes.DUP);
        mv.visitInsn(Opcodes.MONITORENTER);
        mv.visitInsn(Opcodes.MONITOREXIT);
    }

    mv.visitInsn(Opcodes.RETURN);
    Label lEnd = new Label();
    mv.visitLabel(lEnd);

    mv.visitLocalVariable("this", classNameDescriptor, null, lBegin, lEnd, locVarThis);
    mv.visitLocalVariable("controller", "Lorg/actorsguildframework/internal/Controller;", null, lBegin, lEnd,
            locVarController);
    mv.visitLocalVariable("props", "Lorg/actorsguildframework/Props;", null, lBegin, lEnd, locVarProps);
    varCount = 0;
    for (PropertyDescriptor pd : localVarProperties) {
        Type pt = Type.getType(pd.getPropertyClass());
        mv.visitLocalVariable("__" + pd.getName(), pt.getDescriptor(),
                GenericTypeHelper.getSignature(pd.getPropertyType()), lPropertyInit, lEnd,
                locVarPropertiesOffset + varCount);
        varCount += pt.getSize();
    }
    mv.visitLocalVariable("p", "Lorg/actorsguildframework/Props;", null, lPropertyInit, lEnd, locVarP);
    mv.visitLocalVariable("k", "Ljava/lang/String;", null, lWhile, lEndWhile, locVarK);
    mv.visitLocalVariable("v", "Ljava/lang/Object;", null, lWhile, lEndWhile, locVarV);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}