mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			589 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			589 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
// java-interp.h - Header file for the bytecode interpreter.  -*- c++ -*-
 | 
						|
 | 
						|
/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation
 | 
						|
 | 
						|
   This file is part of libgcj.
 | 
						|
 | 
						|
This software is copyrighted work licensed under the terms of the
 | 
						|
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 | 
						|
details.  */
 | 
						|
 | 
						|
#ifndef __JAVA_INTERP_H__
 | 
						|
#define __JAVA_INTERP_H__
 | 
						|
 | 
						|
#include <jvm.h>
 | 
						|
#include <java-cpool.h>
 | 
						|
#include <gnu/gcj/runtime/NameFinder.h>
 | 
						|
 | 
						|
enum _Jv_FrameType
 | 
						|
{
 | 
						|
  frame_native,
 | 
						|
  frame_interpreter,
 | 
						|
  frame_proxy
 | 
						|
};
 | 
						|
 | 
						|
#ifdef INTERPRETER
 | 
						|
 | 
						|
#pragma interface
 | 
						|
 | 
						|
#include <java/lang/Class.h>
 | 
						|
#include <java/lang/ClassLoader.h>
 | 
						|
#include <java/lang/reflect/Modifier.h>
 | 
						|
#include <java/lang/Thread.h>
 | 
						|
#include <gnu/gcj/RawData.h>
 | 
						|
 | 
						|
// Define this to get the direct-threaded interpreter.  If undefined,
 | 
						|
// we revert to a basic bytecode interpreter.  The former is faster
 | 
						|
// but uses more memory.
 | 
						|
#define DIRECT_THREADED
 | 
						|
 | 
						|
#include <ffi.h>
 | 
						|
 | 
						|
struct _Jv_ResolvedMethod;
 | 
						|
 | 
						|
void _Jv_InitInterpreter ();
 | 
						|
void _Jv_DefineClass (jclass, jbyteArray, jint, jint,
 | 
						|
		      java::security::ProtectionDomain *,
 | 
						|
		      _Jv_Utf8Const **);
 | 
						|
 | 
						|
void _Jv_InitField (jobject, jclass, int);
 | 
						|
void * _Jv_AllocMethodInvocation (jsize size);
 | 
						|
int  _Jv_count_arguments (_Jv_Utf8Const *signature,
 | 
						|
			  jboolean staticp = true);
 | 
						|
void _Jv_VerifyMethod (_Jv_InterpMethod *method);
 | 
						|
void _Jv_CompileMethod (_Jv_InterpMethod* method);
 | 
						|
int _Jv_init_cif (_Jv_Utf8Const* signature,
 | 
						|
		  int arg_count,
 | 
						|
		  jboolean staticp,
 | 
						|
		  ffi_cif *cif,
 | 
						|
		  ffi_type **arg_types,
 | 
						|
		  ffi_type **rtype_p);
 | 
						|
 | 
						|
/* the interpreter is written in C++, primarily because it makes it easy for
 | 
						|
 * the entire thing to be "friend" with class Class. */
 | 
						|
 | 
						|
class _Jv_InterpClass;
 | 
						|
class _Jv_InterpMethod;
 | 
						|
 | 
						|
// Before a method is "compiled" we store values as the bytecode PC,
 | 
						|
// an int.  Afterwards we store them as pointers into the prepared
 | 
						|
// code itself.
 | 
						|
union _Jv_InterpPC
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  void *p;
 | 
						|
};
 | 
						|
 | 
						|
class _Jv_InterpException
 | 
						|
{
 | 
						|
  _Jv_InterpPC start_pc;
 | 
						|
  _Jv_InterpPC end_pc;
 | 
						|
  _Jv_InterpPC handler_pc;
 | 
						|
  _Jv_InterpPC handler_type;
 | 
						|
 | 
						|
  friend class _Jv_ClassReader;
 | 
						|
  friend class _Jv_InterpMethod;
 | 
						|
  friend class _Jv_BytecodeVerifier;
 | 
						|
};
 | 
						|
 | 
						|
// Base class for method representations.  Subclasses are interpreted
 | 
						|
// and JNI methods.
 | 
						|
class _Jv_MethodBase
 | 
						|
{
 | 
						|
protected:
 | 
						|
  // The class which defined this method.
 | 
						|
  jclass defining_class;
 | 
						|
 | 
						|
  // The method description.
 | 
						|
  _Jv_Method *self;
 | 
						|
 | 
						|
  // Size of raw arguments.
 | 
						|
  _Jv_ushort args_raw_size;
 | 
						|
 | 
						|
  friend class _Jv_InterpreterEngine;
 | 
						|
 | 
						|
public:
 | 
						|
  _Jv_Method *get_method ()
 | 
						|
  {
 | 
						|
    return self;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
// The type of the PC depends on whether we're doing direct threading
 | 
						|
// or a more ordinary bytecode interpreter.
 | 
						|
#ifdef DIRECT_THREADED
 | 
						|
// Slot in the "compiled" form of the bytecode.
 | 
						|
union insn_slot
 | 
						|
{
 | 
						|
  // Address of code.
 | 
						|
  void *insn;
 | 
						|
  // An integer value used by an instruction.
 | 
						|
  jint int_val;
 | 
						|
  // A pointer value used by an instruction.
 | 
						|
  void *datum;
 | 
						|
};
 | 
						|
 | 
						|
typedef insn_slot *pc_t;
 | 
						|
#else
 | 
						|
typedef unsigned char *pc_t;
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
// This structure holds the bytecode pc and corresponding source code
 | 
						|
// line number.  An array (plus length field) of this structure is put
 | 
						|
// in each _Jv_InterpMethod and used to resolve the (internal) program
 | 
						|
// counter of the interpreted method to an actual java source file
 | 
						|
// line.
 | 
						|
struct  _Jv_LineTableEntry
 | 
						|
{
 | 
						|
  union
 | 
						|
  {
 | 
						|
    pc_t pc;
 | 
						|
    int bytecode_pc;
 | 
						|
  };
 | 
						|
  int line;
 | 
						|
};
 | 
						|
 | 
						|
// This structure holds local variable information.
 | 
						|
// Like _Jv_LineTableEntry above, it is remapped when the method is
 | 
						|
// compiled for direct threading.
 | 
						|
struct _Jv_LocalVarTableEntry
 | 
						|
{
 | 
						|
  // First PC value at which variable is live
 | 
						|
  union
 | 
						|
  {
 | 
						|
    pc_t pc;
 | 
						|
    int bytecode_pc;
 | 
						|
  };
 | 
						|
 | 
						|
  // length of visibility of variable
 | 
						|
  int length;
 | 
						|
 | 
						|
  // variable name
 | 
						|
  char *name;
 | 
						|
 | 
						|
  // type description
 | 
						|
  char *descriptor;
 | 
						|
 | 
						|
  // stack slot number (long and double occupy slot and slot + 1)
 | 
						|
  int slot;
 | 
						|
};
 | 
						|
 | 
						|
class _Jv_InterpMethod : public _Jv_MethodBase
 | 
						|
{
 | 
						|
  // Breakpoint instruction
 | 
						|
  static pc_t breakpoint_insn;
 | 
						|
#ifdef DIRECT_THREADED
 | 
						|
  static insn_slot bp_insn_slot;
 | 
						|
 | 
						|
public:
 | 
						|
  // Mutex to prevent a data race between threads when rewriting
 | 
						|
  // instructions.  See interpret-run.cc for an explanation of its use.
 | 
						|
  static _Jv_Mutex_t rewrite_insn_mutex;
 | 
						|
 | 
						|
  // The count of threads executing this method.
 | 
						|
  long thread_count;
 | 
						|
 | 
						|
private:
 | 
						|
 | 
						|
#else
 | 
						|
  static unsigned char bp_insn_opcode;
 | 
						|
#endif
 | 
						|
 | 
						|
  _Jv_ushort       max_stack;
 | 
						|
  _Jv_ushort       max_locals;
 | 
						|
  int              code_length;
 | 
						|
 | 
						|
  _Jv_ushort       exc_count;
 | 
						|
  bool             is_15;
 | 
						|
 | 
						|
  // Length of the line_table - when this is zero then line_table is NULL.
 | 
						|
  int line_table_len;  
 | 
						|
  _Jv_LineTableEntry *line_table;
 | 
						|
  
 | 
						|
  // The local variable table length and the table itself
 | 
						|
  int local_var_table_len;
 | 
						|
  _Jv_LocalVarTableEntry *local_var_table;
 | 
						|
 | 
						|
  pc_t prepared;
 | 
						|
  int number_insn_slots;
 | 
						|
 | 
						|
  unsigned char* bytecode () 
 | 
						|
  {
 | 
						|
    return 
 | 
						|
      ((unsigned char*)this) 
 | 
						|
      + ROUND((sizeof (_Jv_InterpMethod)
 | 
						|
	       + exc_count*sizeof (_Jv_InterpException)), 4);
 | 
						|
  }
 | 
						|
 | 
						|
  _Jv_InterpException * exceptions ()
 | 
						|
  {
 | 
						|
    return (_Jv_InterpException*) (this+1);
 | 
						|
  }
 | 
						|
 | 
						|
  static size_t size (int exc_count, int code_length)
 | 
						|
  {
 | 
						|
    return 
 | 
						|
      ROUND ((sizeof (_Jv_InterpMethod) 
 | 
						|
	      + (exc_count * sizeof (_Jv_InterpException))), 4)
 | 
						|
      + code_length;
 | 
						|
  }
 | 
						|
 | 
						|
  // return the method's invocation pointer (a stub).
 | 
						|
  void *ncode (jclass);
 | 
						|
  void compile (const void * const *);
 | 
						|
 | 
						|
#if FFI_NATIVE_RAW_API
 | 
						|
#  define INTERP_FFI_RAW_TYPE ffi_raw
 | 
						|
#else
 | 
						|
#  define INTERP_FFI_RAW_TYPE ffi_java_raw
 | 
						|
#endif
 | 
						|
 | 
						|
  static void run_normal (ffi_cif*, void*, INTERP_FFI_RAW_TYPE*, void*);
 | 
						|
  static void run_synch_object (ffi_cif*, void*, INTERP_FFI_RAW_TYPE*, void*);
 | 
						|
  static void run_class (ffi_cif*, void*, INTERP_FFI_RAW_TYPE*, void*);
 | 
						|
  static void run_synch_class (ffi_cif*, void*, INTERP_FFI_RAW_TYPE*, void*);
 | 
						|
  
 | 
						|
  static void run_normal_debug (ffi_cif*, void*, INTERP_FFI_RAW_TYPE*, void*);
 | 
						|
  static void run_synch_object_debug (ffi_cif*, void*, INTERP_FFI_RAW_TYPE*,
 | 
						|
				      void*);
 | 
						|
  static void run_class_debug (ffi_cif*, void*, INTERP_FFI_RAW_TYPE*, void*);
 | 
						|
  static void run_synch_class_debug (ffi_cif*, void*, INTERP_FFI_RAW_TYPE*,
 | 
						|
				     void*);
 | 
						|
 | 
						|
  static void run (void *, INTERP_FFI_RAW_TYPE *, _Jv_InterpMethod *);
 | 
						|
  static void run_debug (void *, INTERP_FFI_RAW_TYPE *, _Jv_InterpMethod *);
 | 
						|
  
 | 
						|
 | 
						|
  
 | 
						|
  // Returns source file line number for given PC value, or -1 if line
 | 
						|
  // number info is unavailable.
 | 
						|
  int get_source_line(pc_t mpc);
 | 
						|
 | 
						|
   public:
 | 
						|
 | 
						|
  // Convenience function for indexing bytecode PC/insn slots in
 | 
						|
  // line tables for JDWP
 | 
						|
  jlong insn_index (pc_t pc);
 | 
						|
  
 | 
						|
  // Helper function used to check if there is a handler for an exception
 | 
						|
  // present at this code index
 | 
						|
  jboolean check_handler (pc_t *pc, _Jv_InterpMethod *meth,
 | 
						|
                     java::lang::Throwable *ex);
 | 
						|
   
 | 
						|
  /* Get the line table for this method.
 | 
						|
   * start  is the lowest index in the method
 | 
						|
   * end    is the  highest index in the method
 | 
						|
   * line_numbers is an array to hold the list of source line numbers
 | 
						|
   * code_indices is an array to hold the corresponding list of code indices
 | 
						|
   */
 | 
						|
  void get_line_table (jlong& start, jlong& end, jintArray& line_numbers,
 | 
						|
		       jlongArray& code_indices);
 | 
						|
  
 | 
						|
  int get_max_locals ()
 | 
						|
  {
 | 
						|
    return static_cast<int> (max_locals);
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* Get info for a local variable of this method.
 | 
						|
   * If there is no loca_var_table for this method it will return -1.
 | 
						|
   * table_slot  indicates which slot in the local_var_table to get, if there is
 | 
						|
   * no variable at this location it will return 0.
 | 
						|
   * Otherwise, it will return the number of table slots after the selected
 | 
						|
   * slot, indexed from 0.
 | 
						|
   * 
 | 
						|
   * Example: there are 5 slots in the table, you request slot 0 so it will
 | 
						|
   * return 4.
 | 
						|
   */
 | 
						|
  int get_local_var_table (char **name, char **sig, char **generic_sig,
 | 
						|
                           jlong *startloc, jint *length, jint *slot,
 | 
						|
                           int table_slot);
 | 
						|
 | 
						|
  /* Installs a break instruction at the given code index. Returns
 | 
						|
     the pc_t of the breakpoint or NULL if index is invalid. */
 | 
						|
  pc_t install_break (jlong index);
 | 
						|
 | 
						|
  // Gets the instruction at the given index
 | 
						|
  pc_t get_insn (jlong index);
 | 
						|
 | 
						|
  /* Writes the given instruction at the given code index. Returns
 | 
						|
     the insn or NULL if index is invalid. */
 | 
						|
  pc_t set_insn (jlong index, pc_t insn);
 | 
						|
 | 
						|
  // Is the given location in this method a breakpoint?
 | 
						|
  bool breakpoint_at (jlong index);
 | 
						|
 | 
						|
#ifdef DIRECT_THREADED
 | 
						|
  friend void _Jv_CompileMethod (_Jv_InterpMethod*);
 | 
						|
#endif
 | 
						|
  
 | 
						|
  friend class _Jv_ClassReader;
 | 
						|
  friend class _Jv_BytecodeVerifier;
 | 
						|
  friend class _Jv_StackTrace;
 | 
						|
  friend class _Jv_InterpreterEngine;
 | 
						|
 | 
						|
#ifdef JV_MARKOBJ_DECL
 | 
						|
  friend JV_MARKOBJ_DECL;
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
class _Jv_InterpClass
 | 
						|
{
 | 
						|
  _Jv_MethodBase **interpreted_methods;
 | 
						|
  _Jv_ushort     *field_initializers;
 | 
						|
  jstring source_file_name;
 | 
						|
  _Jv_ClosureList **closures;
 | 
						|
 | 
						|
  friend class _Jv_ClassReader;
 | 
						|
  friend class _Jv_InterpMethod;
 | 
						|
  friend class _Jv_StackTrace;
 | 
						|
  friend class _Jv_InterpreterEngine;
 | 
						|
 | 
						|
  friend void  _Jv_InitField (jobject, jclass, int);
 | 
						|
#ifdef JV_MARKOBJ_DECL
 | 
						|
  friend JV_MARKOBJ_DECL;
 | 
						|
#endif
 | 
						|
 | 
						|
  friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass);
 | 
						|
  friend jstring _Jv_GetInterpClassSourceFile (jclass);
 | 
						|
};
 | 
						|
 | 
						|
extern inline _Jv_MethodBase **
 | 
						|
_Jv_GetFirstMethod (_Jv_InterpClass *klass)
 | 
						|
{
 | 
						|
  return klass->interpreted_methods;
 | 
						|
}
 | 
						|
 | 
						|
struct _Jv_ResolvedMethod
 | 
						|
{
 | 
						|
  jint            stack_item_count;	
 | 
						|
  jclass          klass;
 | 
						|
  _Jv_Method*     method;
 | 
						|
 | 
						|
  // a resolved method holds the cif in-line, so that _Jv_MarkObj just needs
 | 
						|
  // to mark the resolved method to hold on to the cif.  Some memory could be
 | 
						|
  // saved by keeping a cache of cif's, since many will be the same.
 | 
						|
  ffi_cif         cif;
 | 
						|
  ffi_type *      arg_types[0];
 | 
						|
};
 | 
						|
 | 
						|
class _Jv_JNIMethod : public _Jv_MethodBase
 | 
						|
{
 | 
						|
  // The underlying function.  If NULL we have to look for the
 | 
						|
  // function.
 | 
						|
  void *function;
 | 
						|
 | 
						|
  // This is the CIF used by the JNI function.
 | 
						|
  ffi_cif jni_cif;
 | 
						|
 | 
						|
  // These are the argument types used by the JNI function.
 | 
						|
  ffi_type **jni_arg_types;
 | 
						|
 | 
						|
  // This function is used when making a JNI call from the interpreter.
 | 
						|
  static void call (ffi_cif *, void *, INTERP_FFI_RAW_TYPE *, void *);
 | 
						|
 | 
						|
  void *ncode (jclass);
 | 
						|
 | 
						|
  friend class _Jv_ClassReader;
 | 
						|
  friend class _Jv_InterpreterEngine;
 | 
						|
 | 
						|
#ifdef JV_MARKOBJ_DECL
 | 
						|
  friend JV_MARKOBJ_DECL;
 | 
						|
#endif
 | 
						|
 | 
						|
public:
 | 
						|
  // FIXME: this is ugly.
 | 
						|
  void set_function (void *f)
 | 
						|
  {
 | 
						|
    function = f;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
//  The composite call stack as represented by a linked list of frames
 | 
						|
class _Jv_Frame
 | 
						|
{
 | 
						|
public:
 | 
						|
  java::lang::Thread *thread;
 | 
						|
 | 
						|
  union
 | 
						|
  {
 | 
						|
    _Jv_MethodBase *self;
 | 
						|
    void *meth;
 | 
						|
    _Jv_Method *proxyMethod;
 | 
						|
  };
 | 
						|
  
 | 
						|
  //The full list of frames, JNI and interpreted
 | 
						|
  _Jv_Frame *next;
 | 
						|
  _Jv_FrameType frame_type;
 | 
						|
  
 | 
						|
  _Jv_Frame (_Jv_MethodBase *s, java::lang::Thread *thr, _Jv_FrameType type)
 | 
						|
  {
 | 
						|
    self = s;
 | 
						|
    frame_type = type;
 | 
						|
    next = (_Jv_Frame *) thr->frame;
 | 
						|
    thr->frame = (gnu::gcj::RawData *) this;
 | 
						|
    thread = thr;
 | 
						|
  }
 | 
						|
 | 
						|
  ~_Jv_Frame ()
 | 
						|
  {
 | 
						|
    thread->frame = (gnu::gcj::RawData *) next;
 | 
						|
  }
 | 
						|
 | 
						|
  int depth ()
 | 
						|
  {
 | 
						|
    int depth = 0;
 | 
						|
    struct _Jv_Frame *f;
 | 
						|
    for (f = this; f != NULL; f = f->next)
 | 
						|
      ++depth;
 | 
						|
 | 
						|
    return depth;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
// An interpreted frame in the call stack
 | 
						|
class _Jv_InterpFrame : public _Jv_Frame
 | 
						|
{
 | 
						|
public:
 | 
						|
  
 | 
						|
  // Keep the purely interpreted list around so as not to break backtraces
 | 
						|
  _Jv_InterpFrame *next_interp;
 | 
						|
  
 | 
						|
  union
 | 
						|
  {
 | 
						|
    pc_t pc;
 | 
						|
    jclass proxyClass;
 | 
						|
  };
 | 
						|
  
 | 
						|
  // Pointer to the actual pc value.
 | 
						|
  pc_t *pc_ptr;
 | 
						|
 | 
						|
  //Debug info for local variables.
 | 
						|
  _Jv_word *locals;
 | 
						|
  char *locals_type;
 | 
						|
 | 
						|
  // Object pointer for this frame ("this")
 | 
						|
  jobject obj_ptr;
 | 
						|
 | 
						|
  _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyCls = NULL,
 | 
						|
                   pc_t *pc = NULL, 
 | 
						|
		   _Jv_FrameType frame_type = frame_interpreter)
 | 
						|
  : _Jv_Frame (reinterpret_cast<_Jv_MethodBase *> (meth), thr,
 | 
						|
	             frame_type)
 | 
						|
  {
 | 
						|
    next_interp = (_Jv_InterpFrame *) thr->interp_frame;
 | 
						|
    proxyClass = proxyCls;
 | 
						|
    thr->interp_frame = (gnu::gcj::RawData *) this;
 | 
						|
    obj_ptr = NULL;
 | 
						|
    pc_ptr = pc;
 | 
						|
  }
 | 
						|
 | 
						|
  ~_Jv_InterpFrame ()
 | 
						|
  {
 | 
						|
    thread->interp_frame = (gnu::gcj::RawData *) next_interp;
 | 
						|
  }
 | 
						|
 | 
						|
  jobject get_this_ptr ()
 | 
						|
  {
 | 
						|
    return obj_ptr;
 | 
						|
  }
 | 
						|
  
 | 
						|
  pc_t get_pc ()
 | 
						|
  {
 | 
						|
    pc_t pc;
 | 
						|
    
 | 
						|
    // If the PC_PTR is NULL, we are not debugging.
 | 
						|
    if (pc_ptr == NULL)
 | 
						|
      pc = 0;
 | 
						|
    else
 | 
						|
      pc = *pc_ptr - 1;
 | 
						|
    
 | 
						|
    return pc;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
// A native frame in the call stack really just a placeholder
 | 
						|
class _Jv_NativeFrame : public _Jv_Frame
 | 
						|
{
 | 
						|
public:
 | 
						|
 | 
						|
  _Jv_NativeFrame (_Jv_JNIMethod *s, java::lang::Thread *thr)
 | 
						|
  : _Jv_Frame (s, thr, frame_native)
 | 
						|
  {
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
#ifdef DIRECT_THREADED
 | 
						|
// This class increments and decrements the thread_count field in an
 | 
						|
// interpreted method.  On entry to the interpreter a
 | 
						|
// ThreadCountAdjuster is created when increments the thread_count in
 | 
						|
// the current method and uses the next_interp field in the frame to
 | 
						|
// find the previous method and decrement its thread_count.
 | 
						|
class ThreadCountAdjuster
 | 
						|
{
 | 
						|
 | 
						|
  // A class used to handle the rewrite_insn_mutex while we're
 | 
						|
  // adjusting the thread_count in a method.  Unlocking the mutex in a
 | 
						|
  // destructor ensures that it's unlocked even if (for example) a
 | 
						|
  // segfault occurs in the critical section.
 | 
						|
  class MutexLock
 | 
						|
  {
 | 
						|
  private:
 | 
						|
    _Jv_Mutex_t *mutex;
 | 
						|
  public:
 | 
						|
    MutexLock (_Jv_Mutex_t *m)
 | 
						|
    {
 | 
						|
      mutex = m;
 | 
						|
      _Jv_MutexLock (mutex);
 | 
						|
    }
 | 
						|
    ~MutexLock ()
 | 
						|
    {
 | 
						|
      _Jv_MutexUnlock (mutex);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  _Jv_InterpMethod *method;
 | 
						|
  _Jv_InterpMethod *next_method;
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
  ThreadCountAdjuster (_Jv_InterpMethod *m, _Jv_InterpFrame *fr)
 | 
						|
  {
 | 
						|
    MutexLock lock (&::_Jv_InterpMethod::rewrite_insn_mutex);
 | 
						|
 | 
						|
    method = m;
 | 
						|
    next_method = NULL;
 | 
						|
 | 
						|
    _Jv_InterpFrame *next_interp = fr->next_interp;
 | 
						|
 | 
						|
    // Record the fact that we're executing this method and that
 | 
						|
    // we're no longer executing the method that called us.
 | 
						|
    method->thread_count++;
 | 
						|
 | 
						|
    if (next_interp && next_interp->frame_type == frame_interpreter)
 | 
						|
      {
 | 
						|
	next_method 
 | 
						|
	  = reinterpret_cast<_Jv_InterpMethod *> (next_interp->meth);
 | 
						|
	next_method->thread_count--;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  ~ThreadCountAdjuster ()
 | 
						|
  {
 | 
						|
    MutexLock lock (&::_Jv_InterpMethod::rewrite_insn_mutex);
 | 
						|
 | 
						|
    // We're going to return to the method that called us, so bump its
 | 
						|
    // thread_count and decrement our own.
 | 
						|
 | 
						|
    method->thread_count--;
 | 
						|
 | 
						|
    if (next_method)
 | 
						|
      next_method->thread_count++;
 | 
						|
  }
 | 
						|
};
 | 
						|
#endif // DIRECT_THREADED
 | 
						|
 | 
						|
#endif /* INTERPRETER */
 | 
						|
 | 
						|
#endif /* __JAVA_INTERP_H__ */
 |