java-interp.h 7.45 KB
Newer Older
Anthony Green committed
1 2
// java-interp.h - Header file for the bytecode interpreter.  -*- c++ -*-

3
/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006  Free Software Foundation
Anthony Green committed
4 5 6 7 8 9 10 11 12 13 14 15

   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>
16
#include <gnu/gcj/runtime/NameFinder.h>
Anthony Green committed
17 18 19 20 21 22 23

#ifdef INTERPRETER

#pragma interface

#include <java/lang/Class.h>
#include <java/lang/ClassLoader.h>
24
#include <java/lang/reflect/Modifier.h>
25 26
#include <java/lang/Thread.h>
#include <gnu/gcj/RawData.h>
Anthony Green committed
27

28 29 30 31 32
// 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

Anthony Green committed
33 34 35 36
#include <ffi.h>

struct _Jv_ResolvedMethod;

37
void _Jv_InitInterpreter ();
38
void _Jv_DefineClass (jclass, jbyteArray, jint, jint,
39 40
		      java::security::ProtectionDomain *,
		      _Jv_Utf8Const **);
Anthony Green committed
41 42 43

void _Jv_InitField (jobject, jclass, int);
void * _Jv_AllocMethodInvocation (jsize size);
44 45 46
int  _Jv_count_arguments (_Jv_Utf8Const *signature,
			  jboolean staticp = true);
void _Jv_VerifyMethod (_Jv_InterpMethod *method);
47
void _Jv_CompileMethod (_Jv_InterpMethod* method);
Anthony Green committed
48 49 50 51 52 53

/* 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;
54 55 56 57 58 59 60 61 62

// 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;
};
Anthony Green committed
63

64 65
class _Jv_InterpException
{
66 67 68 69
  _Jv_InterpPC start_pc;
  _Jv_InterpPC end_pc;
  _Jv_InterpPC handler_pc;
  _Jv_InterpPC handler_type;
Anthony Green committed
70 71 72

  friend class _Jv_ClassReader;
  friend class _Jv_InterpMethod;
73
  friend class _Jv_BytecodeVerifier;
Anthony Green committed
74 75
};

76 77 78 79 80 81
// Base class for method representations.  Subclasses are interpreted
// and JNI methods.
class _Jv_MethodBase
{
protected:
  // The class which defined this method.
82
  jclass defining_class;
83 84 85

  // The method description.
  _Jv_Method *self;
86 87 88

  // Size of raw arguments.
  _Jv_ushort args_raw_size;
89

90
  friend class _Jv_InterpreterEngine;
91

92 93 94 95 96
public:
  _Jv_Method *get_method ()
  {
    return self;
  }
97 98
};

99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
// 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;
};

134 135
class _Jv_InterpMethod : public _Jv_MethodBase
{
Anthony Green committed
136 137 138 139 140
  _Jv_ushort       max_stack;
  _Jv_ushort       max_locals;
  int              code_length;

  _Jv_ushort       exc_count;
141
  bool             is_15;
Anthony Green committed
142

143 144 145 146
  // Length of the line_table - when this is zero then line_table is NULL.
  int line_table_len;  
  _Jv_LineTableEntry *line_table;

147
  void *prepared;
148
  int number_insn_slots;
149

Anthony Green committed
150 151 152 153 154 155 156
  unsigned char* bytecode () 
  {
    return 
      ((unsigned char*)this) 
      + ROUND((sizeof (_Jv_InterpMethod)
	       + exc_count*sizeof (_Jv_InterpException)), 4);
  }
157

Anthony Green committed
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
  _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 ();
173
  void compile (const void * const *);
Anthony Green committed
174

Anthony Green committed
175 176
  static void run_normal (ffi_cif*, void*, ffi_raw*, void*);
  static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*);
177
  static void run_class (ffi_cif*, void*, ffi_raw*, void*);
Anthony Green committed
178
  static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
Anthony Green committed
179

180 181 182 183 184
  static void run (void*, ffi_raw *, _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);
Anthony Green committed
185

186 187 188 189 190 191
#ifdef DIRECT_THREADED
  // Convenience function for indexing bytecode PC/insn slots in
  // line tables for JDWP
  jlong insn_index (pc_t pc);
#endif

Anthony Green committed
192 193
 public:

194 195 196 197 198 199 200 201 202
  /* 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);

203 204 205 206
#ifdef DIRECT_THREADED
  friend void _Jv_CompileMethod (_Jv_InterpMethod*);
#endif
  
Anthony Green committed
207
  friend class _Jv_ClassReader;
208
  friend class _Jv_BytecodeVerifier;
209
  friend class _Jv_StackTrace;
210
  friend class _Jv_InterpreterEngine;
Anthony Green committed
211

212 213 214
#ifdef JV_MARKOBJ_DECL
  friend JV_MARKOBJ_DECL;
#endif
Anthony Green committed
215 216
};

217
class _Jv_InterpClass
Anthony Green committed
218
{
219
  _Jv_MethodBase **interpreted_methods;
220 221
  _Jv_ushort     *field_initializers;
  jstring source_file_name;
Anthony Green committed
222 223 224

  friend class _Jv_ClassReader;
  friend class _Jv_InterpMethod;
225
  friend class _Jv_StackTrace;
226
  friend class _Jv_InterpreterEngine;
227

Anthony Green committed
228
  friend void  _Jv_InitField (jobject, jclass, int);
229 230 231
#ifdef JV_MARKOBJ_DECL
  friend JV_MARKOBJ_DECL;
#endif
232 233

  friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass);
Anthony Green committed
234 235
};

236 237 238 239 240 241
extern inline _Jv_MethodBase **
_Jv_GetFirstMethod (_Jv_InterpClass *klass)
{
  return klass->interpreted_methods;
}

242 243
struct _Jv_ResolvedMethod
{
Anthony Green committed
244 245 246 247 248 249 250 251 252 253 254
  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];
};

255 256 257 258 259 260
class _Jv_JNIMethod : public _Jv_MethodBase
{
  // The underlying function.  If NULL we have to look for the
  // function.
  void *function;

261 262 263 264 265 266
  // 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;

267 268 269 270 271 272
  // This function is used when making a JNI call from the interpreter.
  static void call (ffi_cif *, void *, ffi_raw *, void *);

  void *ncode ();

  friend class _Jv_ClassReader;
273 274 275 276 277
  friend class _Jv_InterpreterEngine;

#ifdef JV_MARKOBJ_DECL
  friend JV_MARKOBJ_DECL;
#endif
278 279 280 281 282 283 284

public:
  // FIXME: this is ugly.
  void set_function (void *f)
  {
    function = f;
  }
285 286
};

287 288
// The interpreted call stack, represented by a linked list of frames.
struct _Jv_InterpFrame
289
{
290
  _Jv_InterpMethod *self;
291
  java::lang::Thread *thread;
292 293
  _Jv_InterpFrame *next;
  pc_t pc;
294

295
  _Jv_InterpFrame (_Jv_InterpMethod *s, java::lang::Thread *thr)
296 297
  {
    self = s;
298 299 300
    thread = thr;
    next = (_Jv_InterpFrame *) thr->interp_frame;
    thr->interp_frame = (gnu::gcj::RawData *) this;
301
    pc = NULL;
302 303
  }

304
  ~_Jv_InterpFrame ()
305
  {
306
    thread->interp_frame = (gnu::gcj::RawData *) next;
307 308 309
  }
};

310 311
#endif /* INTERPRETER */

Anthony Green committed
312
#endif /* __JAVA_INTERP_H__ */