java-interp.h 12.2 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, 2007  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 24
enum _Jv_FrameType
{
  frame_native,
  frame_interpreter,
  frame_proxy
};

Anthony Green committed
25 26 27 28 29 30
#ifdef INTERPRETER

#pragma interface

#include <java/lang/Class.h>
#include <java/lang/ClassLoader.h>
31
#include <java/lang/reflect/Modifier.h>
32 33
#include <java/lang/Thread.h>
#include <gnu/gcj/RawData.h>
Anthony Green committed
34

35 36 37 38 39
// 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
40 41 42 43
#include <ffi.h>

struct _Jv_ResolvedMethod;

44
void _Jv_InitInterpreter ();
45
void _Jv_DefineClass (jclass, jbyteArray, jint, jint,
46 47
		      java::security::ProtectionDomain *,
		      _Jv_Utf8Const **);
Anthony Green committed
48 49 50

void _Jv_InitField (jobject, jclass, int);
void * _Jv_AllocMethodInvocation (jsize size);
51 52 53
int  _Jv_count_arguments (_Jv_Utf8Const *signature,
			  jboolean staticp = true);
void _Jv_VerifyMethod (_Jv_InterpMethod *method);
54
void _Jv_CompileMethod (_Jv_InterpMethod* method);
55 56 57 58 59 60
int _Jv_init_cif (_Jv_Utf8Const* signature,
		  int arg_count,
		  jboolean staticp,
		  ffi_cif *cif,
		  ffi_type **arg_types,
		  ffi_type **rtype_p);
Anthony Green committed
61 62 63 64 65 66

/* 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;
67 68 69 70 71 72 73 74 75

// 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
76

77 78
class _Jv_InterpException
{
79 80 81 82
  _Jv_InterpPC start_pc;
  _Jv_InterpPC end_pc;
  _Jv_InterpPC handler_pc;
  _Jv_InterpPC handler_type;
Anthony Green committed
83 84 85

  friend class _Jv_ClassReader;
  friend class _Jv_InterpMethod;
86
  friend class _Jv_BytecodeVerifier;
Anthony Green committed
87 88
};

89 90 91 92 93 94
// Base class for method representations.  Subclasses are interpreted
// and JNI methods.
class _Jv_MethodBase
{
protected:
  // The class which defined this method.
95
  jclass defining_class;
96 97 98

  // The method description.
  _Jv_Method *self;
99 100 101

  // Size of raw arguments.
  _Jv_ushort args_raw_size;
102

103
  friend class _Jv_InterpreterEngine;
104

105 106 107 108 109
public:
  _Jv_Method *get_method ()
  {
    return self;
  }
110 111
};

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
// 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;
};

147
// This structure holds local variable information.
148 149
// Like _Jv_LineTableEntry above, it is remapped when the method is
// compiled for direct threading.
150 151
struct _Jv_LocalVarTableEntry
{
152 153 154 155 156 157 158 159
  // First PC value at which variable is live
  union
  {
    pc_t pc;
    int bytecode_pc;
  };

  // length of visibility of variable
160
  int length;
161 162

  // variable name
163
  char *name;
164 165

  // type description
166
  char *descriptor;
167 168

  // stack slot number (long and double occupy slot and slot + 1)
169 170 171
  int slot;
};

172 173
class _Jv_InterpMethod : public _Jv_MethodBase
{
174 175 176 177 178 179 180 181
  // Breakpoint instruction
  static pc_t breakpoint_insn;
#ifdef DIRECT_THREADED
  static insn_slot bp_insn_slot;
#else
  static unsigned char bp_insn_opcode;
#endif

Anthony Green committed
182 183 184 185 186
  _Jv_ushort       max_stack;
  _Jv_ushort       max_locals;
  int              code_length;

  _Jv_ushort       exc_count;
187
  bool             is_15;
Anthony Green committed
188

189 190 191
  // Length of the line_table - when this is zero then line_table is NULL.
  int line_table_len;  
  _Jv_LineTableEntry *line_table;
192 193 194 195
  
  // The local variable table length and the table itself
  int local_var_table_len;
  _Jv_LocalVarTableEntry *local_var_table;
196

197
  pc_t prepared;
198
  int number_insn_slots;
199

Anthony Green committed
200 201 202 203 204 205 206
  unsigned char* bytecode () 
  {
    return 
      ((unsigned char*)this) 
      + ROUND((sizeof (_Jv_InterpMethod)
	       + exc_count*sizeof (_Jv_InterpException)), 4);
  }
207

Anthony Green committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221
  _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).
222
  void *ncode (jclass);
223
  void compile (const void * const *);
Anthony Green committed
224

225 226 227 228 229
#if FFI_NATIVE_RAW_API
#  define INTERP_FFI_RAW_TYPE ffi_raw
#else
#  define INTERP_FFI_RAW_TYPE ffi_java_raw
#endif
Anthony Green committed
230

231 232 233 234 235 236 237 238 239 240 241 242 243 244
  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 *);
245
  
246

247
  
248 249 250
  // 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
251

252 253
   public:

254 255 256
  // Convenience function for indexing bytecode PC/insn slots in
  // line tables for JDWP
  jlong insn_index (pc_t pc);
257 258 259 260 261
  
  // 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);
262
   
263 264 265 266 267 268 269 270
  /* 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);
271 272 273 274 275
  
  int get_max_locals ()
  {
    return static_cast<int> (max_locals);
  }
276 277 278 279 280 281 282 283 284 285 286 287 288 289
  
  /* 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);
290

291 292 293 294
  /* 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);

295 296 297 298 299 300 301
  // 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);

302 303 304
  // Is the given location in this method a breakpoint?
  bool breakpoint_at (jlong index);

305 306 307 308
#ifdef DIRECT_THREADED
  friend void _Jv_CompileMethod (_Jv_InterpMethod*);
#endif
  
Anthony Green committed
309
  friend class _Jv_ClassReader;
310
  friend class _Jv_BytecodeVerifier;
311
  friend class _Jv_StackTrace;
312
  friend class _Jv_InterpreterEngine;
Anthony Green committed
313

314 315 316
#ifdef JV_MARKOBJ_DECL
  friend JV_MARKOBJ_DECL;
#endif
Anthony Green committed
317 318
};

319
class _Jv_InterpClass
Anthony Green committed
320
{
321
  _Jv_MethodBase **interpreted_methods;
322 323
  _Jv_ushort     *field_initializers;
  jstring source_file_name;
324
  _Jv_ClosureList **closures;
Anthony Green committed
325 326 327

  friend class _Jv_ClassReader;
  friend class _Jv_InterpMethod;
328
  friend class _Jv_StackTrace;
329
  friend class _Jv_InterpreterEngine;
330

Anthony Green committed
331
  friend void  _Jv_InitField (jobject, jclass, int);
332 333 334
#ifdef JV_MARKOBJ_DECL
  friend JV_MARKOBJ_DECL;
#endif
335 336

  friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass);
337
  friend jstring _Jv_GetInterpClassSourceFile (jclass);
Anthony Green committed
338 339
};

340 341 342 343 344 345
extern inline _Jv_MethodBase **
_Jv_GetFirstMethod (_Jv_InterpClass *klass)
{
  return klass->interpreted_methods;
}

346 347
struct _Jv_ResolvedMethod
{
Anthony Green committed
348 349 350 351 352 353 354 355 356 357 358
  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];
};

359 360 361 362 363 364
class _Jv_JNIMethod : public _Jv_MethodBase
{
  // The underlying function.  If NULL we have to look for the
  // function.
  void *function;

365 366 367 368 369 370
  // 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;

371
  // This function is used when making a JNI call from the interpreter.
372
  static void call (ffi_cif *, void *, INTERP_FFI_RAW_TYPE *, void *);
373

374
  void *ncode (jclass);
375 376

  friend class _Jv_ClassReader;
377 378 379 380 381
  friend class _Jv_InterpreterEngine;

#ifdef JV_MARKOBJ_DECL
  friend JV_MARKOBJ_DECL;
#endif
382 383 384 385 386 387 388

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

391 392 393 394 395 396
//  The composite call stack as represented by a linked list of frames
class _Jv_Frame
{
public:
  java::lang::Thread *thread;

397 398
  union
  {
399
    _Jv_MethodBase *self;
400 401 402
    void *meth;
    _Jv_Method *proxyMethod;
  };
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
  
  //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;
  }
421 422 423 424 425 426 427 428 429 430

  int depth ()
  {
    int depth = 0;
    struct _Jv_Frame *f;
    for (f = this; f != NULL; f = f->next)
      ++depth;

    return depth;
  }
431 432 433 434 435 436 437 438 439 440
};

// 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;
  
441 442 443 444 445
  union
  {
    pc_t pc;
    jclass proxyClass;
  };
446 447 448
  
  // Pointer to the actual pc value.
  pc_t *pc_ptr;
449 450 451 452 453

  //Debug info for local variables.
  _Jv_word *locals;
  char *locals_type;

454 455 456
  // Object pointer for this frame ("this")
  jobject obj_ptr;

457 458
  _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyCls = NULL,
                   pc_t *pc = NULL)
459 460
  : _Jv_Frame (reinterpret_cast<_Jv_MethodBase *> (meth), thr,
	             frame_interpreter)
461
  {
462 463
    next_interp = (_Jv_InterpFrame *) thr->interp_frame;
    proxyClass = proxyCls;
464
    thr->interp_frame = (gnu::gcj::RawData *) this;
465
    obj_ptr = NULL;
466
    pc_ptr = pc;
467 468
  }

469
  ~_Jv_InterpFrame ()
470
  {
471 472
    thread->interp_frame = (gnu::gcj::RawData *) next_interp;
  }
473 474 475 476

  jobject get_this_ptr ()
  {
    return obj_ptr;
477 478 479 480 481 482 483 484 485 486
  }
  
  pc_t get_pc ()
  {
    pc_t pc;
    
    // If the PC_PTR is NULL, we are not debugging.
    if (pc_ptr == NULL)
      pc = 0;
    else
487
      pc = *pc_ptr - 1;
488
    
489
    return pc;
490
  }
491 492 493 494 495 496 497 498 499 500
};

// 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)
  {
501 502 503
  }
};

504 505
#endif /* INTERPRETER */

Anthony Green committed
506
#endif /* __JAVA_INTERP_H__ */