]>
Commit | Line | Data |
---|---|---|
1 | // java-interp.h - Header file for the bytecode interpreter. -*- c++ -*- | |
2 | ||
3 | /* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation | |
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 | ||
14 | #include <jvm.h> | |
15 | #include <java-cpool.h> | |
16 | #include <gnu/gcj/runtime/NameFinder.h> | |
17 | ||
18 | #ifdef INTERPRETER | |
19 | ||
20 | #pragma interface | |
21 | ||
22 | #include <java/lang/Class.h> | |
23 | #include <java/lang/ClassLoader.h> | |
24 | #include <java/lang/reflect/Modifier.h> | |
25 | ||
26 | extern "C" { | |
27 | #include <ffi.h> | |
28 | } | |
29 | ||
30 | extern inline jboolean | |
31 | _Jv_IsInterpretedClass (jclass c) | |
32 | { | |
33 | return (c->accflags & java::lang::reflect::Modifier::INTERPRETED) != 0; | |
34 | } | |
35 | ||
36 | struct _Jv_ResolvedMethod; | |
37 | ||
38 | void _Jv_DefineClass (jclass, jbyteArray, jint, jint); | |
39 | ||
40 | void _Jv_InitField (jobject, jclass, int); | |
41 | void * _Jv_AllocMethodInvocation (jsize size); | |
42 | int _Jv_count_arguments (_Jv_Utf8Const *signature, | |
43 | jboolean staticp = true); | |
44 | void _Jv_VerifyMethod (_Jv_InterpMethod *method); | |
45 | ||
46 | /* FIXME: this should really be defined in some more generic place */ | |
47 | #define ROUND(V, A) (((((unsigned) (V))-1) | ((A)-1))+1) | |
48 | ||
49 | /* the interpreter is written in C++, primarily because it makes it easy for | |
50 | * the entire thing to be "friend" with class Class. */ | |
51 | ||
52 | class _Jv_InterpClass; | |
53 | class _Jv_InterpMethod; | |
54 | ||
55 | // Before a method is "compiled" we store values as the bytecode PC, | |
56 | // an int. Afterwards we store them as pointers into the prepared | |
57 | // code itself. | |
58 | union _Jv_InterpPC | |
59 | { | |
60 | int i; | |
61 | void *p; | |
62 | }; | |
63 | ||
64 | class _Jv_InterpException | |
65 | { | |
66 | _Jv_InterpPC start_pc; | |
67 | _Jv_InterpPC end_pc; | |
68 | _Jv_InterpPC handler_pc; | |
69 | _Jv_InterpPC handler_type; | |
70 | ||
71 | friend class _Jv_ClassReader; | |
72 | friend class _Jv_InterpMethod; | |
73 | friend class _Jv_BytecodeVerifier; | |
74 | }; | |
75 | ||
76 | // Base class for method representations. Subclasses are interpreted | |
77 | // and JNI methods. | |
78 | class _Jv_MethodBase | |
79 | { | |
80 | protected: | |
81 | // The class which defined this method. | |
82 | jclass defining_class; | |
83 | ||
84 | // The method description. | |
85 | _Jv_Method *self; | |
86 | ||
87 | // Size of raw arguments. | |
88 | _Jv_ushort args_raw_size; | |
89 | ||
90 | // Chain of addresses to fill in. See _Jv_Defer_Resolution. | |
91 | void *deferred; | |
92 | ||
93 | friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **); | |
94 | friend void _Jv_PrepareClass(jclass); | |
95 | ||
96 | public: | |
97 | _Jv_Method *get_method () | |
98 | { | |
99 | return self; | |
100 | } | |
101 | }; | |
102 | ||
103 | class _Jv_InterpMethod : public _Jv_MethodBase | |
104 | { | |
105 | _Jv_ushort max_stack; | |
106 | _Jv_ushort max_locals; | |
107 | int code_length; | |
108 | ||
109 | _Jv_ushort exc_count; | |
110 | ||
111 | void *prepared; | |
112 | ||
113 | unsigned char* bytecode () | |
114 | { | |
115 | return | |
116 | ((unsigned char*)this) | |
117 | + ROUND((sizeof (_Jv_InterpMethod) | |
118 | + exc_count*sizeof (_Jv_InterpException)), 4); | |
119 | } | |
120 | ||
121 | _Jv_InterpException * exceptions () | |
122 | { | |
123 | return (_Jv_InterpException*) (this+1); | |
124 | } | |
125 | ||
126 | static size_t size (int exc_count, int code_length) | |
127 | { | |
128 | return | |
129 | ROUND ((sizeof (_Jv_InterpMethod) | |
130 | + (exc_count * sizeof (_Jv_InterpException))), 4) | |
131 | + code_length; | |
132 | } | |
133 | ||
134 | // return the method's invocation pointer (a stub). | |
135 | void *ncode (); | |
136 | void compile (const void * const *); | |
137 | ||
138 | static void run_normal (ffi_cif*, void*, ffi_raw*, void*); | |
139 | static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*); | |
140 | static void run_class (ffi_cif*, void*, ffi_raw*, void*); | |
141 | static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*); | |
142 | ||
143 | void run (void*, ffi_raw *); | |
144 | ||
145 | public: | |
146 | static void dump_object(jobject o); | |
147 | ||
148 | friend class _Jv_ClassReader; | |
149 | friend class _Jv_BytecodeVerifier; | |
150 | friend class gnu::gcj::runtime::NameFinder; | |
151 | friend class gnu::gcj::runtime::StackTrace; | |
152 | ||
153 | ||
154 | friend void _Jv_PrepareClass(jclass); | |
155 | ||
156 | #ifdef JV_MARKOBJ_DECL | |
157 | friend JV_MARKOBJ_DECL; | |
158 | #endif | |
159 | }; | |
160 | ||
161 | class _Jv_InterpClass | |
162 | { | |
163 | _Jv_MethodBase **interpreted_methods; | |
164 | _Jv_ushort *field_initializers; | |
165 | ||
166 | friend class _Jv_ClassReader; | |
167 | friend class _Jv_InterpMethod; | |
168 | friend void _Jv_PrepareClass(jclass); | |
169 | friend void _Jv_PrepareMissingMethods (jclass base2, jclass iface_class); | |
170 | friend void _Jv_InitField (jobject, jclass, int); | |
171 | #ifdef JV_MARKOBJ_DECL | |
172 | friend JV_MARKOBJ_DECL; | |
173 | #endif | |
174 | ||
175 | friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass); | |
176 | friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **); | |
177 | }; | |
178 | ||
179 | // We have an interpreted class CL and we're trying to find the | |
180 | // address of the ncode of a method METH. That interpreted class | |
181 | // hasn't yet been prepared, so we defer fixups until they are ready. | |
182 | // To do this, we create a chain of fixups that will be resolved by | |
183 | // _Jv_PrepareClass. | |
184 | extern inline void | |
185 | _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **address) | |
186 | { | |
187 | int i; | |
188 | jclass self = (jclass) cl; | |
189 | _Jv_InterpClass *interp_cl = (_Jv_InterpClass*) self->aux_info; | |
190 | ||
191 | for (i = 0; i < self->method_count; i++) | |
192 | { | |
193 | _Jv_Method *m = &self->methods[i]; | |
194 | if (m == meth) | |
195 | { | |
196 | _Jv_MethodBase *imeth = interp_cl->interpreted_methods[i]; | |
197 | *address = imeth->deferred; | |
198 | imeth->deferred = address; | |
199 | return; | |
200 | } | |
201 | } | |
202 | return; | |
203 | } | |
204 | ||
205 | extern inline _Jv_MethodBase ** | |
206 | _Jv_GetFirstMethod (_Jv_InterpClass *klass) | |
207 | { | |
208 | return klass->interpreted_methods; | |
209 | } | |
210 | ||
211 | struct _Jv_ResolvedMethod { | |
212 | jint stack_item_count; | |
213 | jint vtable_index; | |
214 | jclass klass; | |
215 | _Jv_Method* method; | |
216 | ||
217 | // a resolved method holds the cif in-line, so that _Jv_MarkObj just needs | |
218 | // to mark the resolved method to hold on to the cif. Some memory could be | |
219 | // saved by keeping a cache of cif's, since many will be the same. | |
220 | ffi_cif cif; | |
221 | ffi_type * arg_types[0]; | |
222 | }; | |
223 | ||
224 | class _Jv_JNIMethod : public _Jv_MethodBase | |
225 | { | |
226 | // The underlying function. If NULL we have to look for the | |
227 | // function. | |
228 | void *function; | |
229 | ||
230 | // This is the CIF used by the JNI function. | |
231 | ffi_cif jni_cif; | |
232 | ||
233 | // These are the argument types used by the JNI function. | |
234 | ffi_type **jni_arg_types; | |
235 | ||
236 | // This function is used when making a JNI call from the interpreter. | |
237 | static void call (ffi_cif *, void *, ffi_raw *, void *); | |
238 | ||
239 | void *ncode (); | |
240 | ||
241 | friend class _Jv_ClassReader; | |
242 | friend void _Jv_PrepareClass(jclass); | |
243 | ||
244 | public: | |
245 | // FIXME: this is ugly. | |
246 | void set_function (void *f) | |
247 | { | |
248 | function = f; | |
249 | } | |
250 | }; | |
251 | ||
252 | // A structure of this type is used to link together interpreter | |
253 | // invocations on the stack. | |
254 | struct _Jv_MethodChain | |
255 | { | |
256 | const _Jv_InterpMethod *self; | |
257 | _Jv_MethodChain **ptr; | |
258 | _Jv_MethodChain *next; | |
259 | ||
260 | _Jv_MethodChain (const _Jv_InterpMethod *s, _Jv_MethodChain **n) | |
261 | { | |
262 | self = s; | |
263 | ptr = n; | |
264 | next = *n; | |
265 | *n = this; | |
266 | } | |
267 | ||
268 | ~_Jv_MethodChain () | |
269 | { | |
270 | *ptr = next; | |
271 | } | |
272 | }; | |
273 | ||
274 | #endif /* INTERPRETER */ | |
275 | ||
276 | #endif /* __JAVA_INTERP_H__ */ |