]>
Commit | Line | Data |
---|---|---|
58eb6e7c AG |
1 | // java-interp.h - Header file for the bytecode interpreter. -*- c++ -*- |
2 | ||
d0f4aa53 | 3 | /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation |
58eb6e7c AG |
4 | |
5 | This file is part of libgcj. | |
6 | ||
7 | This software is copyrighted work licensed under the terms of the | |
8 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | #ifndef __JAVA_INTERP_H__ | |
12 | #define __JAVA_INTERP_H__ | |
13 | ||
58eb6e7c AG |
14 | #include <jvm.h> |
15 | #include <java-cpool.h> | |
3308c46e | 16 | #include <gnu/gcj/runtime/NameFinder.h> |
58eb6e7c AG |
17 | |
18 | #ifdef INTERPRETER | |
19 | ||
20 | #pragma interface | |
21 | ||
22 | #include <java/lang/Class.h> | |
23 | #include <java/lang/ClassLoader.h> | |
a1aba4f9 | 24 | #include <java/lang/reflect/Modifier.h> |
1349c688 BM |
25 | #include <java/lang/Thread.h> |
26 | #include <gnu/gcj/RawData.h> | |
58eb6e7c | 27 | |
18744d9b BM |
28 | // Define this to get the direct-threaded interpreter. If undefined, |
29 | // we revert to a basic bytecode interpreter. The former is faster | |
30 | // but uses more memory. | |
31 | #define DIRECT_THREADED | |
32 | ||
58eb6e7c | 33 | #include <ffi.h> |
58eb6e7c | 34 | |
58eb6e7c AG |
35 | struct _Jv_ResolvedMethod; |
36 | ||
6187fd28 | 37 | void _Jv_InitInterpreter (); |
36739040 | 38 | void _Jv_DefineClass (jclass, jbyteArray, jint, jint, |
42c51695 TT |
39 | java::security::ProtectionDomain *, |
40 | _Jv_Utf8Const **); | |
58eb6e7c AG |
41 | |
42 | void _Jv_InitField (jobject, jclass, int); | |
43 | void * _Jv_AllocMethodInvocation (jsize size); | |
a12fe13d TT |
44 | int _Jv_count_arguments (_Jv_Utf8Const *signature, |
45 | jboolean staticp = true); | |
46 | void _Jv_VerifyMethod (_Jv_InterpMethod *method); | |
d0f4aa53 | 47 | void _Jv_CompileMethod (_Jv_InterpMethod* method); |
97b8365c TT |
48 | int _Jv_init_cif (_Jv_Utf8Const* signature, |
49 | int arg_count, | |
50 | jboolean staticp, | |
51 | ffi_cif *cif, | |
52 | ffi_type **arg_types, | |
53 | ffi_type **rtype_p); | |
58eb6e7c | 54 | |
58eb6e7c AG |
55 | /* the interpreter is written in C++, primarily because it makes it easy for |
56 | * the entire thing to be "friend" with class Class. */ | |
57 | ||
58 | class _Jv_InterpClass; | |
59 | class _Jv_InterpMethod; | |
fdae83ab TT |
60 | |
61 | // Before a method is "compiled" we store values as the bytecode PC, | |
62 | // an int. Afterwards we store them as pointers into the prepared | |
63 | // code itself. | |
64 | union _Jv_InterpPC | |
65 | { | |
66 | int i; | |
67 | void *p; | |
68 | }; | |
58eb6e7c | 69 | |
a12fe13d TT |
70 | class _Jv_InterpException |
71 | { | |
fdae83ab TT |
72 | _Jv_InterpPC start_pc; |
73 | _Jv_InterpPC end_pc; | |
74 | _Jv_InterpPC handler_pc; | |
75 | _Jv_InterpPC handler_type; | |
58eb6e7c AG |
76 | |
77 | friend class _Jv_ClassReader; | |
78 | friend class _Jv_InterpMethod; | |
a12fe13d | 79 | friend class _Jv_BytecodeVerifier; |
58eb6e7c AG |
80 | }; |
81 | ||
f39b788a TT |
82 | // Base class for method representations. Subclasses are interpreted |
83 | // and JNI methods. | |
84 | class _Jv_MethodBase | |
85 | { | |
86 | protected: | |
87 | // The class which defined this method. | |
f5310108 | 88 | jclass defining_class; |
f39b788a TT |
89 | |
90 | // The method description. | |
91 | _Jv_Method *self; | |
d348bda4 TT |
92 | |
93 | // Size of raw arguments. | |
94 | _Jv_ushort args_raw_size; | |
8ade4771 | 95 | |
36739040 | 96 | friend class _Jv_InterpreterEngine; |
90471585 | 97 | |
8ade4771 TT |
98 | public: |
99 | _Jv_Method *get_method () | |
100 | { | |
101 | return self; | |
102 | } | |
f39b788a TT |
103 | }; |
104 | ||
18744d9b BM |
105 | // The type of the PC depends on whether we're doing direct threading |
106 | // or a more ordinary bytecode interpreter. | |
107 | #ifdef DIRECT_THREADED | |
108 | // Slot in the "compiled" form of the bytecode. | |
109 | union insn_slot | |
110 | { | |
111 | // Address of code. | |
112 | void *insn; | |
113 | // An integer value used by an instruction. | |
114 | jint int_val; | |
115 | // A pointer value used by an instruction. | |
116 | void *datum; | |
117 | }; | |
118 | ||
119 | typedef insn_slot *pc_t; | |
120 | #else | |
121 | typedef unsigned char *pc_t; | |
122 | #endif | |
123 | ||
124 | ||
125 | // This structure holds the bytecode pc and corresponding source code | |
126 | // line number. An array (plus length field) of this structure is put | |
127 | // in each _Jv_InterpMethod and used to resolve the (internal) program | |
128 | // counter of the interpreted method to an actual java source file | |
129 | // line. | |
130 | struct _Jv_LineTableEntry | |
131 | { | |
132 | union | |
133 | { | |
134 | pc_t pc; | |
135 | int bytecode_pc; | |
136 | }; | |
137 | int line; | |
138 | }; | |
139 | ||
facc279f TT |
140 | class _Jv_InterpMethod : public _Jv_MethodBase |
141 | { | |
0f546316 KS |
142 | // Breakpoint instruction |
143 | static pc_t breakpoint_insn; | |
144 | #ifdef DIRECT_THREADED | |
145 | static insn_slot bp_insn_slot; | |
146 | #else | |
147 | static unsigned char bp_insn_opcode; | |
148 | #endif | |
149 | ||
58eb6e7c AG |
150 | _Jv_ushort max_stack; |
151 | _Jv_ushort max_locals; | |
152 | int code_length; | |
153 | ||
154 | _Jv_ushort exc_count; | |
a022cd59 | 155 | bool is_15; |
58eb6e7c | 156 | |
18744d9b BM |
157 | // Length of the line_table - when this is zero then line_table is NULL. |
158 | int line_table_len; | |
159 | _Jv_LineTableEntry *line_table; | |
160 | ||
19add4f7 | 161 | pc_t prepared; |
e939885f | 162 | int number_insn_slots; |
fdae83ab | 163 | |
58eb6e7c AG |
164 | unsigned char* bytecode () |
165 | { | |
166 | return | |
167 | ((unsigned char*)this) | |
168 | + ROUND((sizeof (_Jv_InterpMethod) | |
169 | + exc_count*sizeof (_Jv_InterpException)), 4); | |
170 | } | |
fdae83ab | 171 | |
58eb6e7c AG |
172 | _Jv_InterpException * exceptions () |
173 | { | |
174 | return (_Jv_InterpException*) (this+1); | |
175 | } | |
176 | ||
177 | static size_t size (int exc_count, int code_length) | |
178 | { | |
179 | return | |
180 | ROUND ((sizeof (_Jv_InterpMethod) | |
181 | + (exc_count * sizeof (_Jv_InterpException))), 4) | |
182 | + code_length; | |
183 | } | |
184 | ||
185 | // return the method's invocation pointer (a stub). | |
186 | void *ncode (); | |
fdae83ab | 187 | void compile (const void * const *); |
58eb6e7c | 188 | |
7941ceab AG |
189 | static void run_normal (ffi_cif*, void*, ffi_raw*, void*); |
190 | static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*); | |
4c98b1b0 | 191 | static void run_class (ffi_cif*, void*, ffi_raw*, void*); |
7941ceab | 192 | static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*); |
50ac2500 KG |
193 | |
194 | static void run_normal_debug (ffi_cif*, void*, ffi_raw*, void*); | |
195 | static void run_synch_object_debug (ffi_cif*, void*, ffi_raw*, void*); | |
196 | static void run_class_debug (ffi_cif*, void*, ffi_raw*, void*); | |
197 | static void run_synch_class_debug (ffi_cif*, void*, ffi_raw*, void*); | |
58eb6e7c | 198 | |
50ac2500 KG |
199 | static void run (void *, ffi_raw *, _Jv_InterpMethod *); |
200 | static void run_debug (void *, ffi_raw *, _Jv_InterpMethod *); | |
201 | ||
18744d9b | 202 | |
50ac2500 | 203 | |
18744d9b BM |
204 | // Returns source file line number for given PC value, or -1 if line |
205 | // number info is unavailable. | |
206 | int get_source_line(pc_t mpc); | |
58eb6e7c | 207 | |
e939885f KS |
208 | // Convenience function for indexing bytecode PC/insn slots in |
209 | // line tables for JDWP | |
210 | jlong insn_index (pc_t pc); | |
50ac2500 KG |
211 | |
212 | public: | |
213 | ||
e939885f KS |
214 | /* Get the line table for this method. |
215 | * start is the lowest index in the method | |
216 | * end is the highest index in the method | |
217 | * line_numbers is an array to hold the list of source line numbers | |
218 | * code_indices is an array to hold the corresponding list of code indices | |
219 | */ | |
220 | void get_line_table (jlong& start, jlong& end, jintArray& line_numbers, | |
221 | jlongArray& code_indices); | |
222 | ||
0f546316 KS |
223 | /* Installs a break instruction at the given code index. Returns |
224 | the pc_t of the breakpoint or NULL if index is invalid. */ | |
225 | pc_t install_break (jlong index); | |
226 | ||
05ee9ca0 KS |
227 | // Gets the instruction at the given index |
228 | pc_t get_insn (jlong index); | |
229 | ||
230 | /* Writes the given instruction at the given code index. Returns | |
231 | the insn or NULL if index is invalid. */ | |
232 | pc_t set_insn (jlong index, pc_t insn); | |
233 | ||
d0f4aa53 KS |
234 | #ifdef DIRECT_THREADED |
235 | friend void _Jv_CompileMethod (_Jv_InterpMethod*); | |
236 | #endif | |
237 | ||
58eb6e7c | 238 | friend class _Jv_ClassReader; |
a12fe13d | 239 | friend class _Jv_BytecodeVerifier; |
18744d9b | 240 | friend class _Jv_StackTrace; |
36739040 | 241 | friend class _Jv_InterpreterEngine; |
58eb6e7c | 242 | |
b4d0051b TT |
243 | #ifdef JV_MARKOBJ_DECL |
244 | friend JV_MARKOBJ_DECL; | |
245 | #endif | |
58eb6e7c AG |
246 | }; |
247 | ||
f5310108 | 248 | class _Jv_InterpClass |
58eb6e7c | 249 | { |
facc279f | 250 | _Jv_MethodBase **interpreted_methods; |
18744d9b BM |
251 | _Jv_ushort *field_initializers; |
252 | jstring source_file_name; | |
58eb6e7c AG |
253 | |
254 | friend class _Jv_ClassReader; | |
255 | friend class _Jv_InterpMethod; | |
18744d9b | 256 | friend class _Jv_StackTrace; |
36739040 | 257 | friend class _Jv_InterpreterEngine; |
18744d9b | 258 | |
58eb6e7c | 259 | friend void _Jv_InitField (jobject, jclass, int); |
470042c7 TT |
260 | #ifdef JV_MARKOBJ_DECL |
261 | friend JV_MARKOBJ_DECL; | |
262 | #endif | |
8ade4771 TT |
263 | |
264 | friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass); | |
58eb6e7c AG |
265 | }; |
266 | ||
8ade4771 TT |
267 | extern inline _Jv_MethodBase ** |
268 | _Jv_GetFirstMethod (_Jv_InterpClass *klass) | |
269 | { | |
270 | return klass->interpreted_methods; | |
271 | } | |
272 | ||
a022cd59 TT |
273 | struct _Jv_ResolvedMethod |
274 | { | |
58eb6e7c | 275 | jint stack_item_count; |
58eb6e7c AG |
276 | jclass klass; |
277 | _Jv_Method* method; | |
278 | ||
279 | // a resolved method holds the cif in-line, so that _Jv_MarkObj just needs | |
280 | // to mark the resolved method to hold on to the cif. Some memory could be | |
281 | // saved by keeping a cache of cif's, since many will be the same. | |
282 | ffi_cif cif; | |
283 | ffi_type * arg_types[0]; | |
284 | }; | |
285 | ||
facc279f TT |
286 | class _Jv_JNIMethod : public _Jv_MethodBase |
287 | { | |
288 | // The underlying function. If NULL we have to look for the | |
289 | // function. | |
290 | void *function; | |
291 | ||
d348bda4 TT |
292 | // This is the CIF used by the JNI function. |
293 | ffi_cif jni_cif; | |
294 | ||
295 | // These are the argument types used by the JNI function. | |
296 | ffi_type **jni_arg_types; | |
297 | ||
facc279f TT |
298 | // This function is used when making a JNI call from the interpreter. |
299 | static void call (ffi_cif *, void *, ffi_raw *, void *); | |
300 | ||
301 | void *ncode (); | |
302 | ||
303 | friend class _Jv_ClassReader; | |
36739040 TT |
304 | friend class _Jv_InterpreterEngine; |
305 | ||
306 | #ifdef JV_MARKOBJ_DECL | |
307 | friend JV_MARKOBJ_DECL; | |
308 | #endif | |
8ade4771 TT |
309 | |
310 | public: | |
311 | // FIXME: this is ugly. | |
312 | void set_function (void *f) | |
313 | { | |
314 | function = f; | |
315 | } | |
facc279f TT |
316 | }; |
317 | ||
18744d9b BM |
318 | // The interpreted call stack, represented by a linked list of frames. |
319 | struct _Jv_InterpFrame | |
3308c46e | 320 | { |
97b8365c TT |
321 | union |
322 | { | |
323 | void *meth; | |
324 | _Jv_InterpMethod *self; | |
325 | _Jv_Method *proxyMethod; | |
326 | }; | |
1349c688 | 327 | java::lang::Thread *thread; |
18744d9b | 328 | _Jv_InterpFrame *next; |
97b8365c TT |
329 | union |
330 | { | |
331 | pc_t pc; | |
332 | jclass proxyClass; | |
333 | }; | |
334 | ||
335 | _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyClass = NULL) | |
3308c46e | 336 | { |
97b8365c | 337 | this->meth = meth; |
1349c688 BM |
338 | thread = thr; |
339 | next = (_Jv_InterpFrame *) thr->interp_frame; | |
340 | thr->interp_frame = (gnu::gcj::RawData *) this; | |
97b8365c | 341 | this->proxyClass = proxyClass; |
3308c46e TT |
342 | } |
343 | ||
18744d9b | 344 | ~_Jv_InterpFrame () |
3308c46e | 345 | { |
1349c688 | 346 | thread->interp_frame = (gnu::gcj::RawData *) next; |
3308c46e TT |
347 | } |
348 | }; | |
349 | ||
f39b788a TT |
350 | #endif /* INTERPRETER */ |
351 | ||
58eb6e7c | 352 | #endif /* __JAVA_INTERP_H__ */ |