SquirrelJME/SquirrelJME

View on GitHub
emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringThreadWorker.java

Summary

Maintainability
F
2 wks
Test Coverage
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the Mozilla Public License Version 2.0.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.emulator.profiler.ProfiledFrame;
import cc.squirreljme.emulator.vm.VMTraceFlagTracker;
import cc.squirreljme.jdwp.JDWPEventKind;
import cc.squirreljme.jdwp.JDWPClassStatus;
import cc.squirreljme.jdwp.host.JDWPHostController;
import cc.squirreljme.jdwp.host.JDWPHostStepTracker;
import cc.squirreljme.jdwp.host.JDWPHostThreadSuspension;
import cc.squirreljme.jdwp.host.JDWPHostValue;
import cc.squirreljme.jdwp.host.trips.JDWPGlobalTrip;
import cc.squirreljme.jdwp.host.trips.JDWPTripBreakpoint;
import cc.squirreljme.jdwp.host.trips.JDWPTripClassStatus;
import cc.squirreljme.jdwp.host.trips.JDWPTripField;
import cc.squirreljme.jdwp.host.trips.JDWPTripThread;
import cc.squirreljme.jvm.mle.constants.VerboseDebugFlag;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.runtime.cldc.util.StreamUtils;
import cc.squirreljme.vm.springcoat.brackets.TypeObject;
import cc.squirreljme.vm.springcoat.exceptions.SpringArithmeticException;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassCastException;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassFormatException;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassNotFoundException;
import cc.squirreljme.vm.springcoat.exceptions.SpringFatalException;
import cc.squirreljme.vm.springcoat.exceptions.SpringIllegalAccessException;
import cc.squirreljme.vm.springcoat.exceptions.SpringIncompatibleClassChangeException;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;
import cc.squirreljme.vm.springcoat.exceptions.SpringMachineExitException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNoSuchFieldException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNoSuchMethodException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNullPointerException;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Map;
import net.multiphasicapps.classfile.ByteCode;
import net.multiphasicapps.classfile.ClassFlags;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.ConstantValue;
import net.multiphasicapps.classfile.ConstantValueClass;
import net.multiphasicapps.classfile.ConstantValueString;
import net.multiphasicapps.classfile.ExceptionHandler;
import net.multiphasicapps.classfile.FieldReference;
import net.multiphasicapps.classfile.Instruction;
import net.multiphasicapps.classfile.InstructionIndex;
import net.multiphasicapps.classfile.InstructionJumpTarget;
import net.multiphasicapps.classfile.IntMatchingJumpTable;
import net.multiphasicapps.classfile.MemberFlags;
import net.multiphasicapps.classfile.MethodDescriptor;
import net.multiphasicapps.classfile.MethodName;
import net.multiphasicapps.classfile.MethodNameAndType;
import net.multiphasicapps.classfile.MethodReference;
import net.multiphasicapps.classfile.PrimitiveType;

/**
 * A worker which runs the actual thread code in single-step fashion.
 *
 * @since 2018/09/03
 */
public final class SpringThreadWorker
    extends Thread
{
    /** Number of instructions which can be executed before warning. */
    private static final int _EXECUTION_THRESHOLD =
        4000000;
    
    /** The owning machine. */
    protected final SpringMachine machine;
    
    /** The thread being run. */
    protected final SpringThread thread;
    
    /** The thread to signal instead for interrupt. */
    protected final Thread signalinstead;
    
    /** The manager for this thread's verbosity output. */
    private final VMTraceFlagTracker _verbose =
        new VMTraceFlagTracker();
    
    /** The current step count. */
    private volatile int _stepCount;
    
    /**
     * Initialize the worker.
     *
     * @param __m The executing machine.
     * @param __t The running thread.
     * @param __main Is this the main thread? Used for interrupt hacking.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/03
     */
    public SpringThreadWorker(SpringMachine __m, SpringThread __t,
        boolean __main)
        throws NullPointerException
    {
        if (__m == null || __t == null)
            throw new NullPointerException("NARG");
        
        this.machine = __m;
        this.thread = __t;
        this.signalinstead = (__main ? Thread.currentThread() : null);
        
        // Set the thread's worker to this
        if (__t._worker == null)
        {
            __t._worker = this;
            
            // Priority may be set before the thread is started
            int setPriority = __t._initPriority;
            if (setPriority >= 0)
                this.setPriority(setPriority);
        }
        
        /* {@squirreljme.error BK1x Thread already has a worker associated
        with it.} */
        else
            throw new SpringVirtualMachineException("BK1x");
    }
    
    /**
     * Allocates the memory needed to store an array of the given class and
     * of the given length.
     *
     * @param __cl The array type.
     * @param __l The length of the array.
     * @return The allocated array.
     * @throws IllegalArgumentException If the type is not an array.
     * @throws NullPointerException On null arguments.
     * @throws SpringNegativeArraySizeException If the array size is negative.
     * @since 2018/09/15
     */
    public final SpringArrayObject allocateArray(SpringClass __cl, int __l)
        throws IllegalArgumentException, NullPointerException,
            SpringNegativeArraySizeException
    {
        if (__cl == null)
            throw new NullPointerException("NARG");
        
        // This must be an array type
        if (!__cl.isArray())
            throw new IllegalArgumentException("Not an array: " + __cl);
        
        // Verbose debug?
        if (this.verboseCheck(VerboseDebugFlag.ALLOCATION))
            this.verboseEmit("Allocate array: %s[%d]",
                __cl.name, __l);
        
        // Depends on the type to be allocated
        switch (__cl.componentType().name().toString())
        {
                // Boolean
            case "boolean":
                return new SpringArrayObjectBoolean(__cl, __l);
            
                // Byte
            case "byte":
                return new SpringArrayObjectByte(__cl, __l);
                
                // Short
            case "short":
                return new SpringArrayObjectShort(__cl, __l);
                
                // Char
            case "char":
                return new SpringArrayObjectChar(__cl, __l);
                
                // Int
            case "int":
                return new SpringArrayObjectInteger(__cl, __l);
                
                // Long
            case "long":
                return new SpringArrayObjectLong(__cl, __l);
                
                // Float
            case "float":
                return new SpringArrayObjectFloat(__cl, __l);
                
                // Float
            case "double":
                return new SpringArrayObjectDouble(__cl, __l);
            
                // Generic array
            default:
                return new SpringArrayObjectGeneric(__cl, __l);
        }
        
    }
    
    /**
     * Allocates the memory needed to store an object of the given class.
     *
     * @param __cl The object to allocate.
     * @return The allocated instance of the object.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/08
     */
    public final SpringObject allocateObject(SpringClass __cl)
        throws NullPointerException
    {
        if (__cl == null)
            throw new NullPointerException("NARG");
        
        // Verbose debug?
        if (this.verboseCheck(VerboseDebugFlag.ALLOCATION))
            this.verboseEmit("Allocate object: %s", __cl);
        
        // The called constructor will allocate the space needed to store
        // this object
        return new SpringSimpleObject(__cl);
    }
    
    /**
     * Converts the specified virtual machine object to a native object.
     *
     * @param __in The input object.
     * @return The resulting native object.
     * @throws NullPointerException On null arguments.
     * @throws SpringFatalException If the object cannot be translated.
     * @since 2018/09/20
     */
    public final Object asNativeObject(Object __in)
        throws NullPointerException, SpringFatalException
    {
        if (__in == null)
            throw new NullPointerException("NARG");
        
        // Is null reference
        else if (__in == SpringNullObject.NULL)
            return null;
        
        // Boxed types remain the same
        else if (__in instanceof Integer || __in instanceof Long ||
            __in instanceof Float || __in instanceof Double)
            return __in;
        
        // Array type
        if (__in instanceof SpringArrayObject)
            return ((SpringArrayObject)__in).array();
        
        // Class type
        else if (__in instanceof SpringSimpleObject)
        {
            SpringSimpleObject sso = (SpringSimpleObject)__in;
            
            // Depends on the class type
            SpringClass sscl = sso.type();
            ClassName type = sscl.name();
            switch (type.toString())
            {
                case "java/lang/Integer":
                    return Integer.valueOf((Integer)
                        sso.fieldByField(sscl.lookupField(false,
                        "_value", "I")).get());
                
                case "java/lang/String":
                    return new String(this.<char[]>asNativeObject(
                        char[].class, this.invokeMethod(false,
                            new ClassName("java/lang/String"),
                            new MethodNameAndType("toCharArray", "()[C"),
                            sso)));
                
                    /* {@squirreljme.error BK1z Do not know how to convert the
                    given virtual machine class to a native machine object.
                    (The input class)} */
                default:
                    throw new RuntimeException(
                        String.format("BK1z %s", type));
            }
        }
        
        /* {@squirreljme.error BK20 Do not know how to convert the given class
        to a native machine object. (The input class)} */
        else
            throw new SpringFatalException(
                String.format("BK20 %s", __in.getClass()));
    }
    
    /**
     * Converts the specified virtual machine object to a native object.
     *
     * @param <C> The class type.
     * @param __cl The class type.
     * @param __in The input object.
     * @return The resulting native object.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/20
     */
    public final <C> C asNativeObject(Class<C> __cl, Object __in)
        throws NullPointerException
    {
        if (__cl == null)
            throw new NullPointerException("NARG");
        
        return __cl.cast(this.asNativeObject(__in));
    }
    
    /**
     * Converts the specified native object to a virtual machine object.
     *
     * @param __in The input object.
     * @return The resulting VM object.
     * @since 2018/09/16
     */
    public final Object asVMObject(Object __in)
    {
        return this.asVMObject(__in, false);
    }
    
    /**
     * Converts the specified native object to a virtual machine object.
     *
     * @param __in The input object.
     * @param __noclassres Do not use class resolution? Just load the class?
     * @return The resulting VM object.
     * @since 2018/09/16
     */
    public final Object asVMObject(Object __in, boolean __noclassres)
    {
        // Null is converted to null
        if (__in == null)
            return SpringNullObject.NULL;
        
        // As-is
        else if (__in instanceof Integer || __in instanceof Long ||
            __in instanceof Float || __in instanceof Double ||
            __in instanceof SpringObject)
            return __in;
        
        // Boolean to integer
        else if (__in instanceof Boolean)
            return (Boolean.TRUE.equals(__in) ? 1 : 0);
        
        // Character to Integer
        else if (__in instanceof Character)
            return (int)(Character)__in;
        
        // Promoted to integer
        else if (__in instanceof Byte || __in instanceof Short)
            return ((Number)__in).intValue();
        
        // An array type (not copied)
        else if (__in instanceof boolean[] ||
            __in instanceof byte[] ||
            __in instanceof short[] ||
            __in instanceof char[] ||
            __in instanceof int[] ||
            __in instanceof long[] ||
            __in instanceof float[] ||
            __in instanceof double[])
            return this.asWrappedArray(__in);
        
        // Object array type
        else if (__in instanceof SpringObject[])
            return new SpringArrayObjectGeneric(
                this.loadClass(new ClassName("java/lang/Object")),
                (SpringObject[])__in);
        
        // String array
        else if (__in instanceof String[])
        {
            String[] in = (String[])__in;
            
            // Setup return array
            int n = in.length;
            SpringArrayObject rv = this.allocateArray(
                this.loadClass(new ClassName("[Ljava/lang/String;")), n);
            
            // Copy array values
            for (int i = 0; i < n; i++)
                rv.set(i, this.asVMObject(in[i]));
            
            return rv;
        }
        
        // Convertible exception
        else if (__in instanceof SpringConvertableThrowable)
        {
            SpringConvertableThrowable e = (SpringConvertableThrowable)__in;
            
            // Initialize new instance with this type, use the input message
            // MLECallError has a distinction for certain sub-errors
            if (e instanceof SpringMLECallError)
                return this.newInstance(new ClassName(e.targetClass()),
                    new MethodDescriptor("(Ljava/lang/String;I)V"),
                    this.asVMObject(e.getMessage()),
                    ((SpringMLECallError)e).distinction);
            return this.newInstance(new ClassName(e.targetClass()),
                new MethodDescriptor("(Ljava/lang/String;)V"),
                this.asVMObject(e.getMessage()));
        }
        
        // String object
        else if (__in instanceof String)
        {
            String s = (String)__in;
            
            // Locate the string class
            SpringClass strclass = this.loadClass(
                new ClassName("java/lang/String"));
                
            // Setup an array of characters to represent the string data,
            // this is the simplest thing to do right now
            SpringObject array = (SpringObject)this.asVMObject(
                s.toString().toCharArray());
            
            // Setup string which uses this sequence
            SpringObject rv = this.newInstance(
                new ClassName("java/lang/String"),
                new MethodDescriptor("([CS)V"),
                array, 0);
            
            return rv;
        }
        
        // Constant string from the constant pool, which shared a global pool
        // of string objects! This must be made so that "aaa" == "aaa" is true
        // even across different classes!
        else if (__in instanceof ConstantValueString)
        {
            ConstantValueString cvs = (ConstantValueString)__in;
            
            // Get the string map but lock on the class loader because a class
            // might want a string but then another thread might be
            // initializing some class, and it will just deadlock as they wait
            // on each other
            SpringMachine machine = this.machine;
            Map<ConstantValueString, SpringObject> stringmap =
                machine.__stringMap();
            synchronized (machine.classLoader().classLoadingLock())
            {
                // Pre-cached object already exists?
                SpringObject rv = stringmap.get(cvs);
                if (rv != null)
                    return rv;
                
                // Setup an array of characters to represent the string data,
                // this is the simplest thing to do right now
                SpringObject array = (SpringObject)this.asVMObject(
                    cvs.toString().toCharArray());
                
                // Setup string which uses this sequence, but it also needs
                // to be interned!
                ClassName strclass = new ClassName("java/lang/String");
                rv = (SpringObject)this.invokeMethod(false, strclass,
                    new MethodNameAndType("intern", "()Ljava/lang/String;"),
                    this.newInstance(strclass, new MethodDescriptor("([CS)V"),
                        array, 0));
                
                // Cache
                stringmap.put(cvs, rv);
                
                // Use it
                return rv;
            }
        }
        
        // A class object, as needed
        else if (__in instanceof ClassName ||
            __in instanceof ConstantValueClass ||
            __in instanceof SpringClass)
        {
            ClassName name = ((__in instanceof SpringClass) ?
                ((SpringClass)__in).name() : ((__in instanceof ClassName) ?
                (ClassName)__in : ((ConstantValueClass)__in).className()));
            
            // Get the class object map but lock on the class loader since we
            // might end up just initializing classes and such
            SpringMachine machine = this.machine;
            Map<ClassName, SpringObject> com = machine.__classObjectMap();
            Map<SpringObject, ClassName> ocm = machine.
                __classObjectToNameMap();
            synchronized (machine.classLoader().classLoadingLock())
            {
                // Pre-cached object already exists?
                SpringObject rv = com.get(name);
                if (rv != null)
                    return rv;
                
                // Resolve the input class, so it is initialized
                SpringClass resClass = (__noclassres ? this.loadClass(name) :
                    this.resolveClass(name));
                
                // Resolve the class object
                SpringClass classClass = this.resolveClass(
                    new ClassName("java/lang/Class"));
                
                // Initialize class with special class index and some class
                // information
                rv = this.newInstance(classClass.name(), new MethodDescriptor(
                    "(Lcc/squirreljme/jvm/mle/brackets/TypeBracket;)V"),
                    new TypeObject(machine, resClass));
                
                // Store it
                synchronized (classClass)
                {
                    classClass._instance = rv;
                }
                
                // Cache and use it
                com.put(name, rv);
                ocm.put(rv, name);
                return rv;
            }
        }
        
        /* {@squirreljme.error BK21 Do not know how to convert the given class
        to a virtual machine object. (The input class)} */
        else
            throw new RuntimeException(
                String.format("BK21 %s", __in.getClass()));
    }
    
    /**
     * Creates an array from the given elements.
     *
     * @param __type The array type.
     * @param __elements The elements to be in the array.
     * @return The array.
     * @throws IllegalArgumentException If the type is not an array that is
     * compatible with objects.
     * @throws NullPointerException On null arguments.
     * @since 2020/06/12
     */
    public final SpringArrayObjectGeneric asVMObjectArray(SpringClass __type,
        SpringObject... __elements)
        throws IllegalArgumentException, NullPointerException
    {
        if (__type == null)
            throw new NullPointerException("NARG");
        
        // Prevent invalid arrays from being wrapped
        if (!__type.isArray() || __type.componentType().name().isPrimitive())
            throw new IllegalArgumentException("Cannot have object array " +
                "that is not an array or primitive type: " + __type);
        
        return new SpringArrayObjectGeneric(__type, __elements);
    }
    
    /**
     * Wraps the native array so that it is directly read and written in
     * the VM code.
     *
     * @param __a The object to convert.
     * @return The object representing the array.
     * @throws RuntimeException If the type is not an array.
     * @since 2018/11/18
     */
    public final SpringObject asWrappedArray(Object __a)
        throws RuntimeException
    {
        if (__a == null)
            return SpringNullObject.NULL;
        
        // Boolean
        else if (__a instanceof boolean[])
            return new SpringArrayObjectBoolean(
                this.loadClass(new ClassName("[Z")),
                (boolean[])__a);
        
        // Byte
        else if (__a instanceof byte[])
            return new SpringArrayObjectByte(
                this.loadClass(new ClassName("[B")),
                (byte[])__a);
        
        // Short
        else if (__a instanceof short[])
            return new SpringArrayObjectShort(
                this.loadClass(new ClassName("[S")),
                (short[])__a);
        
        // Character
        else if (__a instanceof char[])
            return new SpringArrayObjectChar(
                this.loadClass(new ClassName("[C")),
                (char[])__a);
        
        // Integer
        else if (__a instanceof int[])
            return new SpringArrayObjectInteger(
                this.loadClass(new ClassName("[I")),
                (int[])__a);
        
        // Long
        else if (__a instanceof long[])
            return new SpringArrayObjectLong(
                this.loadClass(new ClassName("[J")),
                (long[])__a);
        
        // Float
        else if (__a instanceof float[])
            return new SpringArrayObjectFloat(
                this.loadClass(new ClassName("[F")),
                (float[])__a);
        
        // Double
        else if (__a instanceof double[])
            return new SpringArrayObjectDouble(
                this.loadClass(new ClassName("[D")),
                (double[])__a);
        
        /* {@squirreljme.error BK22 Cannot wrap this as a native array.
        (The input class type)} */
        else
            throw new RuntimeException("BK22 " + __a.getClass());
    }
    
    /**
     * Checks if the given class may be accessed.
     *
     * @param __cl The class to access.
     * @return {@code true} if it may be accessed.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/09
     */
    public final boolean checkAccess(SpringClass __cl)
        throws NullPointerException
    {
        if (__cl == null)
            throw new NullPointerException("NARG");
        
        // If the target class is public then we can access it
        ClassFlags targetflags = __cl.flags();
        if (targetflags.isPublic())
            return true;
        
        // Get our current class
        SpringClass self = this.contextClass();
        
        // No current class, treat as always valid
        if (self == null)
            return true;
        
        // Allow object and class unlimited access to anything
        ClassName cn = self.name();
        if (cn.toString().equals("java/lang/Object") ||
            cn.toString().equals("java/lang/Class"))
            return true;
        
        // This is ourself so access is always granted
        else if (__cl == self)
            return true;
        
        // Protected class, we must be a super class
        else if (targetflags.isProtected())
        {
            for (SpringClass r = self; r != null; r = r.superClass())
                if (__cl == r)
                    return true;
        }
        
        // Must be in the same package
        else if (targetflags.isPackagePrivate())
        {
            if (self.name().inPackage().equals(__cl.name().inPackage()))
                return true;
        }
        
        // This should not occur
        else
            throw Debugging.oops();
        
        // No access permitted
        return false;
    }
    
    /**
     * Checks if the given member can be accessed.
     *
     * @param __m The member to check.
     * @return If the member can be accessed.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/09
     */
    public final boolean checkAccess(SpringMember __m)
        throws NullPointerException
    {
        if (__m == null)
            throw new NullPointerException("NARG");
        
        // Need the current and the target class to check permissions
        SpringClass self = this.contextClass(),
            target = this.loadClass(__m.inClass());
        
        // No current class, treat as always valid
        if (self == null)
            return true;
        
        // If in the same class all access is permitted
        if (self == target)
            return true;
        
        // Public has full access
        MemberFlags flags = __m.flags();
        if (flags.isPublic())
            return true;
        
        // Protected class, we must be a super class
        else if (flags.isProtected())
        {
            for (SpringClass r = self; r != null; r = r.superClass())
                if (target == r)
                    return true;
            
            // Otherwise it has to be in the same package
            if (self.name().inPackage().equals(target.name().inPackage()))
                return true;
        }
        
        // Classes must be in the same package
        else if (flags.isPackagePrivate())
        {
            if (self.name().inPackage().equals(target.name().inPackage()))
                return true;
        }
        
        // Access not permitted
        return false;
    }
    
    /**
     * Returns the current class context, if any.
     *
     * @return The current class context or {@code null} if there is none.
     * @since 2018/09/09
     */
    public final SpringClass contextClass()
    {
        SpringThread thread = this.thread;
        SpringThreadFrame[] frames = thread.frames();
        
        // Go through frames
        for (int n = frames.length, i = n - 1; i >= 0; i--)
        {
            SpringThreadFrame frame = frames[i];
            
            // No method, could be a blank frame
            SpringMethod m = frame.method();
            if (m == null)
                continue;
            
            // If this is the assembly classes, treat it as if the caller were
            // doing things rather than the asm classes itself
            ClassName icl = frame.method().inClass();
            if (icl.toString().startsWith("cc/squirreljme/runtime/cldc/asm/"))
                continue;
            
            return this.machine.classLoader().loadClass(icl);
        }
        
        return null;
    }
    
    /**
     * Invokes the given method.
     *
     * @param __static Is the method static?
     * @param __cl The class name.
     * @param __nat The name and type.
     * @param __args The arguments.
     * @return The return value, if any.
     * @throws MethodInvokeException If the invoked method threw an exception.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/20
     */
    public final Object invokeMethod(boolean __static, ClassName __cl,
        MethodNameAndType __nat, Object... __args)
        throws MethodInvokeException, NullPointerException
    {
        if (__cl == null || __nat == null || __args == null)
            throw new NullPointerException("NARG");
        
        // Lookup class and method for the static method
        SpringClass cl;
        SpringMethod method;
        if (__static)
        {
            cl = this.resolveClass(__cl);
            method = cl.lookupMethod(__static, __nat);
        }
        
        // Call it based on the object instead
        else
        {
            cl = ((SpringObject)__args[0]).type();
            method = cl.lookupMethod(false, __nat);
        } 
        
        // Overflow or exceptions might occur
        int framelimit;
        SpringThreadFrame blank, execframe;
        SpringThread thread = this.thread;
        try
        {
            // Add blank frame for protection, this is used to hold the return
            // value on the stack
            blank = thread.enterBlankFrame();
            
            // Executing a proxy method?
            if (!__static && __args[0] instanceof SpringProxyObject)
                this.__invokeProxy(method.nameAndType(), __args);
            
            // Normal call
            else
            {
                // Enter the method we really want to execute
                framelimit = thread.numFrames();
                this.__vmEnterFrame(method, __args);
                
                // Execute this method
                this.run(framelimit);
            }
        }
        
        // Exception when running which was not caught
        catch (SpringVirtualMachineException e)
        {
            // Print the thread trace
            thread.printStackTrace(System.err);
            
            // Propagate up
            throw e;
        }
        
        // This is an error unless the thread signaled exit
        SpringThreadFrame currentframe = thread.currentFrame();
        if (currentframe != blank)
        {
            // If our thread just happened to signal an exit of the VM, then
            // the current frame will be invalid anyway, so since the
            // exception or otherwise might be signaled we must make an
            // exception for exit here so it continues going down.
            if (thread._signaledexit)
                throw new SpringMachineExitException(
                    this.machine.getExitCode());
            
            /* {@squirreljme.error BK23 Current frame is not our blank frame.} */
            throw new SpringVirtualMachineException("BK23");
        }
        
        // Wrap the exception if there is one
        Object rv = blank.tossedException();
        if (rv != null)
            rv = new MethodInvokeException(String.format(
                "Exception in %s %s:%s(%s)",
                (__static ? "static" : "instance"), __cl, __nat,
                Arrays.asList(__args)), (SpringObject)rv,
                thread.getStackTrace());
        
        // Read return value from the blank frame
        else if (__nat.type().hasReturnValue())
            rv = blank.popFromStack();
        
        // Pop the blank frame, we do not need it anymore
        thread.popFrame();
        
        // Return the popped value
        return rv;
    }
    
    /**
     * Loads the specified class, potentially performing initialization on it
     * if it has not been initialized.
     *
     * @param __cn The class to load.
     * @return The loaded class.
     * @throws NullPointerException On null arguments.
     * @throws SpringClassFormatException If the class is not formatted
     * properly.
     * @throws SpringClassNotFoundException If the class was not found.
     * @since 2020/06/17
     */
    public final SpringClass loadClass(String __cn)
        throws NullPointerException, SpringClassFormatException,
            SpringClassNotFoundException
    {
        return this.loadClass(new ClassName(__cn));
    }
    
    /**
     * Loads the specified class, potentially performing initialization on it
     * if it has not been initialized.
     *
     * @param __cn The class to load.
     * @return The loaded class.
     * @throws NullPointerException On null arguments.
     * @throws SpringClassFormatException If the class is not formatted
     * properly.
     * @throws SpringClassNotFoundException If the class was not found.
     * @since 2018/09/08
     */
    public final SpringClass loadClass(ClassName __cn)
        throws NullPointerException, SpringClassFormatException,
            SpringClassNotFoundException
    {
        if (__cn == null)
            throw new NullPointerException("NARG");
        
        // Use the class loading lock to prevent other threads from loading or
        // initializing classes while this thread does such things
        SpringClassLoader classloader = this.machine.classLoader();
        synchronized (classloader.classLoadingLock())
        {
            // Load the class from the class loader
            return this.loadClass(classloader.loadClass(__cn));
        }
    }
    
    /**
     * Loads the specified class.
     *
     * @param __cl The class to load.
     * @return {@code __cl}.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/08
     */
    public final SpringClass loadClass(SpringClass __cl)
        throws NullPointerException
    {
        if (__cl == null)
            throw new NullPointerException("NARG");
            
        // If the class has already been initialized then the class is
        // ready to be used
        if (__cl.isInitialized())
            return __cl;
        
        // Use the class loading lock to prevent other threads from loading or
        // initializing classes while this thread does such things
        SpringMachine machine = this.machine;
        SpringClassLoader classloader = machine.classLoader();
        synchronized (classloader.classLoadingLock())
        {
            // Check initialization again just in case
            if (__cl.isInitialized())
                return __cl;
            
            // Verbosity?
            if (this.verboseCheck(VerboseDebugFlag.CLASS_INITIALIZE))
                this.verboseEmit("Need to initialize %s.", 
                    __cl.name());
            
            // Set the class as initialized early to prevent loops, because
            // a super class might call something from the base class which
            // might be seen as initialized when it should not be. So this is
            // to prevent bad things from happening.
            __cl.setInitialized();
        }
            
        // Tell the debugger that this class is verified
        JDWPHostController jdwp = this.machine.taskManager().jdwpController;
        JDWPTripClassStatus classTrip = (jdwp == null ? null :
            jdwp.trip(JDWPTripClassStatus.class,
                JDWPGlobalTrip.CLASS_STATUS));
        if (classTrip != null)
            classTrip.classStatus(this.thread, __cl,
                JDWPClassStatus.VERIFIED);
        
        // Recursively call self to load the super class before this class
        // is handled
        SpringClass clsuper = __cl.superClass();
        if (clsuper != null)
            this.loadClass(clsuper);
        
        // Go through interfaces and do the same
        for (SpringClass iface : __cl.interfaceClasses())
            this.loadClass(iface);
        
        // Look for static constructor for this class to initialize it as
        // needed
        SpringMethod init;
        try
        {
            // Verbosity?
            if (this.verboseCheck(VerboseDebugFlag.CLASS_INITIALIZE))
                this.verboseEmit("Lookup static init for %s.", 
                    __cl.name());
            
            init = __cl.lookupMethod(true,
                new MethodNameAndType("<clinit>", "()V"));
        }
        
        // No static initializer exists
        catch (SpringNoSuchMethodException e)
        {
            init = null;
            
            // Verbosity?
            if (this.verboseCheck(VerboseDebugFlag.CLASS_INITIALIZE))
                this.verboseEmit("No static init for %s.", 
                    __cl.name());
        }
        
        // Tell the debugger that this class is prepared
        if (classTrip != null)
            classTrip.classStatus(this.thread, __cl,
                JDWPClassStatus.PREPARED);
        
        // Static initializer exists, setup a frame and call it
        if (init != null)
        {
            // Verbosity?
            if (this.verboseCheck(VerboseDebugFlag.CLASS_INITIALIZE))
                this.verboseEmit("Calling static init for %s.", 
                    __cl.name());
            
            // Stop execution when the initializer exits
            SpringThread thread = this.thread;
            int frameLimit = thread.numFrames();
            
            // Enter the static initializer
            this.__vmEnterFrame(init);
            
            // Execute until it finishes
            this.run(frameLimit);
        }
        
        // Tell the debugger that this class is fully initialized
        if (classTrip != null)
            classTrip.classStatus(this.thread, __cl,
                JDWPClassStatus.INITIALIZED);
        
        // Return the input class
        return __cl;
    }
    
    /**
     * Handles a native action within the VM.
     *
     * Note that the return value should be a native type, it is translated
     * as needed.
     *
     * @param __class The class the function is in.
     * @param __method The method being called.
     * @param __args The arguments to the function.
     * @return The result from the call.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/16
     */
    public final Object nativeMethod(ClassName __class,
        MethodNameAndType __method, Object... __args)
        throws NullPointerException
    {
        if (__class == null || __method == null || __args == null)
            throw new NullPointerException("NARG");
        
        // All low-level calls are considered invalid in SpringCoat because
        // it does not have the given functionality.
        if (__class.toString().startsWith("cc/squirreljme/jvm/pack/lle/"))
        {
            // Otherwise fail
            throw new SpringVirtualMachineException(String.format(
                "Invalid LLE native call: %s:%s %s", __class, __method,
                Arrays.asList(__args)));
        }
        
        // Do not allow the older SpringCoat "asm" classes to be called as
        // the interfaces are very different with the MLE layer.
        if (__class.toString().startsWith("cc/squirreljme/runtime/cldc/asm/"))
            throw new SpringVirtualMachineException(String.format(
                "Old-SpringCoat native call: %s:%s %s", __class, __method,
                Arrays.asList(__args)));
        
        // Only allow mid-level native calls
        if (!__class.toString().startsWith("cc/squirreljme/jvm/mle/"))
            throw new SpringVirtualMachineException(String.format(
                "Non-MLE native call: %s:%s %s", __class, __method,
                Arrays.asList(__args)));
        
        // Debug
        /*Debugging.debugNote("Call native %s::%s %s", __class, __method,
            Arrays.asList(__args));*/
        
        return MLEDispatcher.dispatch(this, __class, __method, __args);
    }
    
    /**
     * Creates a new instance of the given class and initializes it using the
     * given arguments. Access checks are ignored.
     *
     * @param __cl The class to initialize.
     * @param __desc The descriptor of the constructor.
     * @param __args The arguments to the constructor.
     * @return The newly created and setup object.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/16
     */
    public final SpringObject newInstance(ClassName __cl,
        MethodDescriptor __desc, Object... __args)
        throws NullPointerException
    {
        if (__cl == null)
            throw new NullPointerException("NARG");
        
        return this.newInstance(this.loadClass(__cl), __desc, __args);
    }
    
    /**
     * Creates a new instance of the given class and initializes it using the
     * given arguments. Access checks are ignored.
     *
     * @param __cl The class to initialize.
     * @param __desc The descriptor of the constructor.
     * @param __args The arguments to the constructor.
     * @return The newly created and setup object.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/16
     */
    public final SpringObject newInstance(SpringClass __cl,
        MethodDescriptor __desc, Object... __args)
        throws NullPointerException
    {
        if (__cl == null || __desc == null || __args == null)
            throw new NullPointerException("NARG");
        
        // Make sure this class is loaded
        __cl = this.loadClass(__cl);
        
        // Lookup constructor to this method
        SpringMethod cons = __cl.lookupMethod(false,
            new MethodName("<init>"), __desc);
        
        // Allocate the object
        SpringObject rv = this.allocateObject(__cl);
            
        // Stop execution when the constructor exits
        SpringThread thread = this.thread;
        int framelimit = thread.numFrames();
        
        // Need to pass the allocated object as the first argument
        int nargs = __args.length;
        Object[] callargs = new Object[nargs + 1];
        callargs[0] = rv;
        for (int i = 0, o = 1; i < nargs; i++, o++)
            callargs[o] = __args[i];
        
        // Enter the constructor
        this.__vmEnterFrame(cons, callargs);
        
        // Execute until it finishes
        this.run(framelimit);
        
        // Return the resulting object
        return rv;
    }
    
    /**
     * Proxies an input stream.
     *
     * @param __in The stream to proxy.
     * @return The proxied stream.
     * @throws IOException On read errors.
     * @throws NullPointerException On null arguments.
     * @since 2024/03/05
     */
    public SpringObject proxyInputStream(InputStream __in)
        throws IOException, NullPointerException
    {
        if (__in == null)
            throw new NullPointerException("NARG");
        
        // Use this as the stream input
        return this.newInstance(this.loadClass(
            "java/io/ByteArrayInputStream"),
            new MethodDescriptor("([B)V"),
            this.asVMObject(StreamUtils.readAll(__in)));
    }
    
    /**
     * Resolves the given class, checking access.
     *
     * @param __cl The class to resolve.
     * @return The resolved class.
     * @throws NullPointerException On null arguments.
     * @throws SpringIllegalAccessException If the class cannot be accessed.
     * @since 2020/06/17
     */
    public final SpringClass resolveClass(String __cl)
        throws NullPointerException, SpringIllegalAccessException
    {
        return this.resolveClass(new ClassName(__cl));
    }
    
    /**
     * Resolves the given class, checking access.
     *
     * @param __cl The class to resolve.
     * @return The resolved class.
     * @throws NullPointerException On null arguments.
     * @throws SpringIllegalAccessException If the class cannot be accessed.
     * @since 2018/09/15
     */
    public final SpringClass resolveClass(ClassName __cl)
        throws NullPointerException, SpringIllegalAccessException
    {
        if (__cl == null)
            throw new NullPointerException("NARG");
        
        /* {@squirreljme.error BK26 Could not access the specified class.
        (The class to access; The context class)} */
        SpringClass rv = this.loadClass(__cl);
        if (!this.checkAccess(rv))
            throw new SpringIllegalAccessException(String.format("BK26 %s %s",
                __cl, this.contextClass()));
        
        return rv;
    }
    
    /**
     * {@inheritDoc}
     * @since 2018/09/03
     */
    @Override
    public final void run()
    {
        // Run until there are no frames left
        this.run(0);
    }
    
    /**
     * Runs the worker with a limit on the lowest frame that may be reached
     * when execution finishes. This is needed in some cases to invoke methods
     * and static initializers in auxiliary code without needing complex state
     * or otherwise to handle such things.
     *
     * @param __framelimit The current frame depth execution will stop at.
     * @throws IllegalArgumentException If the frame limit is negative.
     * @since 2018/09/08
     */
    public final void run(int __framelimit)
        throws IllegalArgumentException
    {
        SpringThread thread = this.thread;
        try
        {
            /* {@squirreljme.error BK27 Cannot have a negative frame limit.
            (The frame limit)} */
            if (__framelimit < 0)
                throw new IllegalArgumentException(String.format("BK27 %d",
                    __framelimit));
            
            // The thread is alive as long as there are still frames of
            // execution
            while (thread.numFrames() > __framelimit)
            {
                // Single step executing the top frame
                this.__singleStep();
            }
        }
        
        // If the VM is exiting then clear the execution stack before we go
        // away
        catch (SpringMachineExitException e)
        {
            // Terminate the thread
            thread.terminate();
            
            // Thread is okay to exit!
            thread._signaledexit = true;
            
            // Exit all frames
            thread.exitAllFrames();
            
            // Exit profiler stack
            thread.profiler.exitAll(System.nanoTime());
        }
        
        // Caught exception
        catch (RuntimeException e)
        {
            // Printing of the stack trace for the VM error
            PrintStream err = System.err;
            err.println("****************************");
            
            // Print the real stack trace
            err.println("*** EXTERNAL STACK TRACE ***");
            e.printStackTrace(err);
            err.println();
            
            // Print the VM seen stack trace
            err.println("*** INTERNAL STACK TRACE ***");
            thread.printStackTrace(err);
            err.println();
            
            err.println("****************************");
            
            // Frame limit is zero, so kill the thread
            if (__framelimit == 0)
            {
                // Terminate the thread
                thread.terminate();
                
                // Exit all frames
                thread.exitAllFrames();
                
                // Exit from all profiler threads
                thread.profiler.exitAll(System.nanoTime());
            }
            
            // Re-toss
            throw e;
        }
        
        // Terminate if the last frame
        finally
        {
            if (__framelimit == 0)
                thread.terminate();
        }
    }
    
    /**
     * Run the main process for this thread.
     *
     * @since 2020/06/17
     */
    public final void runProcessMain()
    {
        SpringMachine machine = this.machine;
        
        // Locate the main class
        SpringClass bootClass = this.loadClass(
            machine.bootClass.replace('.', '/'));
        
        // Lookup the main method
        SpringMethod main = bootClass.lookupMethod(true,
            new MethodNameAndType("main", "([Ljava/lang/String;)V"));
        
        // Setup main arguments
        String[] args = machine.getMainArguments();
        int argsLen = args.length;
        
        // Allocate in VM
        SpringArrayObject vmArgs = this.allocateArray(
            this.resolveClass("[Ljava/lang/String;"), argsLen);
        
        // Copy everything over
        for (int i = 0; i < argsLen; i++)
            vmArgs.set(i, this.asVMObject(args[i]));
        
        // Enter the main method with all the passed arguments
        int deepness = this.thread.numFrames();
        this.thread.enterFrame(main, vmArgs);
        
        // Run until it finishes execution
        this.run(deepness);
    }
    
    /**
     * Returns the verbosity manager.
     * 
     * @return The verbose manager.
     * @since 2020/07/11
     */
    public final VMTraceFlagTracker verbose()
    {
        return this._verbose;
    }
    
    /**
     * Checks if the verbosity is enabled.
     * 
     * @param __flags The flags to check, one of {@link VerboseDebugFlag}.
     * @return If this check is enabled.
     * @since 2020/07/11
     */
    public boolean verboseCheck(int __flags)
    {
        // Was tracing enabled for this flag?
        if ((this.machine._globalTrace & __flags) != 0)
            return true;
        
        SpringThreadFrame frame = this.thread.currentFrame();
        return this._verbose.check((frame == null ? 0 : frame.level), __flags);
    }
    
    /**
     * Emits a verbose debug message.
     * 
     * @param __format The format used.
     * @param __args The arguments to the format.
     * @since 2022/06/12
     */
    public void verboseEmit(String __format, Object... __args)
    {
        SpringThreadFrame frame = this.thread.currentFrame();
        Debugging.debugNote("[%s @ %s] %s",
            this.thread.toString(),
            (frame == null ? null : String.format("%s:%d (%d)",
                (frame.method == null ? "" : frame.method.nameAndType()),
                frame.pc(),
                frame.pcSourceLine())),
            String.format(__format, __args));
    }
    
    /**
     * Checks if an exception is being thrown and sets up the state from it.
     *
     * @return True if an exception was detected.
     * @since 2018/12/06
     */
    boolean __checkException()
    {
        // Are we exiting in the middle of an exception throwing?
        this.machine.exitCheck();
        
        // Check if this frame handles the exception
        SpringThreadFrame frame = this.thread.currentFrame();
        SpringObject tossing = frame.tossedException();
        if (tossing != null)
        {
            // Handling the tossed exception, so do not try handling it again
            frame.tossException(null);
            
            // Handle it
            int pc = this.__handleException(tossing);
            if (pc < 0)
                return true;
            
            // Put it on an empty stack
            frame.clearStack();
            frame.pushToStack(tossing);
            
            // Execute at the handler address now
            frame.setPc(pc);
            return true;
        }
        
        // No exception thrown
        return false;
    }
    
    /**
     * Handles the exception, if it is in this frame to be handled then it
     * will say that the instruction is to be moved elsewhere. Otherwise it
     * will flag the frame above that an exception occurred and should be
     * handled.
     *
     * @param __o The object being thrown.
     * @return The next PC address of the handler or a negative value if it
     * is to proprogate to the above frame.
     * @throws NullPointerException On null arguments.
     * @since 2018/10/13
     */
    int __handleException(SpringObject __o)
        throws NullPointerException
    {
        if (__o == null)
            throw new NullPointerException("NARG");
        
        // Verbose debug?
        if (this.verboseCheck(VerboseDebugFlag.VM_EXCEPTION))
            this.verboseEmit("Handling exception: %s",
                __o.type().name);
            
        // Are we exiting in the middle of an exception throwing?
        this.machine.exitCheck();
        
        // Need the current frame and its byte code
        SpringThread thread = this.thread;
        SpringThreadFrame frame = thread.currentFrame();
        ByteCode code = frame.byteCode();
        int pc = frame.lastExecutedPc();
        
        // Get the handler for the given exception at the
        // given address
        ExceptionHandler useeh = null;
        for (ExceptionHandler eh : code.exceptions().at(pc))
        {
            // Is this handler compatible for the thrown
            // exception?
            SpringClass ehcl = this.loadClass(eh.type());
            
            if (ehcl.isCompatible(__o))
            {
                useeh = eh;
                break;
            }
        }
        
        // Verbose debug?
        if (this.verboseCheck(VerboseDebugFlag.VM_EXCEPTION))
            this.verboseEmit("Frame handles %s? %b",
                __o.type().name, useeh != null);
        
        // Signal that we caught an exception
        JDWPHostController jdwp = this.machine.tasks.jdwpController;
        if (jdwp != null) {
            // Emit signal
            jdwp.signal(this.thread, (useeh != null ?
                    JDWPEventKind.EXCEPTION_CATCH : JDWPEventKind.EXCEPTION),
                __o, useeh);
            
            // Check to see if we are suspended, so we can stop here if we
            // do happen to have stopped on this signal
            this.__debugSuspension();
        }
        
        // No handler for this exception, so just go up the
        // stack and find a handler recursively up every frame
        if (useeh == null)
        {
            // Pop our current frame from the call stack
            thread.popFrame();
            
            // Did we run out of stack frames?
            SpringThreadFrame cf = thread.currentFrame();
            if (cf == null)
            {
                // Just stop execution here
                return -1;
            }
            
            // Toss onto the new current frame
            cf.tossException(__o);
            
            // Stop executing here and let it continue on the
            // other top frame
            return -1;
        }
        
        // Otherwise jump to that address
        else
        {
            // Clear the stack frame and then push our
            // exception back onto the stack
            frame.clearStack();
            frame.pushToStack(__o);
            
            // Handle at this address
            return useeh.handlerAddress();
        }
    }
    
    /**
     * Invokes the given proxy method.
     * 
     * @param __method The method to invoke.
     * @param __args The arguments to the proxy call.
     * @return The result of the method call.
     * @throws NullPointerException On null arguments.
     * @since 2021/02/25
     */
    private Object __invokeProxy(MethodNameAndType __method, Object... __args)
        throws NullPointerException
    {
        if (__method == null || __args == null)
            throw new NullPointerException("NARG");
        
        // Must be a proxy object
        if (!(__args[0] instanceof SpringProxyObject))
            throw new SpringVirtualMachineException("Not a proxy object.");
        
        SpringProxyObject instance = (SpringProxyObject)__args[0];
        
        // Used for context and return value handling
        SpringThread thread = this.thread;
        SpringThreadFrame frame = thread.currentFrame();
        
        // Invoke the exception
        Object rv;
        try
        {
            // Call proxy handler
            rv = instance.invokeProxy(this, __method,
                Arrays.copyOfRange(__args, 1, __args.length));
            
            // Is this pushed to the stack?
            if (__method.type().hasReturnValue())
                frame.pushToStack(rv);
        }
        
        // Wrap any exceptions
        catch (RuntimeException e)
        {
            throw new SpringVirtualMachineException(String.format(
                "Could not proxy invoke %s.", __method));
        }
        
        return rv;
    }
    
    /**
     * Looks up the specified instance field specifier and returns the
     * information for it.
     *
     * @param __f The field to lookup.
     * @return The specified for the field.
     * @throws NullPointerException On null arguments.
     * @throws SpringIncompatibleClassChangeException If the field is static.
     * @throws SpringNoSuchFieldException If the field does not exist.
     * @since 2018/09/16
     */
    private SpringField __lookupInstanceField(FieldReference __f)
        throws NullPointerException, SpringIncompatibleClassChangeException,
            SpringNoSuchFieldException
    {
        if (__f == null)
            throw new NullPointerException("NARG");
            
        /* {@squirreljme.error BK28 Could not access the target class for
        instance field access. (The field reference)} */
        SpringClass inclass = this.loadClass(__f.className());
        if (!this.checkAccess(inclass))
            throw new SpringIncompatibleClassChangeException(
                String.format("BK28 %s", __f));
        
        /* {@squirreljme.error BK29 Could not access the target field for
        instance field access. (The field reference; The field flags)} */
        SpringField field = inclass.lookupField(false,
            __f.memberNameAndType());
        if (!this.checkAccess(field))
            throw new SpringIncompatibleClassChangeException(
                String.format("BK29 %s %s", __f, field.flags()));
        
        return field;
    }
    
    /**
     * Looks up the specified static field and returns the storage for it.
     *
     * @param __f The field to lookup.
     * @param __outField Output field, this is completely optional and may
     * be {@code null}.
     * @return The static field storage.
     * @throws NullPointerException On null arguments.
     * @throws SpringIncompatibleClassChangeException If the target field is
     * not static.
     * @throws SpringNoSuchFieldException If the field does not exist.
     * @since 2018/09/09
     */
    private SpringFieldStorage __lookupStaticField(FieldReference __f,
        SpringField[] __outField)
        throws NullPointerException, SpringIncompatibleClassChangeException,
            SpringNoSuchFieldException
    {
        if (__f == null)
            throw new NullPointerException("NARG");
        
        // Static fields can point to a parent class but truly exist in a
        // super class
        SpringClass inClass = this.loadClass(__f.className());
        while (inClass != null)
        {
            /* {@squirreljme.error BK2a Could not access the target class for
            static field access. (The field reference)} */
            if (!this.checkAccess(inClass))
                throw new SpringIncompatibleClassChangeException(
                    String.format("BK2a %s", __f));
            
            // Try finding the field
            SpringField field;
            try
            {
                field = inClass.lookupField(
                    true, __f.memberNameAndType());
            }
            catch (SpringNoSuchFieldException ignored)
            {
                // Not found, so try the super class
                inClass = inClass.superClass();
                continue;
            }
            
            // Record field if requested
            if (__outField != null && __outField.length > 0)
                __outField[0] = field;
            
            /* {@squirreljme.error BK2b Could not access the target field for
            static field access. (The field reference)} */
            if (!this.checkAccess(field))
                throw new SpringIncompatibleClassChangeException(
                    String.format("BK2b %s", __f));
            
            // Get the field index
            int index = field.index;
            
            // Look into the class storage
            SpringFieldStorage[] store = inClass._staticFields;
            if (index >= inClass._staticFieldBase && index < store.length &&
                store[index] != null)
                return store[index];
                
            // Not found, so try the super class
            inClass = inClass.superClass();
        }
        
        // This should not hopefully happen
        throw new SpringNoSuchFieldException(
            String.format("Static field %s not found.", __f));
    }
    
    /**
     * Single step through handling a single instruction.
     *
     * This method uses strict floating point to make operations consistent.
     *
     * @since 2018/09/03
     */
    private strictfp void __singleStep()
    {
        // Need the current frame and its byte code
        SpringThread thread = this.thread;
        
        // Check if the VM is exiting, to discontinue execution if it has been
        // requested by any thread
        SpringMachine machine = this.machine;
        try
        {
            machine.exitCheck();
        }
        
        // If the VM is exiting then clear the execution stack before we go
        // away
        catch (SpringMachineExitException e)
        {
            // Thread is okay to exit!
            thread.terminate();
            
            // Exit profiler stack
            thread.profiler.exitAll(System.nanoTime());
            
            throw e;
        }
        
        // We need the current frame and byte code so that we can check on
        // our breakpoints
        SpringThreadFrame frame = thread.currentFrame();
        SpringMethod method = frame.method();
        ByteCode code = frame.byteCode();
        
        // Poll the JDWP debugger for any new debugging state
        // Note that if the thread is exempt from suspension do not single
        // step or stop on any breakpoint...
        JDWPHostController jdwp = this.machine.tasks.jdwpController;
        if (jdwp != null && !thread.noDebugSuspend)
        {
            // Check for breakpoints to stop at first, because if our thread
            // gets suspended we want to know before we check for suspension.
            Map<Integer, JDWPTripBreakpoint> jdwpBreakpoints =
                method.__breakpoints(false);
            if (jdwpBreakpoints != null)
            {
                // See if we can trip on this
                JDWPTripBreakpoint trip;
                synchronized (jdwpBreakpoints)
                {
                    trip = jdwpBreakpoints.get(frame.pc());
                }
                
                // Perform the trip outside of the lock, so we do not deadlock
                if (trip != null)
                    trip.breakpoint(thread);
            }
            
            // Check if we are doing any single stepping
            JDWPHostStepTracker stepTracker = thread._stepTracker;
            if (stepTracker != null && stepTracker.inSteppingMode())
            {
                // Tick the current tracker and see if it will activate
                // before we trigger this event
                if (stepTracker.tick(jdwp, thread))
                    jdwp.trip(JDWPTripThread.class, JDWPGlobalTrip.THREAD)
                        .step(thread, stepTracker);
            }
            
            // Poll and block on suspension when debugging
            this.__debugSuspension();
        }
        
        // Increase the step count
        this._stepCount++;
        
        // Frame is execution
        int iec = frame.incrementExecCount();
        if (iec > 0 && (iec % SpringThreadWorker._EXECUTION_THRESHOLD) == 0)
        {
            /* {@squirreljme.error BK2c Execution seems to be stuck in this
            method.} */
            System.err.println("BK2c");
            this.thread.printStackTrace(System.err);
        }
        
        // Are these certain kinds of initializers? Because final fields are
        // writable during initialization accordingly
        SpringClass currentclass = this.contextClass();
        boolean isstaticinit = method.isStaticInitializer(),
            isinstanceinit = method.isInstanceInitializer();
        
        // Determine the current instruction of execution
        int pc = frame.pc();
        Instruction inst = code.getByAddress(pc);
        
        // If we are tossing an exception, we need to handle it
        if (this.__checkException())
            return;
        
        // This PC is about to be executed, so set it as executed since if an
        // exception is thrown this could change potentially
        frame.setLastExecutedPc(pc);
        
        // Debugging instructions?
        if (this.verboseCheck(VerboseDebugFlag.INSTRUCTIONS))
            this.verboseEmit("step(%s %s::%s) -> %s", thread.name(),
                method.inClass(), method.nameAndType(), inst);
        
        // Used to detect the next instruction of execution following this,
        // may be set accordingly in the frame manually
        int nextPc = code.addressFollowing(pc);
        int origNextPc = nextPc;
        
        // Handle individual instructions
        int opId;
        try
        {
            // Handle it
            switch ((opId = inst.operation()))
            {
                    // Do absolutely nothing!
                case InstructionIndex.NOP:
                    break;
                    
                    // Load object from array
                case InstructionIndex.AALOAD:
                    {
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        frame.pushToStack(obj.<SpringObject>get(
                            SpringObject.class, dx));
                    }
                    break;
                    
                    // Store object to array
                case InstructionIndex.AASTORE:
                    {
                        SpringObject value = frame.<SpringObject>popFromStack(
                            SpringObject.class);
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        obj.set(dx, value);
                    }
                    break;
                    
                    // Push null reference
                case InstructionIndex.ACONST_NULL:
                    frame.pushToStack(SpringNullObject.NULL);
                    break;
                    
                    // Load reference from local
                case InstructionIndex.ALOAD:
                case InstructionIndex.WIDE_ALOAD:
                    frame.loadToStack(SpringObject.class,
                        inst.<Integer>argument(0, Integer.class));
                    break;
                    
                    // Load reference from local (short)
                case InstructionIndex.ALOAD_0:
                case InstructionIndex.ALOAD_1:
                case InstructionIndex.ALOAD_2:
                case InstructionIndex.ALOAD_3:
                    frame.loadToStack(SpringObject.class,
                        opId - InstructionIndex.ALOAD_0);
                    break;
                
                    // Allocate new array
                case InstructionIndex.ANEWARRAY:
                    frame.pushToStack(this.allocateArray(this.resolveClass(
                        inst.<ClassName>argument(0, ClassName.class)
                        .addDimensions(1)),
                        frame.<Integer>popFromStack(Integer.class)));
                    break;
                    
                    // Return reference
                case InstructionIndex.ARETURN:
                    SpringObject rvObject = frame.<SpringObject>popFromStack(
                        SpringObject.class);
                    this.__vmReturn(thread,
                        (rvObject != null ? rvObject : SpringNullObject.NULL));
                    nextPc = Integer.MIN_VALUE;
                    break;
                    
                    // Length of array
                case InstructionIndex.ARRAYLENGTH:
                    frame.pushToStack(
                        frame.<SpringArrayObject>popFromStackNotNull(
                        SpringArrayObject.class).length());
                    break;
                    
                    // Store reference to local variable
                case InstructionIndex.ASTORE:
                case InstructionIndex.WIDE_ASTORE:
                    frame.storeLocal(inst.<Integer>argument(0, Integer.class),
                        frame.<SpringObject>popFromStack(SpringObject.class));
                    break;
                    
                    // Store reference to local varibale
                case InstructionIndex.ASTORE_0:
                case InstructionIndex.ASTORE_1:
                case InstructionIndex.ASTORE_2:
                case InstructionIndex.ASTORE_3:
                    {
                        frame.storeLocal(opId - InstructionIndex.ASTORE_0,
                            frame.<SpringObject>popFromStack(
                                SpringObject.class));
                    }
                    break;
                    
                    // Throwing of an exception
                case InstructionIndex.ATHROW:
                    {
                        SpringObject popped =
                            frame.<SpringObject>popFromStack(
                                SpringObject.class);
                        
                        /* {@squirreljme.error BKnt Throwing null reference.} */
                        if (popped == SpringNullObject.NULL)
                            throw new SpringNullPointerException("BKnt");
                        
                        nextPc = this.__handleException(popped);
                        if (nextPc < 0)
                            return;
                    }
                    break;
                    
                    // Push value
                case InstructionIndex.BIPUSH:
                case InstructionIndex.SIPUSH:
                    frame.pushToStack(inst.<Integer>argument(
                        0, Integer.class));
                    break;
                    
                    // Checks casting from a type to another
                case InstructionIndex.CHECKCAST:
                    {
                        SpringClass as = this.resolveClass(inst.
                            <ClassName>argument(0, ClassName.class));
                        
                        // This is just popped back on if it passes
                        SpringObject pop = frame.<SpringObject>popFromStack(
                            SpringObject.class);
                        
                        /* {@squirreljme.error BK2d Cannot cast object to the
                        target type. (The type to cast to; The type of the
                        object)} */
                        if (pop != SpringNullObject.NULL &&
                            !(pop instanceof AbstractGhostObject) &&
                            !as.isAssignableFrom(pop.type()))
                            throw new SpringClassCastException(String.format(
                                "BK2d %s %s", as, pop.type()));
                        
                        // Return the popped value
                        else
                            frame.pushToStack(pop);
                    }
                    break;
                    
                    // Double to float
                case InstructionIndex.D2F:
                    {
                        double value = frame.<Double>popFromStack(Double.class);
                        frame.pushToStack(Float.valueOf((float)value));
                    }
                    break;
                    
                    // Double to int
                case InstructionIndex.D2I:
                    {
                        double value = frame.<Double>popFromStack(Double.class);
                        frame.pushToStack(Integer.valueOf((int)value));
                    }
                    break;
                    
                    // Double to long
                case InstructionIndex.D2L:
                    {
                        double value = frame.<Double>popFromStack(Double.class);
                        frame.pushToStack(Long.valueOf((long)value));
                    }
                    break;
                
                    // Addiply double
                case InstructionIndex.DADD:
                    {
                        double b = frame.<Double>popFromStack(Double.class),
                            a = frame.<Double>popFromStack(Double.class);
                        frame.pushToStack(a + b);
                    }
                    break;
                    
                    // Compare double, NaN is positive
                case InstructionIndex.DCMPG:
                    {
                        double b = frame.<Float>popFromStack(Float.class),
                            a = frame.<Float>popFromStack(Float.class);
                        
                        if (Double.isNaN(a) || Double.isNaN(b))
                            frame.pushToStack(1);
                        else
                            frame.pushToStack((a < b ? -1 : (a > b ? 1 : 0)));
                    }
                    break;
                
                    // Compare double, NaN is negative
                case InstructionIndex.DCMPL:
                    {
                        double b = frame.<Double>popFromStack(Double.class),
                            a = frame.<Double>popFromStack(Double.class);
                        
                        if (Double.isNaN(a) || Double.isNaN(b))
                            frame.pushToStack(-1);
                        else
                            frame.pushToStack((a < b ? -1 : (a > b ? 1 : 0)));
                    }
                    break;
                    
                    // Double constant
                case InstructionIndex.DCONST_0:
                case InstructionIndex.DCONST_1:
                    frame.pushToStack(
                        Double.valueOf(opId - InstructionIndex.DCONST_0));
                    break;
                
                    // Divide double
                case InstructionIndex.DDIV:
                    {
                        double b = frame.<Double>popFromStack(Double.class),
                            a = frame.<Double>popFromStack(Double.class);
                        frame.pushToStack(a / b);
                    }
                    break;
                    
                    // Load double from local variable
                case InstructionIndex.DLOAD:
                case InstructionIndex.WIDE_DLOAD:
                    frame.loadToStack(Double.class,
                        inst.<Integer>argument(0, Integer.class));
                    break;
                    
                    // Load double from local variable
                case InstructionIndex.DLOAD_0:
                case InstructionIndex.DLOAD_1:
                case InstructionIndex.DLOAD_2:
                case InstructionIndex.DLOAD_3:
                    frame.loadToStack(Double.class,
                        opId - InstructionIndex.DLOAD_0);
                    break;
                
                    // Multiply double
                case InstructionIndex.DMUL:
                    {
                        double b = frame.<Double>popFromStack(Double.class),
                            a = frame.<Double>popFromStack(Double.class);
                        frame.pushToStack(a * b);
                    }
                    break;
                
                    // Negate double
                case InstructionIndex.DNEG:
                    {
                        double a = frame.<Double>popFromStack(Double.class);
                        frame.pushToStack(-a);
                    }
                    break;
                
                    // Remainder double
                case InstructionIndex.DREM:
                    {
                        double b = frame.<Double>popFromStack(Double.class),
                            a = frame.<Double>popFromStack(Double.class);
                        frame.pushToStack(a % b);
                    }
                    break;
                    
                    // Return double
                case InstructionIndex.DRETURN:
                    this.__vmReturn(thread,
                        frame.<Double>popFromStack(Double.class));
                    nextPc = Integer.MIN_VALUE;
                    break;
                
                    // Subtract double
                case InstructionIndex.DSUB:
                    {
                        double b = frame.<Double>popFromStack(Double.class),
                            a = frame.<Double>popFromStack(Double.class);
                        frame.pushToStack(a - b);
                    }
                    break;
                    
                    // Store double to local variable
                case InstructionIndex.DSTORE:
                case InstructionIndex.WIDE_DSTORE:
                    frame.storeLocal(inst.<Integer>argument(0, Integer.class),
                        frame.<Double>popFromStack(Double.class));
                    break;
                    
                    // Store long to double variable
                case InstructionIndex.DSTORE_0:
                case InstructionIndex.DSTORE_1:
                case InstructionIndex.DSTORE_2:
                case InstructionIndex.DSTORE_3:
                    frame.storeLocal(opId - InstructionIndex.DSTORE_0,
                        frame.<Double>popFromStack(Double.class));
                    break;
                    
                    // Duplicate top-most stack entry
                case InstructionIndex.DUP:
                    {
                        Object copy = frame.popFromStack();
                        
                        /* {@squirreljme.error BK2e Cannot duplicate category
                        two type.} */
                        if (copy instanceof Long || copy instanceof Double)
                            throw new SpringVirtualMachineException("BK2e");
                        
                        // Push twice!
                        frame.pushToStack(copy);
                        frame.pushToStack(copy);
                    }
                    break;
                    
                    // Duplicate top and place two down
                case InstructionIndex.DUP_X1:
                    {
                        Object a = frame.popFromStack(),
                            b = frame.popFromStack();
                        
                        /* {@squirreljme.error BK2f Cannot duplicate and place
                        down below with two type.} */
                        if (a instanceof Long || a instanceof Double ||
                            b instanceof Long || b instanceof Double)
                            throw new SpringVirtualMachineException("BK2f");
                        
                        frame.pushToStack(a);
                        frame.pushToStack(b);
                        frame.pushToStack(a);
                    }
                    break;
                    
                    // Dup[licate top entry and place two or three down
                case InstructionIndex.DUP_X2:
                    {
                        Object a = frame.popFromStack(),
                            b = frame.popFromStack();
                        
                        /* {@squirreljme.error BK2g Cannot duplicate cat2
                        type.} */
                        if (a instanceof Long || a instanceof Double)
                            throw new SpringVirtualMachineException("BK2g");
                        
                        // Insert A below C
                        if (b instanceof Long || b instanceof Double)
                        {
                            frame.pushToStack(a);
                            frame.pushToStack(b);
                            frame.pushToStack(a);
                        }
                        
                        // Grab C as well and push below that
                        else
                        {
                            Object c = frame.popFromStack();
                            
                            /* {@squirreljme.error BK2h Cannot duplicate top
                            most entry and place two down because a cat2
                            type is in the way.} */
                            if (c instanceof Long || c instanceof Double)
                                throw new SpringVirtualMachineException(
                                    "BK2h");
                                    
                            frame.pushToStack(a);
                            frame.pushToStack(c);
                            frame.pushToStack(b);
                            frame.pushToStack(a);
                        }
                    }
                    break;
                    
                    // Duplicate top two cat1s or single cat2
                case InstructionIndex.DUP2:
                    {
                        Object a = frame.popFromStack();
                        
                        // Just cat two
                        if (a instanceof Long || a instanceof Double)
                        {
                            frame.pushToStack(a);
                            frame.pushToStack(a);
                        }
                        
                        // Double values
                        else
                        {
                            Object b = frame.popFromStack();
                            
                            /* {@squirreljme.error BK2i Cannot duplicate top
                            two values.} */
                            if (b instanceof Long || b instanceof Double)
                                throw new SpringVirtualMachineException(
                                    "BK2i");
                            
                            frame.pushToStack(b);
                            frame.pushToStack(a);
                            frame.pushToStack(b);
                            frame.pushToStack(a);
                        }
                    }
                    break;
                    
                    // Duplicate top one or two operand values and insert two
                    // or three values down
                case InstructionIndex.DUP2_X1:
                    {
                        Object a = frame.popFromStack(),
                            b = frame.popFromStack();
                        
                        /* {@squirreljme.error BK2j Expected category one
                        type.} */
                        if (b instanceof Long || b instanceof Double)
                            throw new SpringVirtualMachineException(
                                "BK2j");
                        
                        // Insert this below b
                        if (a instanceof Long || a instanceof Double)
                        {
                            frame.pushToStack(a);
                            frame.pushToStack(b);
                            frame.pushToStack(a);
                        }
                        
                        // Three cat1 values
                        else
                        {
                            Object c = frame.popFromStack();
                            
                            /* {@squirreljme.error BK2k Cannot duplicate value
                            below category two type.} */
                            if (c instanceof Long || c instanceof Double)
                                throw new SpringVirtualMachineException(
                                    "BK2k");
                            
                            frame.pushToStack(b);
                            frame.pushToStack(a);
                            frame.pushToStack(c);
                            frame.pushToStack(b);
                            frame.pushToStack(a);
                        }
                    }
                    break;
                
                    // Duplicate top one or two stack entries and insert
                    // two, three, or four down
                case InstructionIndex.DUP2_X2:
                    {
                        Object a = frame.popFromStack(),
                            b = frame.popFromStack();
                        
                        // Category two is on top
                        if (a instanceof Long || a instanceof Double)
                        {
                            // Category two is on bottom (form 4)
                            if (b instanceof Long || b instanceof Double)
                            {
                                frame.pushToStack(a);
                                frame.pushToStack(b);
                                frame.pushToStack(a);
                            }
                            
                            // Category ones on bottom (form 2)
                            else
                            {
                                Object c = frame.popFromStack();
                                
                                /* {@squirreljme.error BK2l Cannot pop cat2
                                type for dup.} */
                                if (c instanceof Long || c instanceof Double)
                                    throw new SpringVirtualMachineException(
                                        "BK2l");
                                
                                frame.pushToStack(a);
                                frame.pushToStack(c);
                                frame.pushToStack(b);
                                frame.pushToStack(a);
                            }
                        }
                        
                        // Category one is on top
                        else
                        {
                            /* {@squirreljme.error BK2m Category two type
                            cannot be on the bottom.} */
                            if (b instanceof Long || b instanceof Double)
                                throw new SpringVirtualMachineException(
                                    "BK2m");
                            
                            Object c = frame.popFromStack();
                            
                            // C is category two (Form 3)
                            if (c instanceof Long || c instanceof Double)
                            {
                                frame.pushToStack(b);
                                frame.pushToStack(a);
                                frame.pushToStack(c);
                                frame.pushToStack(b);
                                frame.pushToStack(a);
                            }
                            
                            // Category one on bottom (Form 1)
                            else
                            {
                                Object d = frame.popFromStack();
                                
                                /* {@squirreljme.error BK2n Bottommost entry
                                cannot be cat2 type.} */
                                if (d instanceof Long || d instanceof Double)
                                    throw new SpringVirtualMachineException(
                                        "BK2n");
                                
                                frame.pushToStack(b);
                                frame.pushToStack(a);
                                frame.pushToStack(d);
                                frame.pushToStack(c);
                                frame.pushToStack(b);
                                frame.pushToStack(a);
                            }
                        }
                    }
                    break;
                    
                    // Float to double
                case InstructionIndex.F2D:
                    {
                        float value = frame.<Float>popFromStack(Float.class);
                        frame.pushToStack(Double.valueOf((double)value));
                    }
                    break;
                    
                    // Float to integer
                case InstructionIndex.F2I:
                    {
                        float value = frame.<Float>popFromStack(Float.class);
                        frame.pushToStack(Integer.valueOf((int)value));
                    }
                    break;
                    
                    // Float to long
                case InstructionIndex.F2L:
                    {
                        float value = frame.<Float>popFromStack(Float.class);
                        frame.pushToStack(Long.valueOf((long)value));
                    }
                    break;
                
                    // Add float
                case InstructionIndex.FADD:
                    {
                        float b = frame.<Float>popFromStack(Float.class),
                            a = frame.<Float>popFromStack(Float.class);
                        frame.pushToStack(a + b);
                    }
                    break;
                
                    // Compare float, NaN is positive
                case InstructionIndex.FCMPG:
                    {
                        float b = frame.<Float>popFromStack(Float.class),
                            a = frame.<Float>popFromStack(Float.class);
                        
                        if (Float.isNaN(a) || Float.isNaN(b))
                            frame.pushToStack(1);
                        else
                            frame.pushToStack((a < b ? -1 : (a > b ? 1 : 0)));
                    }
                    break;
                
                    // Compare float, NaN is negative
                case InstructionIndex.FCMPL:
                    {
                        float b = frame.<Float>popFromStack(Float.class),
                            a = frame.<Float>popFromStack(Float.class);
                        
                        if (Float.isNaN(a) || Float.isNaN(b))
                            frame.pushToStack(-1);
                        else
                            frame.pushToStack((a < b ? -1 : (a > b ? 1 : 0)));
                    }
                    break;
                    
                    // Float constant
                case InstructionIndex.FCONST_0:
                case InstructionIndex.FCONST_1:
                case InstructionIndex.FCONST_2:
                    frame.pushToStack(
                        Float.valueOf(opId - InstructionIndex.FCONST_0));
                    break;
                
                    // Divide float
                case InstructionIndex.FDIV:
                    {
                        float b = frame.<Float>popFromStack(Float.class),
                            a = frame.<Float>popFromStack(Float.class);
                        frame.pushToStack(a / b);
                    }
                    break;
                    
                    // Load float from local variable
                case InstructionIndex.FLOAD:
                case InstructionIndex.WIDE_FLOAD:
                    frame.loadToStack(Float.class,
                        inst.<Integer>argument(0, Integer.class));
                    break;
                    
                    // Load float from local variable
                case InstructionIndex.FLOAD_0:
                case InstructionIndex.FLOAD_1:
                case InstructionIndex.FLOAD_2:
                case InstructionIndex.FLOAD_3:
                    frame.loadToStack(Float.class,
                        opId - InstructionIndex.FLOAD_0);
                    break;
                
                    // Multiply float
                case InstructionIndex.FMUL:
                    {
                        float b = frame.<Float>popFromStack(Float.class),
                            a = frame.<Float>popFromStack(Float.class);
                        frame.pushToStack(a * b);
                    }
                    break;
                
                    // Negate float
                case InstructionIndex.FNEG:
                    {
                        float a = frame.<Float>popFromStack(Float.class);
                        frame.pushToStack(-a);
                    }
                    break;
                
                    // Remainder float
                case InstructionIndex.FREM:
                    {
                        float b = frame.<Float>popFromStack(Float.class),
                            a = frame.<Float>popFromStack(Float.class);
                        frame.pushToStack(a % b);
                    }
                    break;
                    
                    // Return float
                case InstructionIndex.FRETURN:
                    this.__vmReturn(thread,
                        frame.<Float>popFromStack(Float.class));
                    nextPc = Integer.MIN_VALUE;
                    break;
                
                    // Subtract float
                case InstructionIndex.FSUB:
                    {
                        float b = frame.<Float>popFromStack(Float.class),
                            a = frame.<Float>popFromStack(Float.class);
                        frame.pushToStack(a - b);
                    }
                    break;
                    
                    // Store float to local variable
                case InstructionIndex.FSTORE:
                case InstructionIndex.WIDE_FSTORE:
                    frame.storeLocal(inst.<Integer>argument(0, Integer.class),
                        frame.<Float>popFromStack(Float.class));
                    break;
                    
                    // Store float to local variable
                case InstructionIndex.FSTORE_0:
                case InstructionIndex.FSTORE_1:
                case InstructionIndex.FSTORE_2:
                case InstructionIndex.FSTORE_3:
                    frame.storeLocal(opId - InstructionIndex.FSTORE_0,
                        frame.<Float>popFromStack(Float.class));
                    break;
                    
                    // Read from instance field
                case InstructionIndex.GETFIELD:
                    {
                        // Lookup field
                        SpringField ssf = this.__lookupInstanceField(
                            inst.<FieldReference>argument(0,
                            FieldReference.class));
                        
                        // Pop the object to read from
                        SpringObject ref = frame.<SpringObject>popFromStack(
                            SpringObject.class);
                        
                        /* {@squirreljme.error BK2o Cannot read value from
                        null reference.} */
                        if (ref == SpringNullObject.NULL)
                            throw new SpringNullPointerException("BK2o");
                        
                        /* {@squirreljme.error BK2p Cannot read value from
                        this instance because it not a simple object.} */
                        if (!(ref instanceof SpringSimpleObject))
                            throw new SpringIncompatibleClassChangeException(
                                "BK2p");
                        SpringSimpleObject sso = (SpringSimpleObject)ref;
                        
                        // Read and push to the stack
                        SpringFieldStorage store =
                            sso.fieldByIndex(ssf.index());
                        frame.pushToStack(this.asVMObject(store.get()));
                        
                        // Debug signal
                        if (jdwp != null && ssf.isDebugWatching(false))
                            jdwp.trip(JDWPTripField.class,
                                JDWPGlobalTrip.FIELD).field(thread,
                                    this.loadClass(ssf.inclass),
                                    ssf.index, false, ref, null);
                    }
                    break;
                    
                    // Read static variable
                case InstructionIndex.GETSTATIC:
                    {
                        // Lookup field
                        FieldReference fieldRef =
                            inst.<FieldReference>argument(0,
                                FieldReference.class);
                        SpringField[] field = new SpringField[1];
                        SpringFieldStorage ssf = this.__lookupStaticField(
                            fieldRef, field);
                        
                        // Push read value to stack
                        frame.pushToStack(this.asVMObject(
                            ssf.get()));
                        
                        // Debug signal
                        if (jdwp != null &&
                            field[0].isDebugWatching(false))
                            jdwp.trip(JDWPTripField.class,
                                JDWPGlobalTrip.FIELD).field(thread,
                                    this.loadClass(ssf.inclass),
                                    ssf.fieldIndex, false,
                                    null, null);
                    }
                    break;
                    
                    // Go to address
                case InstructionIndex.GOTO:
                case InstructionIndex.GOTO_W:
                    nextPc = inst.<InstructionJumpTarget>argument(0,
                        InstructionJumpTarget.class).target();
                    break;
                    
                    // Load integer from array
                case InstructionIndex.BALOAD:
                case InstructionIndex.CALOAD:
                case InstructionIndex.SALOAD:
                case InstructionIndex.IALOAD:
                    {
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        frame.pushToStack(obj.<Integer>get(Integer.class, dx));
                    }
                    break;
                    
                    // Load double from array
                case InstructionIndex.DALOAD:
                    {
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        frame.pushToStack(obj.<Double>get(Double.class, dx));
                    }
                    break;
                    
                    // Load float from array
                case InstructionIndex.FALOAD:
                    {
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        frame.pushToStack(obj.<Float>get(Float.class, dx));
                    }
                    break;
                    
                    
                    // Load long from array
                case InstructionIndex.LALOAD:
                    {
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        frame.pushToStack(obj.<Long>get(Long.class, dx));
                    }
                    break;
                    
                    // Store integer to array (compatible)
                case InstructionIndex.BASTORE:
                case InstructionIndex.CASTORE:
                case InstructionIndex.SASTORE:
                case InstructionIndex.IASTORE:
                    {
                        int value = frame.<Integer>popFromStack(Integer.class);
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        obj.set(dx, value);
                    }
                    break;
                    
                    // Store double to array
                case InstructionIndex.DASTORE:
                    {
                        double value = frame.<Double>popFromStack(
                            Double.class);
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        obj.set(dx, value);
                    }
                    break;
                    
                    // Store float to array
                case InstructionIndex.FASTORE:
                    {
                        float value = frame.<Float>popFromStack(Float.class);
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        obj.set(dx, value);
                    }
                    break;
                    
                    // Store long to array
                case InstructionIndex.LASTORE:
                    {
                        long value = frame.<Long>popFromStack(Long.class);
                        int dx = frame.<Integer>popFromStack(Integer.class);
                        SpringArrayObject obj = frame.<SpringArrayObject>
                            popFromStackNotNull(SpringArrayObject.class);
                        
                        obj.set(dx, value);
                    }
                    break;
                    
                    // Integer to byte
                case InstructionIndex.I2B:
                    {
                        int value = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(Byte.valueOf((byte)value).
                            intValue());
                    }
                    break;
                    
                    // Integer to double
                case InstructionIndex.I2D:
                    {
                        int value = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(Double.valueOf(value));
                    }
                    break;
                    
                    // Integer to long
                case InstructionIndex.I2L:
                    {
                        int value = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(Long.valueOf(value));
                    }
                    break;
                    
                    // Integer to character
                case InstructionIndex.I2C:
                    {
                        int value = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(Integer.valueOf((char)value));
                    }
                    break;
                    
                    // Integer to short
                case InstructionIndex.I2S:
                    {
                        int value = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(Integer.valueOf((short)value));
                    }
                    break;
                    
                    // Integer to float
                case InstructionIndex.I2F:
                    {
                        int value = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(Float.valueOf(value));
                    }
                    break;
                    
                    // Integer constant
                case InstructionIndex.ICONST_M1:
                case InstructionIndex.ICONST_0:
                case InstructionIndex.ICONST_1:
                case InstructionIndex.ICONST_2:
                case InstructionIndex.ICONST_3:
                case InstructionIndex.ICONST_4:
                case InstructionIndex.ICONST_5:
                    frame.pushToStack(Integer.valueOf(
                        -1 + (opId - InstructionIndex.ICONST_M1)));
                    break;
                    
                    // Object a == b
                case InstructionIndex.IF_ACMPEQ:
                    {
                        SpringObject b = frame.<SpringObject>popFromStack(
                                SpringObject.class),
                            a = frame.<SpringObject>popFromStack(
                                SpringObject.class);
                        
                        if (a == b)
                            nextPc = inst.<InstructionJumpTarget>argument(0,
                                InstructionJumpTarget.class).target();
                    }
                    break;
                    
                    // Object a != b
                case InstructionIndex.IF_ACMPNE:
                    {
                        SpringObject b = frame.<SpringObject>popFromStack(
                                SpringObject.class),
                            a = frame.<SpringObject>popFromStack(
                                SpringObject.class);
                        
                        if (a != b)
                            nextPc = inst.<InstructionJumpTarget>argument(0,
                                InstructionJumpTarget.class).target();
                    }
                    break;
                    
                    // int a == b
                case InstructionIndex.IF_ICMPEQ:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        
                        if (a == b)
                            nextPc = inst.<InstructionJumpTarget>argument(0,
                                InstructionJumpTarget.class).target();
                    }
                    break;
                    
                    // int a >= b
                case InstructionIndex.IF_ICMPGE:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        
                        if (a >= b)
                            nextPc = inst.<InstructionJumpTarget>argument(0,
                                InstructionJumpTarget.class).target();
                    }
                    break;
                    
                    // int a > b
                case InstructionIndex.IF_ICMPGT:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        
                        if (a > b)
                            nextPc = inst.<InstructionJumpTarget>argument(0,
                                InstructionJumpTarget.class).target();
                    }
                    break;
                    
                    // int a <= b
                case InstructionIndex.IF_ICMPLE:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        
                        if (a <= b)
                            nextPc = inst.<InstructionJumpTarget>argument(0,
                                InstructionJumpTarget.class).target();
                    }
                    break;
                    
                    // int a < b
                case InstructionIndex.IF_ICMPLT:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        
                        if (a < b)
                            nextPc = inst.<InstructionJumpTarget>argument(0,
                                InstructionJumpTarget.class).target();
                    }
                    break;
                    
                    // int a != b
                case InstructionIndex.IF_ICMPNE:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        
                        if (a != b)
                            nextPc = inst.<InstructionJumpTarget>argument(0,
                                InstructionJumpTarget.class).target();
                    }
                    break;
                    
                    // int a == 0
                case InstructionIndex.IFEQ:
                    if (frame.<Integer>popFromStack(Integer.class) == 0)
                        nextPc = inst.<InstructionJumpTarget>argument(0,
                            InstructionJumpTarget.class).target();
                    break;
                    
                    // int a >= 0
                case InstructionIndex.IFGE:
                    if (frame.<Integer>popFromStack(Integer.class) >= 0)
                        nextPc = inst.<InstructionJumpTarget>argument(0,
                            InstructionJumpTarget.class).target();
                    break;
                    
                    // int a > 0
                case InstructionIndex.IFGT:
                    if (frame.<Integer>popFromStack(Integer.class) > 0)
                        nextPc = inst.<InstructionJumpTarget>argument(0,
                            InstructionJumpTarget.class).target();
                    break;
                    
                    // int a <= 0
                case InstructionIndex.IFLE:
                    if (frame.<Integer>popFromStack(Integer.class) <= 0)
                        nextPc = inst.<InstructionJumpTarget>argument(0,
                            InstructionJumpTarget.class).target();
                    break;
                    
                    // int a < 0
                case InstructionIndex.IFLT:
                    if (frame.<Integer>popFromStack(Integer.class) < 0)
                        nextPc = inst.<InstructionJumpTarget>argument(0,
                            InstructionJumpTarget.class).target();
                    break;
                    
                    // int a != 0
                case InstructionIndex.IFNE:
                    if (frame.<Integer>popFromStack(Integer.class) != 0)
                        nextPc = inst.<InstructionJumpTarget>argument(0,
                            InstructionJumpTarget.class).target();
                    break;
                    
                    // If reference is not null
                case InstructionIndex.IFNONNULL:
                    if (frame.<SpringObject>popFromStack(
                        SpringObject.class) != SpringNullObject.NULL)
                        nextPc = inst.<InstructionJumpTarget>argument(0,
                            InstructionJumpTarget.class).target();
                    break;
                    
                    // If reference is null
                case InstructionIndex.IFNULL:
                    {
                        SpringObject a = frame.<SpringObject>popFromStack(
                            SpringObject.class);
                        if (a == SpringNullObject.NULL)
                            nextPc = inst.<InstructionJumpTarget>argument(0,
                                InstructionJumpTarget.class).target();
                    }
                    break;
                    
                    // Increment local variable
                case InstructionIndex.IINC:
                case InstructionIndex.WIDE_IINC:
                    {
                        int dx = inst.<Integer>argument(0, Integer.class);
                        frame.storeLocal(dx, frame.<Integer>loadLocal(
                            Integer.class, dx) + inst.<Integer>argument(1,
                            Integer.class));
                    }
                    break;
                    
                    // Load integer from local variable
                case InstructionIndex.ILOAD:
                case InstructionIndex.WIDE_ILOAD:
                    frame.loadToStack(Integer.class,
                        inst.<Integer>argument(0, Integer.class));
                    break;
                    
                    // Load integer from local variable
                case InstructionIndex.ILOAD_0:
                case InstructionIndex.ILOAD_1:
                case InstructionIndex.ILOAD_2:
                case InstructionIndex.ILOAD_3:
                    frame.loadToStack(Integer.class,
                        opId - InstructionIndex.ILOAD_0);
                    break;
                
                    // Addly integer
                case InstructionIndex.IADD:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a + b);
                    }
                    break;
                
                    // AND integer
                case InstructionIndex.IAND:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a & b);
                    }
                    break;
                
                    // Divide integer
                case InstructionIndex.IDIV:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a / b);
                    }
                    break;
                
                    // Multiply integer
                case InstructionIndex.IMUL:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a * b);
                    }
                    break;
                
                    // Negate integer
                case InstructionIndex.INEG:
                    {
                        int a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(-a);
                    }
                    break;
                    
                    // Is the given object an instance of the given class?
                case InstructionIndex.INSTANCEOF:
                    {
                        // Check against this
                        SpringClass as = this.resolveClass(inst.
                            <ClassName>argument(0, ClassName.class));
                        
                        SpringClass vtype = frame.<SpringObject>popFromStack(
                            SpringObject.class).type();
                        frame.pushToStack((vtype != null &&
                            as.isAssignableFrom(vtype) ? 1 : 0));
                    }
                    break;
                    
                    // Invoke interface method
                case InstructionIndex.INVOKEINTERFACE:
                    // Verbose debug?
                    if (this.verboseCheck(VerboseDebugFlag.METHOD_ENTRY))
                        this.verboseEmit("Interface: %s", inst);
                
                    this.__vmInvokeInterface(inst, thread, frame);
                    
                    // Exception to be handled?
                    if (this.__checkException())
                        return;
                    break;
                    
                    // Invoke special method (constructor, superclass,
                    // or private)
                case InstructionIndex.INVOKESPECIAL:
                    // Verbose debug?
                    if (this.verboseCheck(VerboseDebugFlag.METHOD_ENTRY))
                        this.verboseEmit("Special: %s", inst);
                    
                    this.__vmInvokeSpecial(inst, thread, frame);
                    
                    // Exception to be handled?
                    if (this.__checkException())
                        return;
                    break;
                    
                    // Invoke static method
                case InstructionIndex.INVOKESTATIC:
                    // Verbose debug?
                    if (this.verboseCheck(VerboseDebugFlag.METHOD_ENTRY |
                            VerboseDebugFlag.INVOKE_STATIC))
                        this.verboseEmit("Static: %s", inst);
                    
                    this.__vmInvokeStatic(inst, thread, frame);
                    
                    // Exception to be handled?
                    if (this.__checkException())
                        return;
                    break;
                    
                    // Invoke virtual method
                case InstructionIndex.INVOKEVIRTUAL:
                    // Verbose debug?
                    if (this.verboseCheck(VerboseDebugFlag.METHOD_ENTRY))
                        this.verboseEmit("Virtual: %s", inst);
                    
                    this.__vmInvokeVirtual(inst, thread, frame);
                    
                    // Exception to be handled?
                    if (this.__checkException())
                        return;
                    break;
                
                    // OR integer
                case InstructionIndex.IOR:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a | b);
                    }
                    break;
                
                    // Remainder integer
                case InstructionIndex.IREM:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a % b);
                    }
                    break;
                    
                    // Return integer
                case InstructionIndex.IRETURN:
                    this.__vmReturn(thread,
                        frame.<Integer>popFromStack(Integer.class));
                    nextPc = Integer.MIN_VALUE;
                    break;
                
                    // Shift left integer
                case InstructionIndex.ISHL:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a << (b & 0x1F));
                    }
                    break;
                
                    // Shift right integer
                case InstructionIndex.ISHR:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a >> (b & 0x1F));
                    }
                    break;
                    
                    // Store integer to local variable
                case InstructionIndex.ISTORE:
                case InstructionIndex.WIDE_ISTORE:
                    frame.storeLocal(inst.<Integer>argument(0, Integer.class),
                        frame.<Integer>popFromStack(Integer.class));
                    break;
                    
                    // Store integer to local variable
                case InstructionIndex.ISTORE_0:
                case InstructionIndex.ISTORE_1:
                case InstructionIndex.ISTORE_2:
                case InstructionIndex.ISTORE_3:
                    frame.storeLocal(opId - InstructionIndex.ISTORE_0,
                        frame.<Integer>popFromStack(Integer.class));
                    break;
                
                    // Subtract integer
                case InstructionIndex.ISUB:
                    {
                        Integer b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a - b);
                    }
                    break;
                
                    // Unsigned shift right integer
                case InstructionIndex.IUSHR:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a >>> (b & 0x1F));
                    }
                    break;
                
                    // XOR integer
                case InstructionIndex.IXOR:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class),
                            a = frame.<Integer>popFromStack(Integer.class);
                        frame.pushToStack(a ^ b);
                    }
                    break;
                    
                    // Long to double
                case InstructionIndex.L2D:
                    {
                        long value = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(Double.valueOf((double)value));
                    }
                    break;
                    
                    // Long to float
                case InstructionIndex.L2F:
                    {
                        long value = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(Float.valueOf((float)value));
                    }
                    break;
                    
                    // Long to integer
                case InstructionIndex.L2I:
                    {
                        long value = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(Integer.valueOf((int)value));
                    }
                    break;
                    
                    // Add long
                case InstructionIndex.LADD:
                    {
                        long b = frame.<Long>popFromStack(Long.class),
                            a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a + b);
                    }
                    break;
                
                    // And long
                case InstructionIndex.LAND:
                    {
                        long b = frame.<Long>popFromStack(Long.class),
                            a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a & b);
                    }
                    break;
                
                    // Compare long
                case InstructionIndex.LCMP:
                    {
                        long b = frame.<Long>popFromStack(Long.class),
                            a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack((a < b ? -1 : (a > b ? 1 : 0)));
                    }
                    break;
                    
                    // Long constant
                case InstructionIndex.LCONST_0:
                case InstructionIndex.LCONST_1:
                    frame.pushToStack(Long.valueOf(
                        (opId - InstructionIndex.LCONST_0)));
                    break;
                    
                    // Load from constant pool, push to the stack
                case InstructionIndex.LDC:
                case InstructionIndex.LDC_W:
                    {
                        ConstantValue value = inst.<ConstantValue>argument(0,
                            ConstantValue.class);
                        
                        // Pushing a string, which due to the rules of Java
                        // there must always be an equality (==) between two
                        // strings, so "foo" == "foo" must be true even if it
                        // is in different parts of the code
                        // Additionally internall class objects are adapted
                        // too as needed
                        if (value instanceof ConstantValueString ||
                            value instanceof ConstantValueClass)
                            frame.pushToStack(this.asVMObject(value));
                        
                        // This will be pre-boxed so push it to the stack
                        else
                            frame.pushToStack(value.boxedValue());
                    }
                    break;
                    
                    // Load long or double from constant pool, to the stack
                case InstructionIndex.LDC2_W:
                    frame.pushToStack(inst.<ConstantValue>argument(0,
                        ConstantValue.class).boxedValue());
                    break;
                
                    // Divide long
                case InstructionIndex.LDIV:
                    {
                        long b = frame.<Long>popFromStack(Long.class),
                            a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a / b);
                    }
                    break;
                    
                    // Load integer from local variable
                case InstructionIndex.LLOAD:
                case InstructionIndex.WIDE_LLOAD:
                    frame.loadToStack(Long.class,
                        inst.<Integer>argument(0, Integer.class));
                    break;
                    
                    // Load integer from local variable
                case InstructionIndex.LLOAD_0:
                case InstructionIndex.LLOAD_1:
                case InstructionIndex.LLOAD_2:
                case InstructionIndex.LLOAD_3:
                    frame.loadToStack(Long.class,
                        opId - InstructionIndex.LLOAD_0);
                    break;
                    
                    // Multiply long
                case InstructionIndex.LMUL:
                    {
                        long b = frame.<Long>popFromStack(Long.class),
                            a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a * b);
                    }
                    break;
                
                    // Negate long
                case InstructionIndex.LNEG:
                    {
                        long a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(-a);
                    }
                    break;
                    
                    // OR long
                case InstructionIndex.LOR:
                    {
                        long b = frame.<Long>popFromStack(Long.class),
                            a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a | b);
                    }
                    break;
                    
                    // Subtract long
                case InstructionIndex.LSUB:
                    {
                        long b = frame.<Long>popFromStack(Long.class),
                            a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a - b);
                    }
                    break;
                    
                    // Lookup in a jump table
                case InstructionIndex.LOOKUPSWITCH:
                case InstructionIndex.TABLESWITCH:
                    nextPc = inst.<IntMatchingJumpTable>argument(0,
                        IntMatchingJumpTable.class).match(
                        frame.<Integer>popFromStack(Integer.class)).target();
                    break;
                
                    // Remainder long
                case InstructionIndex.LREM:
                    {
                        long b = frame.<Long>popFromStack(Long.class),
                            a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a % b);
                    }
                    break;
                    
                    // Return long
                case InstructionIndex.LRETURN:
                    this.__vmReturn(thread,
                        frame.<Long>popFromStack(Long.class));
                    nextPc = Integer.MIN_VALUE;
                    break;
                
                    // Shift left long
                case InstructionIndex.LSHL:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class);
                        long a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a << (((long)b) & 0x3F));
                    }
                    break;
                
                    // Shift right long
                case InstructionIndex.LSHR:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class);
                        long a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a >> (((long)b) & 0x3F));
                    }
                    break;
                    
                    // Store long to local variable
                case InstructionIndex.LSTORE:
                case InstructionIndex.WIDE_LSTORE:
                    frame.storeLocal(inst.<Integer>argument(0, Integer.class),
                        frame.<Long>popFromStack(Long.class));
                    break;
                    
                    // Store long to local variable
                case InstructionIndex.LSTORE_0:
                case InstructionIndex.LSTORE_1:
                case InstructionIndex.LSTORE_2:
                case InstructionIndex.LSTORE_3:
                    frame.storeLocal(opId - InstructionIndex.LSTORE_0,
                        frame.<Long>popFromStack(Long.class));
                    break;
                
                    // Unsigned shift right long
                case InstructionIndex.LUSHR:
                    {
                        int b = frame.<Integer>popFromStack(Integer.class);
                        long a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a >>> (((long)b) & 0x3F));
                    }
                    break;
                    
                    // XOR long
                case InstructionIndex.LXOR:
                    {
                        long b = frame.<Long>popFromStack(Long.class),
                            a = frame.<Long>popFromStack(Long.class);
                        frame.pushToStack(a ^ b);
                    }
                    break;
                    
                    // Enter monitor
                case InstructionIndex.MONITORENTER:
                    {
                        SpringObject object = frame.
                            <SpringObject>popFromStack(SpringObject.class);
                        
                        // Verbose debug?
                        if (this.verboseCheck(VerboseDebugFlag.MONITOR_ENTER))
                            this.verboseEmit(
                                "Monitor Enter: %s on %s",
                                object, thread);
                        
                        object.monitor().enter(thread);
                    }
                    break;
                    
                    // Exit monitor
                case InstructionIndex.MONITOREXIT:
                    {
                        SpringObject object = frame.
                            <SpringObject>popFromStack(SpringObject.class);
                        
                        // Verbose debug?
                        if (this.verboseCheck(VerboseDebugFlag.MONITOR_EXIT))
                            this.verboseEmit(
                                "Monitor Exit: %s on %s",
                                object, thread);
                        
                        object.monitor().exit(thread, true);
                    }
                    break;
                    
                    // Allocate multi-dimensional array
                case InstructionIndex.MULTIANEWARRAY:
                    {
                        // Determine component type and dimension count
                        SpringClass ccl = this.resolveClass(
                            inst.<ClassName>argument(0, ClassName.class));
                        int n = inst.<Integer>argument(1, Integer.class);
                        
                        // Pop values into array
                        int[] pops = new int[n];
                        for (int i = n - 1; i >= 0; i--)
                            pops[i] = frame.<Integer>popFromStack(
                                Integer.class);
                        
                        // Call method within the class library since it is
                        // easier, because this is one super complex
                        // instruction
                        Object rv = this.invokeMethod(true,
                            new ClassName(
                                "cc/squirreljme/runtime/cldc/lang" +
                                 "/ArrayUtils"),
                            new MethodNameAndType("multiANewArray",
                                "(Ljava/lang/Class;I[I)Ljava/lang/Object;"),
                            this.asVMObject(ccl), 0,
                            this.asVMObject(pops));
                        
                        // Did this call fail?
                        if (rv instanceof MethodInvokeException)
                        {
                            // Emit the exception
                            ((MethodInvokeException)rv).printStackTrace();
                            ((MethodInvokeException)rv).printVmTrace(
                                System.err);
                            
                            // Toss it, due to the failure
                            frame.tossException(
                                ((MethodInvokeException)rv).exception);
                        }
                        
                        // Otherwise push the result to the stack
                        else
                            frame.pushToStack(rv);
                        
                        // Exception to be handled?
                        if (this.__checkException())
                            return;
                    }
                    break;
                    
                    // Allocate new object
                case InstructionIndex.NEW:
                    this.__vmNew(inst, frame);
                    break;
                
                    // Allocate new primitive array
                case InstructionIndex.NEWARRAY:
                    frame.pushToStack(this.allocateArray(this.resolveClass(
                        ClassName.fromPrimitiveType(
                        inst.<PrimitiveType>argument(0,
                            PrimitiveType.class)).addDimensions(1)),
                        frame.<Integer>popFromStack(Integer.class)));
                    break;
                    
                    // Return from method with no return value
                case InstructionIndex.RETURN:
                    this.__vmReturn(thread, null);
                    break;
                    
                    // Pop category 1 value
                case InstructionIndex.POP:
                    {
                        /* {@squirreljme.error BK2q Cannot pop category two
                        value from stack.} */
                        Object val = frame.popFromStack();
                        if (val instanceof Long || val instanceof Double)
                            throw new SpringVirtualMachineException("BK2q");
                    }
                    break;
                    
                    // Pop two cat1s or one cat2
                case InstructionIndex.POP2:
                    {
                        // Pop one value, if it is a long or double then only
                        // pop one
                        Object val = frame.popFromStack();
                        if (!(val instanceof Long || val instanceof Double))
                        {
                            /* {@squirreljme.error BK2r Cannot pop a category
                            one then category two type.} */
                            val = frame.popFromStack();
                            if (val instanceof Long || val instanceof Double)
                                throw new SpringVirtualMachineException(
                                    "BK2r");
                        }
                    }
                    break;
                    
                    // Put to instance field
                case InstructionIndex.PUTFIELD:
                    {
                        // Lookup field
                        SpringField ssf = this.__lookupInstanceField(
                            inst.<FieldReference>argument(0,
                            FieldReference.class));
                        
                        // Pop the value and the object to mess with
                        Object value = frame.popFromStack();
                        SpringObject ref = frame.<SpringObject>popFromStack(
                            SpringObject.class);
                        
                        /* {@squirreljme.error BK2s Cannot store value into
                        null reference.} */
                        if (ref == SpringNullObject.NULL)
                            throw new SpringNullPointerException("BK2s");
                        
                        /* {@squirreljme.error BK2t Cannot store value into
                        this instance because it not a simple object.} */
                        if (!(ref instanceof SpringSimpleObject))
                            throw new SpringIncompatibleClassChangeException(
                                "BK2t");
                        SpringSimpleObject sso = (SpringSimpleObject)ref;
                        
                        /* {@squirreljme.error BK2u Cannot store value into
                        a field which belongs to another class.} */
                        if (!this.loadClass(ssf.inClass()).isAssignableFrom(
                            sso.type()))
                            throw new SpringClassCastException("BK2u");
                        
                        // Debug signal
                        if (jdwp != null && ssf.isDebugWatching(true))
                            try (JDWPHostValue jVal = jdwp.value())
                            {
                                jVal.set(
                                    DebugViewObject.__normalizeNull(value));
                                jdwp.trip(JDWPTripField.class,
                                    JDWPGlobalTrip.FIELD).field(thread,
                                        this.loadClass(ssf.inclass),
                                        ssf.index, true, ref, jVal);
                            }
                        
                        // Set
                        SpringFieldStorage store =
                            sso.fieldByIndex(ssf.index());
                        store.set(value, isinstanceinit);
                    }
                    break;
                
                    // Put to static field
                case InstructionIndex.PUTSTATIC:
                    {
                        // Lookup field
                        FieldReference fieldRef =
                            inst.<FieldReference>argument(0,
                                FieldReference.class);
                        SpringField[] field = new SpringField[1];
                        SpringFieldStorage ssf = this.__lookupStaticField(
                            fieldRef, field);
                        
                        // Read value
                        Object value = frame.popFromStack();
                        
                        // Debug signal
                        if (jdwp != null &&
                            field[0].isDebugWatching(true))
                            try (JDWPHostValue jVal = jdwp.value())
                            {
                                jVal.set(
                                    DebugViewObject.__normalizeNull(value));
                                jdwp.trip(JDWPTripField.class,
                                    JDWPGlobalTrip.FIELD).field(thread,
                                        this.loadClass(ssf.inclass),
                                        ssf.fieldIndex, true,
                                        null, jVal);
                            }
                        
                        // Set value, note that static initializers can set
                        // static field values even if they are final
                        ssf.set(value, isstaticinit);
                    }
                    break;
                    
                    // Swap top two cat1 stack entries
                case InstructionIndex.SWAP:
                    {
                        Object v1 = frame.popFromStack(),
                            v2 = frame.popFromStack();
                        
                        /* {@squirreljme.error BK2v Cannot swap category
                        two types.} */
                        if (v1 instanceof Long || v1 instanceof Double ||
                            v2 instanceof Long || v2 instanceof Double)
                            throw new SpringClassCastException("BK2v");
                        
                        frame.pushToStack(v1);
                        frame.pushToStack(v2);
                    }
                    break;
                
                    /* {@squirreljme.error BK2w Reserved instruction. (The
                    instruction)} */
                case InstructionIndex.BREAKPOINT:
                case InstructionIndex.IMPDEP1:
                case InstructionIndex.IMPDEP2:
                    throw new SpringVirtualMachineException(String.format(
                        "BK2w %s", inst));
                    
                    /* {@squirreljme.error BK2x Unimplemented operation.
                    (The instruction)} */
                default:
                    throw new SpringVirtualMachineException(String.format(
                        "BK2x %s", inst));
            }
        }
        
        // Arithmetic exception, a divide by zero happened somewhere
        catch (ArithmeticException e)
        {
            // PC converts?
            nextPc = this.__handleException(
                (SpringObject)this.asVMObject(new SpringArithmeticException(
                e.getMessage())));
            
            // Do not set PC address?
            if (nextPc < 0)
                return;
        }
        
        // Use the original exception, just add a suppression note on it since
        // that is the simplest action
        catch (SpringException e)
        {
            // Verbose debug?
            if (this.verboseCheck(VerboseDebugFlag.VM_EXCEPTION))
            {
                this.verboseEmit("-------------------------------");
                this.verboseEmit("Exception, %s: %s",
                    e.getClass().getName(), e.getMessage());
                
                e.printStackTrace();
                
                this.verboseEmit("-------------------------------");
            }
            
            // Do not add causes or do anything if this was already thrown
            if ((e instanceof SpringFatalException) ||
                (e instanceof SpringMachineExitException))
                throw e;
            
            // Now the exception is either converted or tossed for failure
            // Is this a convertible exception on the VM?
            if (e instanceof SpringConvertableThrowable)
            {
                // PC converts?
                nextPc = this.__handleException(
                    (SpringObject)this.asVMObject(e));
                
                // Do not set PC address?
                if (nextPc < 0)
                    return;
            }
            
            // Not a wrapped exception, toss up higher which will kill the VM
            else
            {
                // Where is this located?
                SpringMethod inmethod = frame.method();
                ClassName inclassname = inmethod.inClass();
                SpringClass inclass = machine.classLoader().loadClass(
                    inclassname);
                
                // Location information if debugging is used, this makes it
                // easier to see exactly where failed code happened
                String onfile = inclass.file().sourceFile();
                int online = code.lineOfAddress(pc);
                
                /* {@squirreljme.error BK2y An exception was thrown in the
                virtual machine while executing the specified location.
                (The class; The method; The program counter; The file in
                source code, null means it is unknown; The line in source
                code, negative values are unknown; The instruction)} */
                e.addSuppressed(new SpringVirtualMachineException(
                    String.format("BK2y %s %s %d %s %d %s", inclassname,
                    inmethod.nameAndType(), pc, onfile, online, inst)));
                
                /* {@squirreljme.error BK2z Fatal VM exception.} */
                throw new SpringFatalException("BK2z", e);
            }
        }
        
        // Set implicit next PC address, if it has not been set or the next
        // address was actually changed
        if (nextPc != origNextPc || pc == frame.pc())
            frame.setPc(nextPc);
    }
    
    /**
     * Handles debug suspension and waiting.
     * 
     * @since 2022/08/28
     */
    private void __debugSuspension()
    {
        SpringThread thread = this.thread;
        
        // Disallow any kind of debug suspend, for example if this thread
        // is created by the debugger for certain tasks or running.
        if (thread.noDebugSuspend)
            return;
        
        JDWPHostController jdwp = this.machine.tasks.jdwpController;
        
        // This only returns while we are suspended, but if it returns
        // early then we were interrupted which means we need to signal
        // that to whatever is running
        boolean interrupted = false;
        JDWPHostThreadSuspension suspension = thread.debuggerSuspension;
        while (suspension.await(jdwp, thread))
        {
            interrupted = true;
        }
        
        // The debugger released suspension, so we can perform the
        // interrupt now
        if (interrupted)
            thread.hardInterrupt();
    }
    
    /**
     * Invokes a method in an interface.
     *
     * @param __i The instruction.
     * @param __t The current thread.
     * @param __f The current frame.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/19
     */
    private void __vmInvokeInterface(Instruction __i, SpringThread __t,
        SpringThreadFrame __f)
        throws NullPointerException
    {
        if (__i == null || __t == null || __f == null)
            throw new NullPointerException("NARG");
        
        MethodReference ref = __i.<MethodReference>argument(
            0, MethodReference.class);
        
        // Resolve the method reference
        SpringClass refclass = this.loadClass(ref.className());
        SpringMethod refmethod = refclass.lookupMethod(false,
            ref.memberNameAndType());
        
        /* {@squirreljme.error BK30 Could not access the target
        method for interface invoke. (The target method)} */
        if (!this.checkAccess(refmethod))
            throw new SpringIncompatibleClassChangeException(
                String.format("BK30 %s", ref));
        
        // Load arguments, includes the instance it acts on
        int nargs = refmethod.nameAndType().type().argumentCount() + 1;
        Object[] args = new Object[nargs];
        for (int i = nargs - 1; i >= 0; i--)
            args[i] = __f.popFromStack();
            
        /* {@squirreljme.error BK31 Instance object for interface invoke is
        null.} */
        SpringObject instance = (SpringObject)args[0];
        if (instance == null || instance == SpringNullObject.NULL)
            throw new SpringNullPointerException("BK31");
            
        /* {@squirreljme.error BK32 Cannot invoke the method in the object
        because it is of the wrong type. (The reference class; The class
        of the target object; The first argument)} */
        SpringClass objClass = instance.type();
        if (objClass == null || !refclass.isAssignableFrom(objClass))
            throw new SpringClassCastException(
                String.format("BK32 %s %s %s", refclass, objClass, args[0]));
                
        // Executing a proxy method?
        if (instance instanceof SpringProxyObject)
            this.__invokeProxy(ref.memberNameAndType(), args);
        
        // Re-lookup the method since we need to the right one! Then invoke it
        else
            this.__vmEnterFrame(objClass.lookupMethod(false, ref.memberNameAndType()), args);
    }
    
    /**
     * Performs a special invoke.
     *
     * @param __i The instruction.
     * @param __t The current thread.
     * @param __f The current frame.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/15
     */
    private void __vmInvokeSpecial(Instruction __i, SpringThread __t,
        SpringThreadFrame __f)
        throws NullPointerException
    {
        if (__i == null || __t == null || __f == null)
            throw new NullPointerException("NARG");
        
        MethodReference ref = __i.<MethodReference>argument(
            0, MethodReference.class);
        
        // Resolve the method reference
        SpringClass refClass = this.loadClass(ref.className());
        SpringMethod refMethod = refClass.lookupMethod(false,
            ref.memberNameAndType());
        
        /* {@squirreljme.error BK34 Could not access the target
        method for special invoke. (The target method)} */
        if (!this.checkAccess(refMethod))
            throw new SpringIncompatibleClassChangeException(
                String.format("BK34 %s", ref));
        
        // Load arguments
        int nargs = refMethod.nameAndType().type().
            argumentCount() + 1;
        Object[] args = new Object[nargs];
        for (int i = nargs - 1; i >= 0; i--)
            args[i] = __f.popFromStack();
        
        // Get the class of the current method being executed, lookup depends
        // on it
        SpringClass currentClass = this.loadClass(
            this.thread.currentFrame().method().inClass());
        
        /* {@squirreljme.error BK35 Instance object for special invoke is
        null.} */
        SpringObject onthis = (SpringObject)args[0];
        if (onthis == null || onthis == SpringNullObject.NULL)
            throw new SpringNullPointerException("BK35");
        
        // These modify the action to be performed
        boolean inSameClass = (currentClass == refClass);
        boolean inSuper = currentClass.isSuperClass(refClass);
        boolean isInit = refMethod.name().isInstanceInitializer();
        boolean isPrivate = refMethod.flags().isPrivate();
        boolean isPackagePrivate = refMethod.flags().isPackagePrivate();
        
        // Call superclass method instead?
        if ((!isPrivate && !isPackagePrivate) && inSuper && !isInit)
            try
            {
                refMethod = currentClass.superClass()
                    .lookupMethod(false, ref.memberNameAndType());
            }
            catch (SpringNoSuchMethodException e)
            {
                throw new SpringIncompatibleClassChangeException(
                    String.format("No ref %s from %s", ref, currentClass), e);
            }
        
        /* {@squirreljme.error BK36 Cannot call private method that is not
        in the same class. (The method reference; Our current class)} */
        else if ((isPrivate || (isPackagePrivate && !isInit)) &&
            !inSameClass && !inSuper)
            throw new SpringIncompatibleClassChangeException(
                String.format("BK36 %s %s", ref, currentClass));
        
        // Invoke this method
        this.__vmEnterFrame(refMethod, args);
    }
    
    /**
     * Performs a static invoke.
     *
     * @param __i The instruction.
     * @param __t The current thread.
     * @param __f The current frame.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/15
     */
    private void __vmInvokeStatic(Instruction __i, SpringThread __t,
        SpringThreadFrame __f)
        throws NullPointerException
    {
        if (__i == null || __t == null || __f == null)
            throw new NullPointerException("NARG");
        
        MethodReference ref = __i.<MethodReference>argument(
            0, MethodReference.class);
        
        // Resolve the method reference
        SpringClass refclass = this.loadClass(ref.className());
        SpringMethod refmethod = refclass.lookupMethod(true,
            ref.memberNameAndType());
        
        /* {@squirreljme.error BK37 Could not access the target
        method for static invoke. (The target method)} */
        if (!this.checkAccess(refmethod))
            throw new SpringIncompatibleClassChangeException(
                String.format("BK37 %s", ref));
        
        // Load arguments
        int nargs = refmethod.nameAndType().type().
            argumentCount();
        Object[] args = new Object[nargs];
        for (int i = nargs - 1; i >= 0; i--)
            args[i] = __f.popFromStack();
        
        // Virtualized native call, depends on what it is
        if (refmethod.flags().isNative())
        {
            // Add profiler point for native calls to track them there along
            // with being able to handle that
            ProfiledFrame pFrame = this.thread.profiler.enterFrame(
                ref.className().toString(),
                ref.memberName().toString(), ref.memberType().toString());
            
            // Current framer
            SpringThreadFrame currentFrame = this.thread.currentFrame();
            
            // Potential return value?
            MethodDescriptor type = ref.memberType();
            Object rv;
            
            // Now perform the actual call
            ProfiledFrame oldFrame = currentFrame._profiler;
            try
            {
                // Replace frame for tracking
                currentFrame._profiler = pFrame;
                
                // Perform call and get the result
                rv = this.nativeMethod(ref.className(),
                    ref.memberNameAndType(), args);
            }
            
            // Exit the profiler frame so it is no longer tracked
            finally
            {
                if (pFrame.inCallCount() > 0)
                    this.thread.profiler.exitFrame();
                
                // Restore old frame
                if (currentFrame._profiler == pFrame)
                    currentFrame._profiler = oldFrame;
            }
            
            // Push result to the stack, if there is one. This is done here
            // because this may cause other methods to be invoked
            if (type.hasReturnValue())
                __f.pushToStack(this.asVMObject(rv, true));
        }
        
        // Real code that exists in class file format
        else
            this.__vmEnterFrame(refmethod, args);
    }
    
    /**
     * Enters the given frame within the virtual machine.
     * 
     * @param __target The target method.
     * @param __args The arguments to the method.
     * @since 2022/02/28
     */
    private void __vmEnterFrame(SpringMethod __target, Object... __args)
    {
        // Perform the entry
        this.thread.enterFrame(__target, __args);
        
        // Send signal after we enter to indicate that we just went into
        // a method
        JDWPHostController jdwp = this.machine.tasks.jdwpController;
        if (jdwp != null)
        {
            // Signal that we went into a method
            jdwp.signal(this.thread, JDWPEventKind.METHOD_ENTRY);
            
            // Debugger may have stopped here
            this.__debugSuspension();
        }
    }
    
    /**
     * Performs a virtual invoke.
     *
     * @param __i The instruction.
     * @param __t The current thread.
     * @param __f The current frame.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/16
     */
    private void __vmInvokeVirtual(Instruction __i, SpringThread __t,
        SpringThreadFrame __f)
        throws NullPointerException
    {
        if (__i == null || __t == null || __f == null)
            throw new NullPointerException("NARG");
        
        MethodReference ref = __i.<MethodReference>argument(
            0, MethodReference.class);
        
        // Resolve the method reference
        SpringClass refclass = this.loadClass(ref.className());
        SpringMethod refmethod = refclass.lookupMethod(false,
            ref.memberNameAndType());
        
        /* {@squirreljme.error BK38 Could not access the target
        method for virtual invoke. (The target method)} */
        if (!this.checkAccess(refmethod))
            throw new SpringIncompatibleClassChangeException(
                String.format("BK38 %s", ref));
        
        // Load arguments, includes the instance it acts on
        int nargs = refmethod.nameAndType().type().argumentCount() + 1;
        Object[] args = new Object[nargs];
        for (int i = nargs - 1; i >= 0; i--)
            args[i] = __f.popFromStack();
        
        /* {@squirreljme.error BK39 Instance object for virtual invoke is
        null.} */
        SpringObject instance = (SpringObject)args[0];
        if (instance == null || instance == SpringNullObject.NULL)
            throw new SpringNullPointerException("BK39");
        
        // Re-resolve method for this object's class
        refmethod = instance.type().lookupMethod(false,
            ref.memberNameAndType());
        
        // Calling onto a proxy?
        if (instance instanceof SpringProxyObject)
            this.__invokeProxy(refmethod.nameAndType(), args);
        
        // Enter frame as like a static method
        else
            this.__vmEnterFrame(refmethod, args);
    }
    
    /**
     * Allocates a new instance of the given object, it is not initialized just
     * allocated.
     *
     * @param __i The instruction.
     * @param __f The current frame.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/15
     */
    private void __vmNew(Instruction __i, SpringThreadFrame __f)
        throws NullPointerException
    {
        if (__i == null || __f == null)
            throw new NullPointerException("NARG");
        
        // Lookup class we want to allocate
        ClassName allocName;
        SpringClass toAlloc = this.loadClass((allocName =
            __i.<ClassName>argument(0, ClassName.class)));
        
        /* {@squirreljme.error BK3a Cannot allocate an instance of the given
        class because it cannot be accessed. (The class to allocate)} */
        if (!this.checkAccess(toAlloc))
            throw new SpringIncompatibleClassChangeException(
                String.format("BK3a %s", allocName));
        
        // Push a new allocation to the stack
        __f.pushToStack(this.allocateObject(toAlloc));
    }
    
    /**
     * Returns from the top-most frame then pushes the return value to the
     * parent frame's stack (if any).
     *
     * @param __thread The thread to return in.
     * @param __value The value to push.
     * @throws NullPointerException On null arguments.
     * @since 2018/09/16
     */
    private void __vmReturn(SpringThread __thread, Object __value)
        throws NullPointerException
    {
        if (__thread == null)
            throw new NullPointerException("NARG");
        
        // Indicate exit with return value
        JDWPHostController jdwp = this.machine.tasks.jdwpController;
        if (jdwp != null)
        {
            // Signal that method exited
            if (__value == null)
                jdwp.signal(__thread, JDWPEventKind.METHOD_EXIT);
            else
                jdwp.signal(__thread, JDWPEventKind.METHOD_EXIT_WITH_RETURN_VALUE,
                    __value);
            
            // Debugger may have stopped here
            this.__debugSuspension();
        }
        
        // Pop our current frame
        SpringThreadFrame old = __thread.popFrame();
        old.setPc(Integer.MIN_VALUE);
            
        // Verbose debug?
        if (this.verboseCheck(VerboseDebugFlag.METHOD_EXIT))
            this.verboseEmit("Exiting frame.");
        
        // Push the value to the current frame
        if (__value != null)
        {
            SpringThreadFrame cur = __thread.currentFrame();
            if (cur != null)
                cur.pushToStack(__value);
        }
        
        /*System.err.printf("+++RETURN: %s%n", __value);
        __thread.printStackTrace(System.err);*/
    }
}