* src/vm/jit/codegen-common.cpp, src/vm/jit/x86_64/codegen.c: Generate
[cacao.git] / src / vm / jit / stubs.cpp
1 /* src/vm/jit/stubs.cpp - JIT stubs
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5    Copyright (C) 2008 Theobroma Systems Ltd.
6
7    This file is part of CACAO.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2, or (at
12    your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.
23
24 */
25
26
27 #include "config.h"
28
29 #include <stdint.h>
30
31 // Include machine dependent headers.
32 #include "md.h"
33
34 #include "mm/dumpmemory.hpp"
35
36 #include "vm/method.hpp"
37 #include "vm/options.h"
38
39 #include "vm/jit/abi.h"
40 #include "vm/jit/code.hpp"
41 #include "vm/jit/codegen-common.hpp"
42 #include "vm/jit/disass.h"
43 #include "vm/jit/emit-common.hpp"
44 #include "vm/jit/jit.hpp"
45 #include "vm/jit/show.hpp"
46 #include "vm/jit/stubs.hpp"
47
48
49 /**
50  * Wrapper for codegen_emit_stub_compiler.
51  *
52  * @param m Method object.
53  *
54  * @return Pointer to the compiler stub code.
55  */
56 void* CompilerStub::generate(methodinfo *m)
57 {
58         jitdata     *jd;
59         codegendata *cd;
60         ptrint      *d;                     /* pointer to data memory             */
61         u1          *c;                     /* pointer to code memory             */
62
63         // Create new dump memory area.
64         DumpMemoryArea dma;
65
66         /* allocate required data structures */
67
68         jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
69
70         jd->m     = m;
71         jd->cd    = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
72         jd->flags = 0;
73
74         /* get required compiler data */
75
76         cd = jd->cd;
77
78 #if !defined(JIT_COMPILER_VIA_SIGNAL)
79         /* allocate code memory */
80
81         c = CNEW(u1, 3 * SIZEOF_VOID_P + get_code_size());
82
83         /* set pointers correctly */
84
85         d = (ptrint *) c;
86
87         cd->mcodebase = c;
88
89         c = c + 3 * SIZEOF_VOID_P;
90         cd->mcodeptr = c;
91
92         /* NOTE: The codeinfo pointer is actually a pointer to the
93            methodinfo (this fakes a codeinfo structure). */
94
95         d[0] = (ptrint) asm_call_jit_compiler;
96         d[1] = (ptrint) m;
97         d[2] = (ptrint) &d[1];                                    /* fake code->m */
98
99         /* call the emit function */
100
101         codegen_emit_stub_compiler(jd);
102
103 #if defined(ENABLE_STATISTICS)
104         if (opt_stat)
105                 count_cstub_len += 3 * SIZEOF_VOID_P + get_code_size();
106 #endif
107
108         /* flush caches */
109
110         md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + get_code_size());
111 #else
112         /* Allocate code memory. */
113
114         c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + get_code_size());
115
116         /* Set pointers correctly. */
117
118         d = (ptrint *) c;
119
120         cd->mcodebase = c;
121
122         c = c + 2 * SIZEOF_VOID_P;
123         cd->mcodeptr = c;
124
125         /* NOTE: The codeinfo pointer is actually a pointer to the
126            methodinfo (this fakes a codeinfo structure). */
127
128         d[0] = (ptrint) m;
129         d[1] = (ptrint) &d[0];                                    /* fake code->m */
130
131         /* Emit the trap instruction. */
132
133         emit_trap_compiler(cd);
134
135 #if defined(ENABLE_STATISTICS)
136         if (opt_stat)
137                 count_cstub_len += 2 * SIZEOF_VOID_P + get_code_size();
138 #endif
139
140         /* Flush caches. */
141
142         md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + get_code_size());
143 #endif
144
145         /* return native stub code */
146
147         return c;
148 }
149
150
151 /**
152  * Free a compiler stub from memory.
153  *
154  * @param 
155  */
156 void CompilerStub::remove(void* stub)
157 {
158         // Pass size 1 to keep the intern function happy.
159         CFREE(stub, 1);
160 }
161
162
163 /* codegen_disassemble_nativestub **********************************************
164
165    Disassembles the generated builtin or native stub.
166
167 *******************************************************************************/
168
169 #if defined(ENABLE_DISASSEMBLER)
170 static void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
171 {
172         printf("Stub code: ");
173         if (m->clazz != NULL)
174                 utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
175         else
176                 printf("NULL");
177         printf(".");
178         utf_fprint_printable_ascii(stdout, m->name);
179         utf_fprint_printable_ascii(stdout, m->descriptor);
180         printf("\nLength: %d\n\n", (s4) (end - start));
181
182         DISASSEMBLE(start, end);
183 }
184 #endif
185
186
187 /**
188  * Wrapper for codegen_emit_stub_native.
189  *
190  * @param m   Method object.
191  * @param bte Builtin function structure.
192  */
193 void BuiltinStub::generate(methodinfo* m, builtintable_entry* bte)
194 {
195         jitdata  *jd;
196         codeinfo *code;
197         int       skipparams;
198
199         // Create new dump memory area.
200         DumpMemoryArea dma;
201
202         /* Create JIT data structure. */
203
204         jd = jit_jitdata_new(m);
205
206         /* Get required compiler data. */
207
208         code = jd->code;
209
210         /* Stubs are non-leaf methods. */
211
212         code_unflag_leafmethod(code);
213
214         /* setup code generation stuff */
215
216         codegen_setup(jd);
217
218         /* Set the number of native arguments we need to skip. */
219
220         skipparams = 0;
221
222         /* generate the code */
223
224 #if defined(ENABLE_JIT)
225 # if defined(ENABLE_INTRP)
226         if (!opt_intrp) {
227 # endif
228                 assert(bte->fp != NULL);
229                 codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
230 # if defined(ENABLE_INTRP)
231         }
232 # endif
233 #endif
234
235         /* reallocate the memory and finish the code generation */
236
237         codegen_finish(jd);
238
239         /* set the stub entry point in the builtin table */
240
241         bte->stub = code->entrypoint;
242
243 #if defined(ENABLE_STATISTICS)
244         if (opt_stat)
245                 size_stub_native += code->mcodelength;
246 #endif
247
248 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
249         /* disassemble native stub */
250
251         if (opt_DisassembleStubs) {
252                 codegen_disassemble_stub(m,
253                                                                  (u1 *) (ptrint) code->entrypoint,
254                                                                  (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
255
256                 /* show data segment */
257
258                 if (opt_showddatasegment)
259                         dseg_display(jd);
260         }
261 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
262 }
263
264
265 /**
266  * Wrapper for codegen_emit_stub_native.
267  *
268  * @param m Method object of the native function.
269  * @param f Native function pointer.
270  *
271  * @return The codeinfo representing the stub code.
272  */
273 codeinfo* NativeStub::generate(methodinfo* m, functionptr f)
274 {
275         jitdata     *jd;
276         codeinfo    *code;
277         methoddesc  *md;
278         methoddesc  *nmd;       
279         int          skipparams;
280
281         // Create new dump memory area.
282         DumpMemoryArea dma;
283
284         /* Create JIT data structure. */
285
286         jd = jit_jitdata_new(m);
287
288         /* Get required compiler data. */
289
290         code = jd->code;
291
292         /* Stubs are non-leaf methods. */
293
294         code_unflag_leafmethod(code);
295
296         /* set the flags for the current JIT run */
297
298 #if defined(ENABLE_PROFILING)
299         if (opt_prof)
300                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
301 #endif
302
303         if (opt_verbosecall)
304                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
305
306         /* setup code generation stuff */
307
308 #if defined(ENABLE_JIT)
309 # if defined(ENABLE_INTRP)
310         if (!opt_intrp)
311 # endif
312                 reg_setup(jd);
313 #endif
314
315         codegen_setup(jd);
316
317         /* create new method descriptor with additional native parameters */
318
319         md = m->parseddesc;
320
321         /* Set the number of native arguments we need to skip. */
322
323         if (m->flags & ACC_STATIC)
324                 skipparams = 2;
325         else
326                 skipparams = 1;
327         
328         nmd = (methoddesc*) DumpMemory::allocate(sizeof(methoddesc) - sizeof(typedesc) +
329                                                                                          md->paramcount * sizeof(typedesc) +
330                                                                                          skipparams * sizeof(typedesc));
331
332         nmd->paramcount = md->paramcount + skipparams;
333
334         nmd->params = (paramdesc*) DumpMemory::allocate(sizeof(paramdesc) * nmd->paramcount);
335
336         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
337
338         if (m->flags & ACC_STATIC)
339                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
340
341         MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
342                   md->paramcount);
343
344 #if defined(ENABLE_JIT)
345 # if defined(ENABLE_INTRP)
346         if (!opt_intrp)
347 # endif
348                 /* pre-allocate the arguments for the native ABI */
349
350                 md_param_alloc_native(nmd);
351 #endif
352
353         /* generate the code */
354
355 #if defined(ENABLE_JIT)
356 # if defined(ENABLE_INTRP)
357         if (opt_intrp)
358                 intrp_createnativestub(f, jd, nmd);
359         else
360 # endif
361                 codegen_emit_stub_native(jd, nmd, f, skipparams);
362 #else
363         intrp_createnativestub(f, jd, nmd);
364 #endif
365
366         /* reallocate the memory and finish the code generation */
367
368         codegen_finish(jd);
369
370 #if defined(ENABLE_STATISTICS)
371         /* must be done after codegen_finish() */
372
373         if (opt_stat)
374                 size_stub_native += code->mcodelength;
375 #endif
376
377 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
378         /* disassemble native stub */
379
380         if (opt_DisassembleStubs) {
381 # if defined(ENABLE_DEBUG_FILTER)
382                 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
383 # endif
384                 {
385                         codegen_disassemble_stub(m,
386                                                                          (u1 *) (ptrint) code->entrypoint,
387                                                                          (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
388
389                         /* show data segment */
390
391                         if (opt_showddatasegment)
392                                 dseg_display(jd);
393                 }
394         }
395 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
396
397         /* return native stub code */
398
399         return code;
400 }
401
402
403 /**
404  * Free a native stub from memory.
405  *
406  * @param stub Pointer to stub memory.
407  */    
408 void NativeStub::remove(void* stub)
409 {
410         // Pass size 1 to keep the intern function happy.
411         CFREE(stub, 1);
412 }
413
414
415 // Legacy C interface.
416
417 extern "C" {
418         void*     CompilerStub_generate(methodinfo* m) { return CompilerStub::generate(m); }
419         void      CompilerStub_remove(void* stub) { CompilerStub::remove(stub); }
420
421         void      BuiltinStub_generate(methodinfo* m, builtintable_entry* bte) { BuiltinStub::generate(m, bte); }
422
423         void      NativeStub_remove(void* stub) { NativeStub::remove(stub); }
424 }
425
426
427 /*
428  * These are local overrides for various environment variables in Emacs.
429  * Please do not remove this and leave it at the end of the file, where
430  * Emacs will automagically detect them.
431  * ---------------------------------------------------------------------
432  * Local variables:
433  * mode: c++
434  * indent-tabs-mode: t
435  * c-basic-offset: 4
436  * tab-width: 4
437  * End:
438  * vim:noexpandtab:sw=4:ts=4:
439  */