# Path: pyjvm/bytecode.py
# def bytecode(code):
#     def cl(func):
#         BYTECODE[hex(code)] = func
#         return func
# 
#     return cl
# 
# Path: pyjvm/jassert.py
# def jassert_ref(ref):
#     assert ref is None or (type(ref) is tuple and ref[0] in ("ref", "vm_ref"))
# 
# Path: pyjvm/thread.py
# class SkipThreadCycle(Exception):
#     '''Thread may skip his execution quota in case when a monitor
#     is busy or sleep was called
#     '''
#     pass
# 
# Path: pyjvm/utils.py
# def category_type(value):
#     '''Get category type of a variable according to jdk specs
# 
#     long, double are 2, others are 1'''
#     if type(value) is tuple and value[0] in ('long', 'double'):
#         return 2
#     else:
#         return 1


import struct
from pyjvm.bytecode import bytecode
from pyjvm.jassert import jassert_ref
from pyjvm.thread import SkipThreadCycle
from pyjvm.utils import category_type

@bytecode(code=0xba)
def invokedynamic(frame):
    raise Exception("Method handlers are not supported")


@bytecode(code=0xca)
def breakpoint(frame):
    raise Exception("This op code (fe) should not present in class file")


@bytecode(code=0xc2)
def monitorenter(frame):
    ref = frame.stack.pop()
    jassert_ref(ref)
    o = frame.vm.heap[ref[1]]
    if "@monitor" in o.fields:
        if o.fields["@monitor"] == frame.thread:
            o.fields["@monitor_count"] += 1
        else:
            frame.stack.append(ref)
            raise SkipThreadCycle()
    else:
        o.fields["@monitor"] = frame.thread
        o.fields["@monitor_count"] = 1


@bytecode(code=0xc3)
def monitorexit(frame):
    ref = frame.stack.pop()

# Path: pyjvm/bytecode.py
# def bytecode(code):
#     def cl(func):
#         BYTECODE[hex(code)] = func
#         return func
# 
#     return cl
# 
# Path: pyjvm/jassert.py
# def jassert_ref(ref):
#     assert ref is None or (type(ref) is tuple and ref[0] in ("ref", "vm_ref"))
# 
# Path: pyjvm/thread.py
# class SkipThreadCycle(Exception):
#     '''Thread may skip his execution quota in case when a monitor
#     is busy or sleep was called
#     '''
#     pass
# 
# Path: pyjvm/utils.py
# def category_type(value):
#     '''Get category type of a variable according to jdk specs
# 
#     long, double are 2, others are 1'''
#     if type(value) is tuple and value[0] in ('long', 'double'):
#         return 2
#     else:
#         return 1


# Path: pyjvm/ops/ops_misc.py
import struct
from pyjvm.bytecode import bytecode
from pyjvm.jassert import jassert_ref
from pyjvm.thread import SkipThreadCycle
from pyjvm.utils import category_type


@bytecode(code=0xba)
def invokedynamic(frame):
    raise Exception("Method handlers are not supported")


@bytecode(code=0xca)
def breakpoint(frame):
    raise Exception("This op code (fe) should not present in class file")


@bytecode(code=0xc2)
def monitorenter(frame):
    ref = frame.stack.pop()
    jassert_ref(ref)
    o = frame.vm.heap[ref[1]]
    if "@monitor" in o.fields:
        if o.fields["@monitor"] == frame.thread:
            o.fields["@monitor_count"] += 1
        else:
            frame.stack.append(ref)
            raise SkipThreadCycle()
    else:
        o.fields["@monitor"] = frame.thread
        o.fields["@monitor_count"] = 1


@bytecode(code=0xc3)
def monitorexit(frame):
    ref = frame.stack.pop()

    jassert_ref(ref)