/*
 * Licensed Materials - Property of IBM
 * IBM Developer Kit, Java(TM) Tech Edition
 * (c) Copyright IBM Corp. 1996, 1999. All rights reserved.
 *
 * US Government Users Restricted Rights - Use,
 * duplication or disclosure restricted by GSA
 * ADP Schedule Contract with IBM Corp.
 */
/*
 * @(#)interpreter.h    1.121 98/07/14
 *
 * Copyright 1995-1998 by Sun Microsystems, Inc.,
 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
 * All rights reserved.
 *
 */

/*
 * Definitions for the interpreter      6/27/91
 */

#ifndef _INTERPRETER_H_
#define _INTERPRETER_H_

#ifdef IBM_AIX								/* ibm.10283 */
#define AIX_HEAP_GROWTH
#endif									/* ibm.10283 */

#if defined(IBM_INTEL) && defined(IBM_FASTSWEEP)			/*ibm.8904*/
#define COMPACTION_AVOIDANCE
#endif									/*ibm.8904*/

#ifndef IBM4690_INCLUDES_P5                     /*ibm.7717*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif //!IBM4690_INCLUDES_P5           /*ibm.7717*/

#include "bool.h"
#include "config.h"
#include "jni.h"
#include "alloc_cache.h"

extern char *progname;
extern bool_t debugging;
extern bool_t verbose;
extern bool_t verbosegc;
#ifdef JMS_TRL
extern bool_t verbosemongc;
extern bool_t compactgc;
#endif
extern bool_t noasyncgc;
extern bool_t classgc;

extern ClassClass *classJavaLangClass;     /* class java/lang/Class */
extern ClassClass *classJavaLangObject;    /* class java/lang/Object */
extern ClassClass *classJavaLangString;    /* class java/lang/String */

extern ClassClass *classJavaLangThrowable;
extern ClassClass *classJavaLangException;
extern ClassClass *classJavaLangError;
extern ClassClass *classJavaLangRuntimeException;
extern ClassClass *classJavaLangThreadDeath;

extern ClassClass *interfaceJavaLangCloneable; /* class java/lang/Cloneable */
extern ClassClass *interfaceJavaIoSerializable; /* class java/io/Serializable */

enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL };

extern int verifyclasses;

#define FINALIZER_METHOD_NAME "finalize"
#define FINALIZER_METHOD_SIGNATURE "()V"

#ifdef TRACING
  extern int trace;
  extern int tracem;
  extern void trace_method(struct execenv*, struct methodblock*, int, int);
  enum { TRACE_METHOD_ENTER, TRACE_METHOD_RETURN, TRACE_METHOD_NATIVE_RETURN };

#ifdef JOVATION                                                         /*ibm.6780*/
  extern bool_t javation;
# define TRACE_METHOD(ee, mb, args_size, type) \
      if (tracem && !javation) trace_method(ee, mb, args_size, type); else
# define TRACE_ENTER(ee, mb, o) \
        if (tracem && javation) trace_enter(ee, mb, o); else
# define TRACE_LEAVE(ee, mb, o) \
        if (tracem && javation) trace_leave(ee, mb, o); else
  extern void trace_enter(struct execenv*, struct methodblock*, HObject*);
  extern void trace_leave(struct execenv*, struct methodblock*, HObject*);

# define TRACE_GC(o) ( (tracem && javation) ? trace_gc(o) : 0)
# define TRACE_CLASS(db) ( (tracem && javation) ? trace_class(db) :0)

#else                                                                   /*ibm.6780*/
# define TRACE_METHOD(ee, mb, args_size, type) \
      if (tracem) trace_method(ee, mb, args_size, type); else
#endif                                                                  /*ibm.6780*/

#else
# define trace  0
# define tracem 0
# define TRACE_METHOD(ee, mb, args_size, type)
#endif

extern char * const opnames[];

/* Get a constant pool index, from a pc */
#define GET_INDEX(ptr) (((int)((ptr)[0]) << 8) | (ptr)[1])

extern char *Object2CString(JHandle *);

#ifdef JMS_TRL
/*
 * [TRL] TRL Java Memory System
 */
#define METHOD_FLAG_BITS 5
#define FLAG_MASK       ((1<<METHOD_FLAG_BITS)-1)  /* valid flag bits */
#define METHOD_MASK     (~FLAG_MASK)  /* valid mtable ptr bits */
#define LENGTH_MASK     METHOD_MASK

/*
       10987654321098765432109876543210
       ttttthhhhhhhhhhhhhhhhhhhhhhhhN-H

        ttttt                      typecode
        hhhhhhhhhhhhhhhhhhhhhhhh   hashcore
        A                          array or normal
        -
        H                          hash or monitor pointer
 */


#define obj_length(o)   ((unsigned long) (o)->methods)

#define OBJ_TYPECODE         5
#ifdef MON_FLAT
#define OBJ_TYPECODE_SHIFT  (8-OBJ_TYPECODE)
#define OBJ_TYPECODE_MASK ((1<<OBJ_TYPECODE)-1)
#else
#define OBJ_TYPECODE_SHIFT  (32-OBJ_TYPECODE)
#define OBJ_TYPEMASK        ((1<<OBJ_TYPECODE_SHIFT)-1)
#endif


#define OBJ_IsArray  0x02 /* Whether it is an array */
#ifndef MON_FLAT /* ibm.3740 */
#define OBJ_MONMASK  0x03
#define OBJ_IsHash   0x01 /* Whether it is a hash value or a monitor pointer */
#endif /* ibm.3740 */

#ifdef MON_FLAT
#define OBJ_HashedAndMoved 0x04 /* The object has been hashed, and moved */
#define OBJ_Hashed   0x01 /* Whether the object has been hashed-upon */
#define is_normal_object(o)     (((o)->locknflags & OBJ_IsArray)==0)

#define obj_flags(o)    (((o)->locknflags >> OBJ_TYPECODE_SHIFT) & OBJ_TYPECODE_MASK)
#define obj_array_flags(o)    obj_flags(o)
#define obj_makelocknflags(type,array) \
         ((((type)&OBJ_TYPECODE_MASK)<<OBJ_TYPECODE_SHIFT) | (array))
#else
#define is_normal_object(o)     (((o)->hash & OBJ_IsArray)==0)

#define obj_flags(o)    ((o)->hash >> OBJ_TYPECODE_SHIFT)
#define obj_array_flags(o)    obj_flags(o)
#endif /* MON_FLAT */

#ifdef IBM_HAIFA_GC                                             /*ibm.4860*/
#define jms_ee2thr(ee) \
     ((ee)->thread ? (sys_thread_t*)(THREAD((ee)->thread)->PrivateInfo) : 0)
#endif /* IBM_HAIFA_GC */                                       /*ibm.4860*/

#define obj_makehash(type,hash,array) \
         (((type)<<OBJ_TYPECODE_SHIFT) | ((hash) & OBJ_TYPEMASK) | (array))

#define obj_methodtable(obj) ((obj)->methods)
#define obj_classblock(obj) ((obj)->methods->classdescriptor)

#define obj_array_methodtable(obj) \
    (is_normal_object(obj) ? obj_methodtable(obj)      \
                           : cbMethodTable(classJavaLangObject))
#define obj_array_classblock(obj) \
    (is_normal_object(obj) ? (obj)->methods->classdescriptor \
                           : classJavaLangObject)

#ifdef MON_FLAT
#define IntrinsicSize(__obj,__rv__)                                                             \
        do {                                                                                        \
      JHandle *__obj__ = (__obj);                                                               \
      if (is_normal_object (__obj__)) {                                                         \
                ClassClass *__cb__ = obj_classblock (__obj__);                                          \
        (__rv__) = cbInstanceSize(__cb__) + (cbFinalizer(__cb__) ? sizeof(finalizer_t) : 0);    \
          } else {                                                                                  \
                unsigned int __tc__ = obj_flags (__obj__);                                              \
                if (__tc__ == T_CLASS) {                                                                \
                  (__rv__) = sizearray (__tc__,(int) obj_methodtable (__obj__)) + sizeof (OBJECT);            \
                } else {                                                                                \
                  (__rv__) = sizearray (__tc__,(int) obj_methodtable (__obj__));                              \
                }                                                                                       \
          }                                                                                         \
        } while (0)

#define InitialSize(__obj,__rv__)                                                               \
        do {                                                                                        \
      int __intrinsicsize__;                                                                    \
          IntrinsicSize (__obj,__intrinsicsize__);                                                  \
          (__rv__) = (__intrinsicsize__ + HEADER_SIZE + (OBJECTGRAIN - 1)) & ~(OBJECTGRAIN - 1);    \
        } while (0)

#define HashedMovedSize(__obj,__rv__)                                                           \
        do {                                                                                        \
      int __intrinsicsize__;                                                                    \
          IntrinsicSize (__obj,__intrinsicsize__);                                                  \
          __intrinsicsize__ += sizeof (unsigned long);                                              \
          (__rv__) = (__intrinsicsize__ + HEADER_SIZE + (OBJECTGRAIN - 1)) & ~(OBJECTGRAIN - 1);    \
        } while (0)
#endif /* MON_FLAT */

#else /* SUN JDK */
#define METHOD_FLAG_BITS 5
#define FLAG_MASK       ((1<<METHOD_FLAG_BITS)-1)  /* valid flag bits */
#define METHOD_MASK     (~FLAG_MASK)  /* valid mtable ptr bits */
#define LENGTH_MASK     METHOD_MASK

#define obj_flags(o) \
    (((unsigned long) (o)->methods) & FLAG_MASK)
#define obj_length(o)   \
    (((unsigned long) (o)->methods) >> METHOD_FLAG_BITS)

#define mkatype(t,l) ((struct methodtable *) (((l) << METHOD_FLAG_BITS)|(t)))
#define atype(m) ((m) & FLAG_MASK)


#define obj_methodtable(obj) ((obj)->methods)
#define obj_classblock(obj) ((obj)->methods->classdescriptor)

#define obj_array_methodtable(obj) \
    ((obj_flags((obj)) == T_NORMAL_OBJECT) ? obj_methodtable((obj))      \
                                           : cbMethodTable(classJavaLangObject))
#define obj_array_classblock(obj) \
    ((obj_flags((obj)) == T_NORMAL_OBJECT) ? (obj)->methods->classdescriptor \
                                           : classJavaLangObject)

#endif /* JMS_TRL */

#define mt_slot(methodtable, slot) (methodtable)->methods[slot]

#define uobj_getslot(o, slot) (o)[slot]
#define uobj_setslot(o, slot, v) (uobj_getslot(o, slot) = (v))

#define obj_getslot(o, slot) uobj_getslot(unhand(o), slot)
#define obj_setslot(o, slot, v) (obj_getslot(o, slot) = (v))

#ifdef MON_FLAT
#define obj_monitor(handlep) ((struct Hjava_lang_Object *) handlep)     /*ibm.4317*/
#else
#define obj_monitor(handlep) ((int) handlep)
#endif


struct arrayinfo {
    int index;
    char sig;      /* type signature. */
    char *name;
    int factor;
};

typedef union stack_item {
    /* Non pointer items */
    int            i;
    float_t        f;                                           /*ibm01229*/
    OBJECT         o;
    /* Pointer items */
    JHandle       *h;
    void          *p;
    unsigned char *addr;
} stack_item;

/* ibm.5832 */
/* ELS 6/98      Multiple mark stack implementation */

#define  MAX_MARK_ENTRIES 5000 /* Depth of mark stack */
typedef enum {AVAILABLE, IN_USE, FULL} Stackstatus;
typedef struct MarkStack *MarkStackPtr;
typedef struct MarkStack {
  MarkStackPtr volatile next;        /* Next mark stack in link list */
  volatile int nextWriteIndex;     /* Next slot free */
  int lastReadIndex;       /* Last slot read by tracing collector */
  volatile int status;     /* Status of mark stack */
  JHandle * volatile objectPtrs[MAX_MARK_ENTRIES];  /* Ptrs to queued objects *//*ibm.9498*/
} MarkStack;

/* ELS ibm.5832 */

struct execenv {
    struct javastack  *initial_stack;
    struct javaframe  *current_frame;
    JHandle           *thread;      /* vague type to avoid include files */
    char              exceptionKind;
    union {
        JHandle       *exc;         /* holds exception object */
        unsigned char *addr;        /* holds pc for stack overflow */
    } exception;

    /* Stuff for the JNI: */
    struct JNIEnv_    nativeInterface;

    /* Detecting class circularities */
    struct seenclass {
        ClassClass    *cb;
        struct seenclass *next;
    } seenclasses;

#ifdef JIT_TRL
    /* Stuff For JIT implementation of Frame Access Abstraction */
    struct jit_execenv {
        int    exec_mode;
        void*  last_frame;
        void*  privateInfo;
    } jit_ee;
#endif

#ifdef MON_FLAT
  long tindex; /* stuff for fast monitors */
#endif

    /* Per-thread allocation cache */
    struct alloc_cache alloc_cache;

    /* error message occurred during class loading */
    char *class_loading_msg;

#ifdef IBM_HAIFA_GC                                             /*ibm.5023*/
  /* IGOR & TMR 28/7/97 */
  volatile int    status;        /* The synchronization status of the thread */
  volatile int    allocatedInCycle; /* The number of bytes allocated during the current GC cycle */
  volatile bool_t cantCooperate;
  volatile int notified; /* holds the number of passes through the thread ring
                            until the collector will send a signal to cooperate ibm.9524 */
  volatile int    numGCcycles;
  volatile bool_t update;   /* Whether update has to be invoked in the current
                                                           state */
  volatile int    AllocVecNum;  /* Allocation Vector Number for small
                                                                   objects*/
  MarkStackPtr pMarkStack;  /* Mark stack for thread's use - ibm.5832  */
  volatile bool_t dirty;   /*ibm.5833*/
  void   *compensatedBlockHeaders; /*ibm.5833*/
  /* pointer to the current bin for small object sizes, for the current thread */
  JHandle  (* volatile  (*pBin)); /*ibm.6565*/
  /* Current allocation color */
  char            allocationColor;
  /* Pointer to compensated markbits */
  unsigned char  *volatile compensatedMarkbits;
  unsigned char  clearColor,markColor;
#endif                                                          /*ibm.5023*/

#if defined(IBM_MIXED_MODE)						/*ibm.8222*/
    /* per thread debug and stats info */
    int stopped_at_single_step;
    int breakpoint_last_time;
    int lastOpcode;
#endif /*+IBM_MIXED_MODE*/						/*ibm.8222*/

#if defined(IBM_JVMPI)                                              /*ibm.6402*/
    /* per thread profile information */
    struct profile_table * profileData;

    /* For HPROF. Always compiled in to make sure the SysThread2EE
     * macro stays the same for JITs.
     */
    unsigned int RESERVED3;

    /* Platform-dependent thread block. See threads_md.c for details.
     * This field must be placed at the end of execenv.
     * Use double to make sure sys_thr is 8-byte aligned.
     */
    double sys_thr[1];
#endif /* +IBM_JVMPI */                                             /*ibm.6402*/
};

#if defined(IBM_JVMPI)                                              /*ibm.6402*/
#define EE_FROM_SYS_THR  (sizeof(struct execenv)-sizeof(double))
#endif /* +IBM_JVMPI */                                             /*ibm.6402*/

typedef struct execenv ExecEnv;

#define PRIVILEGED_EE ((ExecEnv*)-1)

#define JAVASTACK_CHUNK_SIZE 2000
struct javastack {
    struct execenv  *execenv;       /* execenv we belong to */
    struct javastack *prev;          /* previous stack of this execenv */
    struct javastack *next;          /* next stack of this execenv */
    stack_item      *end_data;      /* address of end of data */
    unsigned int     stack_so_far;  /* total space used by this chunk and
                                     * all previous chunks. */
    stack_item       data[JAVASTACK_CHUNK_SIZE];    /* actual data */

};

typedef struct javastack JavaStack;


struct javaframe {
    /* DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER
     * N. B.the first two items in structure shouldn't be needed by function
     * return or by the Garbage Collector, since they may be overwritten by
     * dreturn, lreturn, etc.
     */
    cp_item_type       *constant_pool; /* constant_pool of this method */
    unsigned char      *returnpc;      /* pc of next instruction */
    /* REGNAD REGNAD REGNAD REGNAD REGNAD REGNAD REGNAD REGNAD REGNAD REGNAD */

    stack_item         *optop;         /* current top of stack */
    stack_item         *vars;          /* pointer to this frame's vars */
    struct javaframe   *prev;          /* previous java frame. */
    struct javastack   *javastack;
    unsigned char      *lastpc;        /* pc of last executed instruction */
    struct methodblock *current_method;/* method currently executing */
    JHandle            *monitor;       /* object locked by this method */
    int                 mon_starttime; /* time this method began */
    stack_item ostack[1];              /* start of this frame's stack */
};

typedef struct javaframe JavaFrame;


/*
 * Javaframe.exceptionKind is used to signal why the interpreter
 * loop was exited.
 */
#define EXCKIND_NONE            0               /* return */
#define EXCKIND_THROW           1               /* throw */
#define EXCKIND_STKOVRFLW       2               /* stack overflow */

/*
 * Be sure to use these macros to access the exception structure.  Do
 * not access the fields directly.
 */
#define exceptionClear(ee)                      \
    ((ee)->exceptionKind = EXCKIND_NONE);

#define exceptionOccurred(ee)                   \
    ((ee)->exceptionKind != EXCKIND_NONE)

#define exceptionThrow(ee, obj)                 \
    (ee)->exceptionKind = EXCKIND_THROW;        \
    (ee)->exception.exc = (obj);

/* Macro for handling specific kinds of exceptions */
#define exceptionThrowSpecial(ee, obj, kind)    \
    (ee)->exceptionKind = kind;                 \
    (ee)->exception.exc = (obj);


extern long nbinclasses, sizebinclasses;
extern ClassClass **binclasses;

/* stuff for dealing with handles */
#ifndef JMS_TRL  /* [TRL] Sun's original definition */
#define unhand(o) ((o)->obj)
#endif


/* globals.c */

ClassClass** get_binclasses(void);
ClassClass* get_classClass(void);
ClassClass* get_classObject(void);
long get_nbinclasses(void);

/* gc.c */
#define MINHEAPEXPANSION (1 * 1024 * 1024)
#if defined (IBM_INTEL) || defined (AIX_HEAP_GROWTH)			/*ibm.8988*/ /* ibm.10283 */
#define MAXHEAPEXPANSION 0
#else									/*ibm.8988*/
#define MAXHEAPEXPANSION (4 * 1024 * 1024)
#endif									/*ibm.8988*/
#define MINHEAPFREEPERCENT (float)0.25
#if defined(IBM_INTEL) && defined(COMPACTION_AVOIDANCE)			/*ibm.8904,8988*/
#define MAXHEAPFREEPERCENT (float)0.70
#else
#define MAXHEAPFREEPERCENT (float)1.00
#endif /* COMPACTION_AVOIDANCE */					/*ibm.8904,8988*/

typedef struct heapoptions {
    float minHeapFreePercent;
    float maxHeapFreePercent;
    long minHeapExpansion;
    long maxHeapExpansion;
} heapoptions;

#ifdef IBM_MVS
/* ibm.7978 Kathy -- dynamic bin vectors number, start */
bool_t InitializeAlloc(long max, long min, int binVecs);
extern int binVecsNumber;
/* ibm.7978 Kathy -- dynamic bin vectors number, end */
#else /* IBM_MVS */
bool_t InitializeAlloc(long max, long min);
#endif /* IBM_MVS */
HObject *AllocHandle(struct methodtable *, ClassObject *);
extern struct arrayinfo const arrayinfo[];
extern int64_t TotalObjectMemory(void);
extern int64_t FreeObjectMemory(void);
extern int64_t TotalHandleMemory(void);
extern int64_t FreeHandleMemory(void);
extern int tracegc;

#ifdef IBM_HAIFA_GC                                             /*ibm.4860*/
#define gc(async_call,free_space_goal) StartSyncGC()

/* Variable for determining which bin vector is used  */
static volatile int binVectorIndicator = 0;
#else                                                           /*ibm.4860*/
extern void gc(int async, unsigned int spaceRequested);
#endif /* IBM_HAIFA_GC */                                       /*ibm.4860*/


/* interpreter.c */

/* SignalError() -- Instantiate an object of the specified class.
 * Indicate that that error occurred.
 */
extern bool_t UseLosslessQuickOpcodes;
void SignalError(struct execenv *, char *, char *);

JavaStack *CreateNewJavaStack(ExecEnv *ee, JavaStack *previous_stack);

void InitializeExecEnv(ExecEnv *ee, JHandle *thread);
void DeleteExecEnv(ExecEnv *ee);
extern ExecEnv *DefaultExecEnv;


HObject *execute_java_constructor(ExecEnv *,
                                 char *classname,
                                 ClassClass *cb,
                                 char *signature, ...);
long execute_java_static_method(ExecEnv *, ClassClass *cb,
                               char *method_name, char *signature, ...);
long execute_java_dynamic_method(ExecEnv *, HObject *obj,
                                char *method_name, char *signature, ...);

long do_execute_java_method(ExecEnv *ee, void *obj,
                           char *method_name, char *signature,
                           struct methodblock *mb,
                           bool_t isStaticCall, ...);

long do_execute_java_method_vararg(ExecEnv *ee, void *obj,
                                   char *method_name, char *signature,
                                   struct methodblock *mb,
                                   bool_t isStaticCall, va_list args,
                                   long *highBits, bool_t shortFloats);

long now(void);
bool_t isSpecialSuperCall(ClassClass *current_class, struct methodblock *mb);

void InitializeInterpreter(void);
bool_t is_instance_of(JHandle * h, ClassClass *dcb, ExecEnv *ee);
bool_t is_subclass_of(ClassClass *cb, ClassClass *dcb, ExecEnv *ee);
bool_t array_is_instance_of_array_type(JHandle * h, ClassClass *cb,
                                       ExecEnv *ee);
bool_t ImplementsInterface(ClassClass *cb, ClassClass *icb, ExecEnv *ee);
HObject *MultiArrayAlloc(int dimensions, ClassClass *, stack_item *sizes);
bool_t ExecuteJava(unsigned char  *, ExecEnv *ee);

/*
 * Called from ExecuteJava.
 *    -1:   rewrite signalled an error
 *     0:   rewrite went okay
 *    +1:   opcode changed underneath us.  Redo
 */

int quickFieldAccess( int opcode, unsigned char * pc, struct fieldblock *fb,
                        ExecEnv *ee );
int quickStaticAccess( int opcode, unsigned char * pc, struct fieldblock *fb,
                        ExecEnv *ee );
int quickInvocation( int opcode, unsigned char * pc, struct methodblock *mb,
                        ExecEnv *ee );
void FixupQuickInvocation(unsigned char *pc,
                          struct methodblock *currentMethod,
                          struct methodblock *targetMethod);

bool_t
invokeInterfaceError(ExecEnv *ee, unsigned char *pc,
                     ClassClass *cb, ClassClass *intf);

unsigned char *
ProcedureFindThrowTag(ExecEnv *ee,
                      JavaFrame *frame, JHandle *object, unsigned char *pc);

void *
ResolveClassConstantFromPC(unsigned char *pc, unsigned char opcode,
                               cp_item_type *, struct execenv *ee, unsigned mask);



struct stat;

#if defined(IBM_MIXED_MODE)						/*ibm.8961*/
bool_t	dynoLink_nonstub(struct methodblock *);
#endif	/* IBM_MIXED_MODE */						/*ibm.8961*/
bool_t dynoLink(struct methodblock *);
bool_t dynoLinkJNI(struct methodblock *);
char *str2rd(char *);
char *unicode2rd(unicode *, long);

/* classruntime.c */
HArrayOfChar *MakeString(char *, long);

ClassClass *FindClass(struct execenv *, char *, bool_t resolve);
ClassClass *FindStickySystemClass(struct execenv *, char *, bool_t resolve);
ClassClass *FindClassFromClass(struct execenv *, char *, bool_t resolve, ClassClass *from);
#ifdef JIT_WAY
void InstallStaticInitializer(ClassClass *cb);
void ExecuteStaticInitializers(ClassClass *cb);
void MayExecuteStaticInitializersFor_multianewarray(ClassClass*array,int dim);
#else
bool_t RunStaticInitializers(ClassClass *cb);
#endif
void InitializeInvoker(ClassClass *cb);

#if defined(IBM_MIXED_MODE)                                         /*ibm.6205*/
#if !defined(IBM_MVS)                                               /*ibm.8933*/
bool_t  invokeJavaMethodWithCatch(JHandle *o, struct methodblock *mb, int args_size, ExecEnv *ee);
bool_t  invokeSynchronizedJavaMethodWithCatch(JHandle *o, struct methodblock *mb, int args_size, ExecEnv *ee);
#endif /* !IBM_MVS */                                               /*ibm.8933*/
bool_t  invokeNativeMethod_nonstub(JHandle *o, struct methodblock *mb, int args_size, ExecEnv *ee);
bool_t  invokeSynchronizedNativeMethod_nonstub(JHandle *o, struct methodblock *mb, int args_size, ExecEnv *ee);
#endif /* +IBM_MIXED_MODE */                                        /*ibm.6205*/

bool_t
invokeJavaMethod(JHandle *o, struct methodblock *mb, int args_size, ExecEnv *ee);
bool_t invokeSynchronizedJavaMethod(JHandle *o, struct methodblock *mb,
                                    int args_size, ExecEnv *ee);
bool_t invokeNativeMethod(JHandle *o, struct methodblock *mb, int args_size,
                          ExecEnv *ee);
bool_t invokeSynchronizedNativeMethod(JHandle *o, struct methodblock *mb,
                                      int args_size, ExecEnv *ee);
bool_t invokeJNINativeMethod(JHandle *o, struct methodblock *mb, int args_size,
                             ExecEnv *ee);
bool_t invokeJNISynchronizedNativeMethod(JHandle *o, struct methodblock *mb,
                                         int args_size, ExecEnv *ee);
bool_t invokeLazyNativeMethod(JHandle *o, struct methodblock *mb, int args_size,
                              ExecEnv *ee);
bool_t invokeAbstractMethod(JHandle *o, struct methodblock *mb, int args_size,
                            ExecEnv *ee);
bool_t invokeCompiledMethod(JHandle *o, struct methodblock *mb, int args_size,
                            ExecEnv *ee);


void LoadClassConstants(ClassClass *cb);
bool_t ResolveClassStringConstant(ClassClass *, unsigned, struct execenv *);
bool_t ResolveClassConstant(cp_item_type *, unsigned index, struct execenv *ee,
                            unsigned mask);
bool_t ResolveClassConstantFromClass(ClassClass *, unsigned index,
                                     struct execenv *ee, unsigned mask);

void InitializeClassConstantResolver();

bool_t VerifyClassAccess(ClassClass *, ClassClass *, bool_t);
bool_t VerifyFieldAccess(ClassClass *, ClassClass *, int, bool_t);
bool_t IsSameClassPackage(ClassClass *class1, ClassClass *class2);

char *GetClassConstantClassName(cp_item_type *constant_pool, int index);
unsigned NameAndTypeToHash(char *name, char *type);
#if defined(IBM_FASTHASH)                                          /*ibm.8934*/
unsigned NameAndTypeToHash_RO(char *name, char *type);
#endif /*IBM_FASTHASH*/                                            /*ibm.8934*/
HObject *newobject(ClassClass *cb, unsigned char *pc, struct execenv *ee);


char *pc2string(unsigned char *pc, struct methodblock *mb, char *buf, char *limit);

#ifdef IBM_HAIFA_GC                                             /*ibm.5023*/
JHandle *ObjAlloc_ee(ClassClass *, long, ExecEnv *);
JHandle *ArrayAlloc_ee(int, int, ExecEnv *);
#define ArrayAlloc( t, l)  ArrayAlloc_ee(t, l, EE() )
#define ObjAlloc(cb, n0)   ObjAlloc_ee(cb, n0, EE() )
#else                                                           /*ibm.5023*/
JHandle *ArrayAlloc(int, int);
JHandle *ObjAlloc(ClassClass *, long);
#endif /*IBM_HAIFA_GC */                                        /*ibm.5023*/
#if defined(JMS_TRL) && defined(IBM_ALLOC_CACHE)
JHandle *FastArrayAlloc(struct execenv*, int, int);
JHandle *FastObjAlloc(struct execenv*, ClassClass *, long);
#endif
int sizearray(int, int);
extern char *remote_classname(JHandle *);
extern JHandle *remote_clone(struct execenv *);
extern long remote_cast(JHandle *, ClassClass *);
int pc2lineno(struct methodblock *, unsigned int);

/* From verify_class.c */
bool_t VerifyClass(ClassClass *cb);
bool_t IsLegalClassname(char *name, bool_t allowArrayClass);

/* From verify_code.c */
bool_t verify_class_codes(ClassClass *cb);


/* from profiler.c */
extern int java_monitor;
void javamon(int i);
void java_mon(struct methodblock *caller, struct methodblock *callee, int time);
void java_mon_dump(void);

#ifdef JCOV
#include "jcov.h"
#endif /* JCOV */

/* from classloader.c */
void FreeClass(ClassClass *cb);
void AddBinClass(ClassClass * cb);
void DelBinClass(ClassClass * cb);
ClassClass *LoadClassLocally(char *name);
bool_t createInternalClass(unsigned char *bytes, unsigned char *limit,
                           ClassClass *cb, struct Hjava_lang_ClassLoader *,
                            char *utfname, char **detail);
ClassClass *createFakeArrayClass(char *name, int base_type, int depth,
                                 ClassClass *inner_cb,
                                 struct Hjava_lang_ClassLoader *);
ClassClass *createPrimitiveClass(char *name, char sig, unsigned char typecode,
    unsigned char slotsize, unsigned char elementsize);
unsigned Signature2ArgsSize(char *method_signature);

typedef struct {
    unsigned char *class_data;
    int            class_data_len;
    unsigned char *new_class_data;
    int            new_class_data_len;
    void *       (*malloc_f)(int);
} classload_event;

typedef void (*classload_hook)(classload_event *);

/* from classresolver.c */
char *LinkClass(ClassClass *cb, char **detail);
char *InitializeClass(ClassClass * cb, char **detail);
char *ResolveClass(ClassClass * cb, char **detail);
ClassClass *FindClass(struct execenv *ee, char *name, bool_t resolve);
ClassClass *FindClassFromClass(struct execenv *ee, char *name,
                               bool_t resolve, ClassClass *from);
ClassClass *ClassLoaderFindClass(ExecEnv *ee,
                                 struct Hjava_lang_ClassLoader *loader,
                                 char *name, bool_t resolve);

int  makeslottable(ClassClass * clb);
void lock_classes(void);
void unlock_classes(void);

extern ClassClass *class_void;
extern ClassClass *class_boolean;
extern ClassClass *class_byte;
extern ClassClass *class_char;
extern ClassClass *class_short;
extern ClassClass *class_int;
extern ClassClass *class_long;
extern ClassClass *class_float;
extern ClassClass *class_double;

extern ClassClass *FindPrimitiveClass(char *);

/* from path_md.c */
char **CLASSPATH(void);

/* from threadruntime.c */
struct Hjava_lang_Thread *InitializeClassThread(ExecEnv *ee, char **errmsg);
void InitializeMainThread(void);
long *getclassvariable(ClassClass *cb, char *fname);
struct Hjava_lang_Thread;
char *thread_name(struct Hjava_lang_Thread *tid);

void setThreadName(struct Hjava_lang_Thread *ht, HArrayOfChar *newName);
HArrayOfChar *getThreadName(void);

/* from exception.c */
struct Hjava_lang_Throwable;
void fillInStackTrace(struct Hjava_lang_Throwable *handle, ExecEnv *ee);

/* from CompSupport.c */
long CallInterpreted(register struct methodblock * mb, void *obj,...);

/* used to indicate of an object or remote or local */
extern struct methodtable *remote_methodtable;

void unicode2str(unicode *, char *, long);
unicode *str2unicode(char *, unicode *, long);

enum {
    MangleMethodName_JDK_1,
    MangleMethodName_JNI_SHORT,
    MangleMethodName_JNI_LONG
};
void mangleMethodName(struct methodblock *mb, char *buffer, int buflen,
                      int mangleType);
#if defined(IBM_MIXED_MODE)						/*ibm.8961*/
void mangleMethodName_nonstub(struct methodblock *mb, char *buffer, int buflen);
#endif	/* IBM_MIXED_MODE */						/*ibm.8961*/

enum {
    MangleUTF_Class,
    MangleUTF_Field,
    MangleUTF_FieldStub,
    MangleUTF_Signature,
    MangleUTF_JNI
};
int mangleUTFString(char *name, char *buffer, int buflen, int mangleType);

/* string hash support */
struct StrIDhash;
unsigned short Str2ID(struct StrIDhash **, char *, void ***, int);
#if defined(IBM_FASTHASH)                                          /*ibm.8934*/
unsigned short Str2ID_RO(struct StrIDhash **,char *);
#endif /*IBM_FASTHASH*/                                            /*ibm.8934*/
char *ID2Str(struct StrIDhash *, unsigned short, void ***);
void Str2IDFree(struct StrIDhash **);
#ifdef JMS_TRL
void Str2IDCallback(struct StrIDhash **hash_ptr, void (*)(char *, void**));
#else
void Str2IDCallback(struct StrIDhash **hash_ptr, void (*)(char *, void *));
#endif
ExecEnv *EE(void);

/* Miscellaneous functions in util.c */
char *unicode2rd(unicode *s, long len);
void out_of_memory(void);
void prints(char *s);
void printus(unicode *str, long len);
int jio_snprintf(char *str, size_t count, const char *fmt, ...);
int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args);

int jio_printf(const char *fmt, ...);
int jio_fprintf(FILE *, const char *fmt, ...);
int jio_vfprintf(FILE *, const char *fmt, va_list args);


/* allows you to override panic & oom "functionality" */
typedef void (*PanicHook)(const char* panicString);
typedef void (*OutOfMemoryHook) ();

extern PanicHook panic_hook;
extern OutOfMemoryHook out_of_memory_hook;

/* Stuff from compiler.c */

void InitializeForCompiler(ClassClass *cb);
void CompilerFreeClass(ClassClass *cb);
void CompilerCompileClass(ClassClass *cb);
void ReadInCompiledCode(void *context, struct methodblock *mb,
                        int attribute_length,
                        unsigned long (*get1byte)(),
                        unsigned long (*get2bytes)(),
                        unsigned long (*get4bytes)(),
                        void (*getNbytes)());

bool_t PCinCompiledCode(unsigned char *pc, struct methodblock *mb);
unsigned char *CompiledCodePC(JavaFrame *frame, struct methodblock *mb);
JavaFrame *CompiledFramePrev(JavaFrame *frame, JavaFrame *buf);

#ifdef JIT_TRL
/*
 * execution mode
 */
typedef enum {
   EXECMODE_BYTECODE,
   EXECMODE_COMPILEDCODE,
   EXECMODE_JITCOMPILE
} ExecMode;

/*
 * Frame traverser
 *
 * The size of a frame traverser varies depending on implementations.
 * However, for the efficiency reason, the user of a traverser interface
 * has the resopnsibility to allocate the traverser's memory. We
 * (believe and) assume that the following macro constant is
 * sufficiently large for any traverser implementation.
 */

typedef struct {
#define MAX_FRAME_TRAVERSER_SIZE 32
   char buf[MAX_FRAME_TRAVERSER_SIZE];
} FrameTraverser;

/*
 * Frame Interface (Facade)
 */
typedef struct {
    /* FrameTraverser
     */
    void (*init)(ExecEnv*, FrameTraverser*);
    void (*clone)(FrameTraverser*src, FrameTraverser*dest);

    void   (*prev)(FrameTraverser*);
    bool_t (*more)(FrameTraverser*);

    struct methodblock* (*method)(FrameTraverser*);
    unsigned char*      (*lastpc)(FrameTraverser*);
    JHandle*            (*target)(FrameTraverser*);
    /* only for dumping thread info */
    stack_item          (*args)(FrameTraverser*, int);

    /* Quick access to the attributes of the "current frame",
     * done without creating a FrameTraverser.
     */
    bool_t              (*current_frame_exists)(ExecEnv*);
    struct methodblock* (*current_frame_method)(ExecEnv*);
    unsigned char*      (*current_frame_lastpc)(ExecEnv*);
    int                 (*current_frame_address)(ExecEnv*);

    /* execution mode
     */
    ExecMode (*set_mode)(ExecEnv*, ExecMode);
    ExecMode (*get_mode)(ExecEnv*);

    /* for java.lang.Thread.stop0(o) */
    void (*jitcThreadPostException)(ExecEnv*, void*);

#if defined(IBM_MIXED_MODE)						/*ibm.8961*/
    /* Get current frame pointer	*/
    unsigned long *(* getframe)(FrameTraverser *);

    /* Get execution mode of the method owning the frame	*/
    ExecMode (* frame_mode)(FrameTraverser *);
#endif	/* IBM_MIXED_MODE */						/*ibm.8961*/
} FrameInterface;

#ifdef IBM_OS2								/*ibm.8706*/
/* This is a cutdown version of the FrameInterface structure that */
/* is exported (via an API) for use by other components.          */
typedef struct {
    void (*init)(ExecEnv *, void *);
    void (*clone)(void *, void *);
    void (*prev)(void *);
    int  (*more)(void *);
    struct methodblock * (*method)(void *);
    unsigned char *      (*lastpc)(void *);
} NsFrameIntf;

void NsGetFrameIntf(NsFrameIntf **, int *);
#endif									/*ibm.8706*/

extern FrameInterface  FrameIntf;

#define being_interpreted(ee)     (FrameIntf.get_mode(ee)==EXECMODE_BYTECODE)
#define being_jitcompiled(ee)     (FrameIntf.get_mode(ee)==EXECMODE_JITCOMPILE)

#endif /* JIT_TRL */

/* Stuff from simplify.c */
bool_t MethodCallInline(unsigned char *pc, struct methodblock *sourceMethod,
                        struct methodblock *mb, unsigned char *result);

#define KEEP_POINTER_ALIVE(p) if ((p) == 0) EE()



#if defined(IBM_JVMPI)                                              /*ibm.6402*/
JavaFrame *CompiledFrameUpdate(JavaFrame *frame);
bool_t CompilerRegisterNatives(ClassClass *cb);
bool_t CompilerUnRegisterNatives(ClassClass *cb);
// bool_t CompiledCodeSignalHandler( int sig, void *info, void *uc);

/*
 * These macros are used for walking the stack and determining if
 * a frame is JITed or not.  JITed frames are special in that multiple
 * JIT frames may be represented by a single JavaFrame.  The frame_buf
 * argument is normally a pointer to a JavaFrame structure on the stack.
 * The JIT will fill this frame in for the cases were multiple JIT frames
 * are being represented by a single JavaFrame.
 */

#define IS_JIT_FRAME(frame) \
    ((frame)->current_method && \
    (frame)->current_method->fb.access & ACC_MACHINE_COMPILED && \
    (frame)->constant_pool == NULL)

#define FRAME_PREV(frame, frame_buf) \
    IS_JIT_FRAME(frame) ? \
    CompiledFramePrev(frame, frame_buf) : frame->prev;
#endif /* +IBM_JVMPI */                                             /*ibm.6402*/




/*
 * BEGIN JNI STUFF:
 * Only the stuff used by the JNI implementation, but not by JNI
 * programmers. jni.h contains the types and function prototypes
 * used by JNI programmers
 */

int InitializeJNI();

void InitializeJNIRootFrame(ExecEnv *ee);
void DeleteJNIRootFrame(ExecEnv *ee);

/*
 * Reference tables
 */

#define JNI_REF_COUNT_MASK 0x1fffffff

#define JNI_REF_TAG_MASK 0x60000000

#define JNI_REF_HANDLE_TAG 0x00000000

#define JNI_REF_FB_TAG 0x20000000

#define JNI_REF_MB_TAG 0x40000000

typedef struct JNIRefCell {
    uint32_t refCount;
    void *content;
} JNIRefCell;

typedef struct JNIRefTable {
    JNIRefCell *elements;
    int base;
    int top;
    int size;
} JNIRefTable;

extern jref jni_AddRefCell(JNIRefTable *table, void *entry, int kind);
extern JNIRefTable globalRefTable;

/*
 * JNIEnv <-> ExecEnv conversion
 */

#define JNIEnv2EE(env) \
    ((ExecEnv*)((char*)(env) - offsetof(ExecEnv, nativeInterface)))

#define EE2JNIEnv(ee) ((JNIEnv *)(&(ee)->nativeInterface))

/*
 * References
 * The local reference table is stored in field reserved1.
 */

#define JNIEnvGetLocalRefs(env) \
    ((JNIRefTable *)(((struct JNIEnv_ *)(env))->reserved1))

#define MkRefLocal(env, jobj, tag) \
    ((jref)(jni_AddRefCell(JNIEnvGetLocalRefs(env), (void *)(jobj), tag)))

#define DeRef(env, ref) \
    ((int)(ref) > 0 ? \
         JNIEnvGetLocalRefs(env)->elements[(int)(ref) - 1].content \
       : ((ref) ? \
              globalRefTable.elements[-((int)(ref)) - 1].content \
            : 0))

/*
 * JavaVM <-> main EE conversion
 * The main EE is stored in field reserved0.
 */
#define JavaVMGetEE(vm) ((ExecEnv *)(((struct JavaVM_ *)vm)->reserved0))

/* used in java_main */
struct methodblock *
JNI_FindMainMethod(ClassClass *cb, char **error_message_p);
/*
 * END JNI STUFF
 */

#endif /* ! _INTERPRETER_H_ */

