// Path: instrumenter/src/main/java/com/offbynull/coroutines/instrumenter/asm/VariableTable.java
// public final class Variable {
//     private Type type;
//     private int index;
//     private boolean used;
// 
//     private Variable(Type type, int index, boolean used) {
//         this.type = type;
//         this.index = index;
//         this.used = used;
//     }
// 
//     /**
//      * Get the type of this local variable table entry.
//      * @return type of this entry
//      * @throws IllegalArgumentException if this {@link Variable} has been released
//      */
//     public Type getType() {
//         Validate.isTrue(used);
//         return type;
//     }
// 
//     /**
//      * Get the index of this entry within the local variable table.
//      * @return index of this entry
//      * @throws IllegalArgumentException if this {@link Variable} has been released
//      */
//     public int getIndex() {
//         Validate.isTrue(used);
//         return index;
//     }
// 
//     /**
//      * Returns {@code true} if this object hasn't been released.
//      * @see VariableTable#releaseExtra(com.offbynull.coroutines.instrumenter.asm.VariableTable.Variable) 
//     
//      * @return index of this entry
//      * @throws IllegalArgumentException if this {@link Variable} has been released
//      */
//     public boolean isUsed() {
//         return used;
//     }
//         
//     private VariableTable getParent() {
//         return VariableTable.this;
//     }
// }
// 
// Path: user/src/main/java/com/offbynull/coroutines/user/LockState.java
// public final class LockState implements Serializable {
//     private static final long serialVersionUID = 6L;
// 
//     // We use a linkedlist to make sure that we retain the order of monitors as they come in. Otherwise we're going to deal with deadlock
//     // issues if we have code structured with double locks. For example, imagine the following scenario...
//     //
//     // Method 1:
//     // synchronized(a) {
//     //    synchronized(b) {
//     //        continuation.suspend();
//     //    }
//     // }
//     //
//     // Method 2 (same as method1):
//     // synchronized(a) {
//     //    synchronized(b) {
//     //        continuation.suspend();
//     //    }
//     // }
//     //
//     //
//     // If we weren't ordered, we may end up coming back after a suspend and re-locking the monitors in the wrong order. For example,
//     // we may lock b before we lock a. That has the potential for a deadlock because another thread could execute the locking logic
//     // correctly (first a and then b). Dual locking without retaining the same order = a deadlock waiting to happen.
//     //
//     // Long story short: it's vital that we keep the order which locks happen
//     private LinkedList monitors = new LinkedList();
// 
//     /**
//      * Do not use -- for internal use only.
//      * <p>
//      * Should be called after a MONITORENTER instruction has been executed. Tracks the object that MONITORENTER was used on.
//      * @param monitor object the MONITORENTER instruction was used on
//      */
//     public void enter(Object monitor) {
//         if (monitor == null) {
//             throw new NullPointerException();
//         }
// 
//         monitors.add(monitor);
//     }
// 
//     /**
//      * Do not use -- for internal use only.
//      * <p>
//      * Should be called after a MONITOREXIT instruction has been executed. Untracks the object that MONITOREXIT was used on.
//      * @param monitor object the MONITOREXIT instruction was used on
//      */
//     public void exit(Object monitor) {
//         if (monitor == null) {
//             throw new NullPointerException();
//         }
// 
//         // remove last
//         ListIterator it = monitors.listIterator(monitors.size());
//         while (it.hasPrevious()) {
//             Object prev = it.previous();
//             if (monitor == prev) { // Never use equals() to test equality. We always need to make sure that the objects are the same, we
//                                    // don't care if they're the objects are logically equivalent
//                 it.remove();
//                 return;
//             }
//         }
//         
//         throw new IllegalArgumentException(); // not found
//     }
//     
//     /**
//      * Dumps monitors out as an array. Order is retained.
//      * @return monitors
//      */
//     public Object[] toArray() {
//         return monitors.toArray();
//     }
// }


import com.offbynull.coroutines.instrumenter.asm.VariableTable.Variable;
import com.offbynull.coroutines.user.LockState;
import org.apache.commons.lang3.Validate;
import org.objectweb.asm.Type;
/*
 * Copyright (c) 2016, Kasra Faghihi, All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 */
package com.offbynull.coroutines.instrumenter;


final class LockVariables {
    private final Variable lockStateVar;
    private final Variable counterVar;
    private final Variable arrayLenVar;

    LockVariables(
            Variable lockStateVar,
            Variable counterVar,
            Variable arrayLenVar) {
        // vars can be null -- they'll be null if the analyzer determined tehy aren't required
// Path: instrumenter/src/main/java/com/offbynull/coroutines/instrumenter/asm/VariableTable.java
// public final class Variable {
//     private Type type;
//     private int index;
//     private boolean used;
// 
//     private Variable(Type type, int index, boolean used) {
//         this.type = type;
//         this.index = index;
//         this.used = used;
//     }
// 
//     /**
//      * Get the type of this local variable table entry.
//      * @return type of this entry
//      * @throws IllegalArgumentException if this {@link Variable} has been released
//      */
//     public Type getType() {
//         Validate.isTrue(used);
//         return type;
//     }
// 
//     /**
//      * Get the index of this entry within the local variable table.
//      * @return index of this entry
//      * @throws IllegalArgumentException if this {@link Variable} has been released
//      */
//     public int getIndex() {
//         Validate.isTrue(used);
//         return index;
//     }
// 
//     /**
//      * Returns {@code true} if this object hasn't been released.
//      * @see VariableTable#releaseExtra(com.offbynull.coroutines.instrumenter.asm.VariableTable.Variable) 
//     
//      * @return index of this entry
//      * @throws IllegalArgumentException if this {@link Variable} has been released
//      */
//     public boolean isUsed() {
//         return used;
//     }
//         
//     private VariableTable getParent() {
//         return VariableTable.this;
//     }
// }
// 
// Path: user/src/main/java/com/offbynull/coroutines/user/LockState.java
// public final class LockState implements Serializable {
//     private static final long serialVersionUID = 6L;
// 
//     // We use a linkedlist to make sure that we retain the order of monitors as they come in. Otherwise we're going to deal with deadlock
//     // issues if we have code structured with double locks. For example, imagine the following scenario...
//     //
//     // Method 1:
//     // synchronized(a) {
//     //    synchronized(b) {
//     //        continuation.suspend();
//     //    }
//     // }
//     //
//     // Method 2 (same as method1):
//     // synchronized(a) {
//     //    synchronized(b) {
//     //        continuation.suspend();
//     //    }
//     // }
//     //
//     //
//     // If we weren't ordered, we may end up coming back after a suspend and re-locking the monitors in the wrong order. For example,
//     // we may lock b before we lock a. That has the potential for a deadlock because another thread could execute the locking logic
//     // correctly (first a and then b). Dual locking without retaining the same order = a deadlock waiting to happen.
//     //
//     // Long story short: it's vital that we keep the order which locks happen
//     private LinkedList monitors = new LinkedList();
// 
//     /**
//      * Do not use -- for internal use only.
//      * <p>
//      * Should be called after a MONITORENTER instruction has been executed. Tracks the object that MONITORENTER was used on.
//      * @param monitor object the MONITORENTER instruction was used on
//      */
//     public void enter(Object monitor) {
//         if (monitor == null) {
//             throw new NullPointerException();
//         }
// 
//         monitors.add(monitor);
//     }
// 
//     /**
//      * Do not use -- for internal use only.
//      * <p>
//      * Should be called after a MONITOREXIT instruction has been executed. Untracks the object that MONITOREXIT was used on.
//      * @param monitor object the MONITOREXIT instruction was used on
//      */
//     public void exit(Object monitor) {
//         if (monitor == null) {
//             throw new NullPointerException();
//         }
// 
//         // remove last
//         ListIterator it = monitors.listIterator(monitors.size());
//         while (it.hasPrevious()) {
//             Object prev = it.previous();
//             if (monitor == prev) { // Never use equals() to test equality. We always need to make sure that the objects are the same, we
//                                    // don't care if they're the objects are logically equivalent
//                 it.remove();
//                 return;
//             }
//         }
//         
//         throw new IllegalArgumentException(); // not found
//     }
//     
//     /**
//      * Dumps monitors out as an array. Order is retained.
//      * @return monitors
//      */
//     public Object[] toArray() {
//         return monitors.toArray();
//     }
// }


// Path: instrumenter/src/main/java/com/offbynull/coroutines/instrumenter/LockVariables.java
import com.offbynull.coroutines.instrumenter.asm.VariableTable.Variable;
import com.offbynull.coroutines.user.LockState;
import org.apache.commons.lang3.Validate;
import org.objectweb.asm.Type;

/*
 * Copyright (c) 2016, Kasra Faghihi, All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 */
package com.offbynull.coroutines.instrumenter;


final class LockVariables {
    private final Variable lockStateVar;
    private final Variable counterVar;
    private final Variable arrayLenVar;

    LockVariables(
            Variable lockStateVar,
            Variable counterVar,
            Variable arrayLenVar) {
        // vars can be null -- they'll be null if the analyzer determined tehy aren't required
        Validate.isTrue(lockStateVar == null || lockStateVar.getType().equals(Type.getType(LockState.class)));