CACAO
stubs.cpp
Go to the documentation of this file.
1 /* src/vm/jit/stubs.cpp - JIT stubs
2 
3  Copyright (C) 1996-2013
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 #include "vm/jit/stubs.hpp"
27 #include <stdint.h> // for uint8_t
28 #include "arch.hpp" // for JIT_COMPILER_VIA_SIGNAL
29 #include "config.h" // for ENABLE_JIT
30 #include "md-stubs.hpp" // for CompilerStub::get_code_size
31 #include "md.hpp" // for md_cacheflush
32 #include "mm/codememory.hpp"
33 #include "mm/dumpmemory.hpp" // for DumpMemory, DumpMemoryArea
34 #include "vm/descriptor.hpp" // for methoddesc, typedesc, etc
35 #include "vm/jit/abi.hpp" // for md_param_alloc_native
36 #include "vm/jit/builtin.hpp" // for builtintable_entry
37 #include "vm/jit/code.hpp" // for code_unflag_leafmethod, etc
38 #include "vm/jit/codegen-common.hpp" // for codegen_emit_stub_native, etc
39 #include "vm/jit/disass.hpp"
40 #include "vm/jit/dseg.hpp"
41 #include "vm/jit/emit-common.hpp" // for emit_trap_compiler
42 #include "vm/jit/jit.hpp" // for jitdata, jit_jitdata_new
43 #include "vm/jit/reg.hpp" // for reg_setup
44 #include "vm/jit/show.hpp"
45 #include "vm/jit/trap.hpp"
46 #include "vm/method.hpp" // for methodinfo
47 #include "vm/options.hpp" // for opt_verbosecall
48 #include "vm/statistics.hpp" // for StatVar
49 #include "vm/types.hpp" // for ptrint, u1
50 
51 STAT_DECLARE_VAR(int,count_cstub_len,0)
52 STAT_DECLARE_VAR(int,size_stub_native,0)
53 
54 /**
55  * Wrapper for codegen_emit_stub_compiler.
56  *
57  * @param m Method object.
58  *
59  * @return Pointer to the compiler stub code.
60  */
61 void* CompilerStub::generate(methodinfo *m)
62 {
63  jitdata *jd;
64  codegendata *cd;
65  ptrint *d; /* pointer to data memory */
66  u1 *c; /* pointer to code memory */
67 
68  // Create new dump memory area.
69  DumpMemoryArea dma;
70 
71  /* allocate required data structures */
72 
73  jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
74 
75  jd->m = m;
77  jd->flags = 0;
78 
79  /* get required compiler data */
80 
81  cd = jd->cd;
82 
83 #if !defined(JIT_COMPILER_VIA_SIGNAL)
84  /* allocate code memory */
85 
86  c = CNEW(u1, 3 * SIZEOF_VOID_P + get_code_size());
87 
88  /* set pointers correctly */
89 
90  d = (ptrint *) c;
91 
92  cd->mcodebase = c;
93 
94  c = c + 3 * SIZEOF_VOID_P;
95  cd->mcodeptr = c;
96 
97  /* NOTE: The codeinfo pointer is actually a pointer to the
98  methodinfo (this fakes a codeinfo structure). */
99 
100  d[0] = (ptrint) asm_call_jit_compiler;
101  d[1] = (ptrint) m;
102  d[2] = (ptrint) &d[1]; /* fake code->m */
103 
104  /* call the emit function */
105 
107 
108  STATISTICS(count_cstub_len += 3 * SIZEOF_VOID_P + get_code_size());
109 
110  /* flush caches */
111 
112  md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + get_code_size());
113 #else
114  /* Allocate code memory. */
115 
116  c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + get_code_size());
117 
118  /* Set pointers correctly. */
119 
120  d = (ptrint *) c;
121 
122  cd->mcodebase = c;
123 
124  c = c + 2 * SIZEOF_VOID_P;
125  cd->mcodeptr = c;
126 
127  /* NOTE: The codeinfo pointer is actually a pointer to the
128  methodinfo (this fakes a codeinfo structure). */
129 
130  d[0] = (ptrint) m;
131  d[1] = (ptrint) &d[0]; /* fake code->m */
132 
133  /* Emit the trap instruction. */
134 
135  emit_trap_compiler(cd);
136 
137  STATISTICS(count_cstub_len += 2 * SIZEOF_VOID_P + get_code_size());
138 
139  /* Flush caches. */
140 
141  md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + get_code_size());
142 #endif
143 
144  /* return native stub code */
145 
146  return c;
147 }
148 
149 
150 /**
151  * Free a compiler stub from memory.
152  *
153  * @param
154  */
155 void CompilerStub::remove(void* stub)
156 {
157  // Pass size 1 to keep the intern function happy.
158  CFREE(stub, 1);
159 }
160 
161 
162 /* codegen_disassemble_nativestub **********************************************
163 
164  Disassembles the generated builtin or native stub.
165 
166 *******************************************************************************/
167 
168 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
169 static void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
170 {
171  printf("Stub code: ");
172  if (m->clazz != NULL)
174  else
175  printf("NULL");
176  printf(".");
177  utf_fprint_printable_ascii(stdout, m->name);
179  printf("\nLength: %d\n\n", (s4) (end - start));
180 
181  DISASSEMBLE(start, end);
182 }
183 #endif
184 
185 
186 /**
187  * Wrapper for codegen_emit_stub_native.
188  *
189  * @param m Method object.
190  * @param bte Builtin function structure.
191  */
193 {
194  jitdata *jd;
195  codeinfo *code;
196  int skipparams;
197 
198  // Create new dump memory area.
199  DumpMemoryArea dma;
200 
201  /* Create JIT data structure. */
202 
203  jd = jit_jitdata_new(m);
204 
205  /* Get required compiler data. */
206 
207  code = jd->code;
208 
209  /* Stubs are non-leaf methods. */
210 
212 
213  /* setup code generation stuff */
214 
215  codegen_setup(jd);
216 
217  /* Set the number of native arguments we need to skip. */
218 
219  skipparams = 0;
220 
221  /* generate the code */
222 
223 #if defined(ENABLE_JIT)
224 # if defined(ENABLE_INTRP)
225  if (!opt_intrp) {
226 # endif
227  assert(bte->fp != NULL);
228  codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
229 # if defined(ENABLE_INTRP)
230  }
231 # endif
232 #endif
233 
234  /* reallocate the memory and finish the code generation */
235 
236  codegen_finish(jd);
237 
238  /* set the stub entry point in the builtin table */
239 
240  bte->stub = code->entrypoint;
241 
242  STATISTICS(size_stub_native += code->mcodelength);
243 
244 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
245  /* disassemble native stub */
246 
247  if (opt_DisassembleStubs) {
248  codegen_disassemble_stub(m,
249  (u1 *) (ptrint) code->entrypoint,
250  (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
251 
252  /* show data segment */
253 
255  dseg_display(jd);
256  }
257 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
258 }
259 
261 
263 {
264  codegendata *cd = NEW(codegendata);
265  // 16 bytes should be enough for all architectures
266  cd->mcodebase = cd->mcodeptr = CNEW(u1, 16);
267 
269  md_cacheflush(cd->mcodebase, 16);
270  stubcode = cd->mcodebase;
271 }
272 
273 
274 /**
275  * Wrapper for codegen_emit_stub_native.
276  *
277  * @param m Method object of the native function.
278  * @param f Native function pointer.
279  *
280  * @return The codeinfo representing the stub code.
281  */
283 {
284  jitdata *jd;
285  codeinfo *code;
286  methoddesc *md;
287  methoddesc *nmd;
288  int skipparams;
289 
290  // Create new dump memory area.
291  DumpMemoryArea dma;
292 
293  /* Create JIT data structure. */
294 
295  jd = jit_jitdata_new(m);
296 
297  /* Get required compiler data. */
298 
299  code = jd->code;
300 
301  /* Stubs are non-leaf methods. */
302 
304 
305  /* set the flags for the current JIT run */
306 
307 #if defined(ENABLE_PROFILING)
308  if (opt_prof)
310 #endif
311 
312  if (opt_verbosecall)
314 
315  /* setup code generation stuff */
316 
317 #if defined(ENABLE_JIT)
318 # if defined(ENABLE_INTRP)
319  if (!opt_intrp)
320 # endif
321  reg_setup(jd);
322 #endif
323 
324  codegen_setup(jd);
325 
326  /* create new method descriptor with additional native parameters */
327 
328  md = m->parseddesc;
329 
330  /* Set the number of native arguments we need to skip. */
331 
332  if (m->flags & ACC_STATIC)
333  skipparams = 2;
334  else
335  skipparams = 1;
336 
337  nmd = (methoddesc*) DumpMemory::allocate(sizeof(methoddesc) - sizeof(typedesc) +
338  md->paramcount * sizeof(typedesc) +
339  skipparams * sizeof(typedesc));
340 
341  nmd->paramcount = md->paramcount + skipparams;
342 
343  nmd->params = (paramdesc*) DumpMemory::allocate(sizeof(paramdesc) * nmd->paramcount);
344 
345  nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
346 
347  if (m->flags & ACC_STATIC)
348  nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
349 
350  MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
351  md->paramcount);
352 
353 #if defined(ENABLE_JIT)
354 # if defined(ENABLE_INTRP)
355  if (!opt_intrp)
356 # endif
357  /* pre-allocate the arguments for the native ABI */
358 
360 #endif
361 
362  /* generate the code */
363 
364 #if defined(ENABLE_JIT)
365 # if defined(ENABLE_INTRP)
366  if (opt_intrp)
367  intrp_createnativestub(f, jd, nmd);
368  else
369 # endif
370  codegen_emit_stub_native(jd, nmd, f, skipparams);
371 #else
372  intrp_createnativestub(f, jd, nmd);
373 #endif
374 
375  /* reallocate the memory and finish the code generation */
376 
377  codegen_finish(jd);
378 
379  /* must be done after codegen_finish() */
380  STATISTICS(size_stub_native += code->mcodelength);
381 
382 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
383  /* disassemble native stub */
384 
385  if (opt_DisassembleStubs) {
386 # if defined(ENABLE_DEBUG_FILTER)
388 # endif
389  {
390  codegen_disassemble_stub(m,
391  (u1 *) (ptrint) code->entrypoint,
392  (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
393 
394  /* show data segment */
395 
397  dseg_display(jd);
398  }
399  }
400 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
401 
402  /* return native stub code */
403 
404  return code;
405 }
406 
407 
408 /**
409  * Free a native stub from memory.
410  *
411  * @param stub Pointer to stub memory.
412  */
413 void NativeStub::remove(void* stub)
414 {
415  // Pass size 1 to keep the intern function happy.
416  CFREE(stub, 1);
417 }
418 
419 
420 /*
421  * These are local overrides for various environment variables in Emacs.
422  * Please do not remove this and leave it at the end of the file, where
423  * Emacs will automagically detect them.
424  * ---------------------------------------------------------------------
425  * Local variables:
426  * mode: c++
427  * indent-tabs-mode: t
428  * c-basic-offset: 4
429  * tab-width: 4
430  * End:
431  * vim:noexpandtab:sw=4:ts=4:
432  */
Utf8String name
Definition: method.hpp:71
#define STATISTICS(x)
Wrapper for statistics only code.
Definition: statistics.hpp:975
Definition: jit.hpp:126
paramdesc * params
Definition: descriptor.hpp:164
methoddesc * md
Definition: builtin.hpp:71
#define NEW(type)
Definition: memory.hpp:93
#define JITDATA_FLAG_VERBOSECALL
Definition: jit.hpp:197
codeinfo * code
Definition: jit.hpp:128
static void remove(void *stub)
Free a compiler stub from memory.
Definition: stubs.cpp:155
bool opt_intrp
Definition: options.cpp:55
#define JITDATA_FLAG_INSTRUMENT
Definition: jit.hpp:187
codegendata * cd
Definition: jit.hpp:129
u4 flags
Definition: jit.hpp:138
void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
Definition: codegen.cpp:2010
void utf_fprint_printable_ascii_classname(FILE *file, Utf8String u)
Definition: utf8.cpp:665
uint8_t u1
Definition: types.hpp:40
static void code_unflag_leafmethod(codeinfo *code)
Definition: code.hpp:161
s4 mcodelength
Definition: code.hpp:85
bool opt_verbosecall
Definition: options.cpp:76
u1 * stub
Definition: builtin.hpp:64
static void * stubcode
Definition: stubs.hpp:59
void dseg_display(jitdata *jd)
Definition: dseg.cpp:633
void emit_abstractmethoderror_trap(codegendata *cd)
Definition: emit.cpp:468
void md_cacheflush(u1 *addr, s4 nbytes)
Definition: md.c:49
u1 * intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
Definition: codegen.c:1972
void(* functionptr)(void)
Definition: global.hpp:39
typedesc paramtypes[1]
Definition: descriptor.hpp:167
Utf8String descriptor
Definition: method.hpp:72
bool opt_showddatasegment
Definition: options.cpp:86
Dump memory area.
Definition: dumpmemory.hpp:90
jitdata * jit_jitdata_new(methodinfo *m)
Definition: jit.cpp:217
classinfo * clazz
Definition: method.hpp:80
This file contains the statistics framework.
#define SHOW_FILTER_FLAG_SHOW_METHOD
Definition: show.hpp:70
Utf8String name
Definition: class.hpp:91
void reg_setup(jitdata *jd)
Definition: reg.cpp:42
void emit_trap_compiler(codegendata *cd)
Definition: emit.cpp:463
int32_t s4
Definition: types.hpp:45
#define CFREE(ptr, num)
Definition: codememory.hpp:35
void utf_fprint_printable_ascii(FILE *file, Utf8String u)
Definition: utf8.cpp:650
static void generate()
Definition: stubs.cpp:262
void md_param_alloc_native(methoddesc *md)
Definition: md-abi.cpp:224
void codegen_setup(jitdata *jd)
void codegen_emit_stub_compiler(jitdata *jd)
Definition: codegen.cpp:2474
methoddesc * parseddesc
Definition: method.hpp:78
Definition: builtin.hpp:60
methodinfo * m
Definition: jit.hpp:127
u1 filtermatches
Definition: method.hpp:119
static void generate(methodinfo *m, builtintable_entry *bte)
Wrapper for codegen_emit_stub_native.
Definition: stubs.cpp:192
static void * allocate(size_t size)
Definition: dumpmemory.hpp:251
static void remove(void *stub)
Free a native stub from memory.
Definition: stubs.cpp:413
void asm_call_jit_compiler(void)
functionptr fp
Definition: builtin.hpp:63
#define MCOPY(dest, src, type, num)
Definition: memory.hpp:103
s4 flags
Definition: method.hpp:70
uintptr_t ptrint
Definition: types.hpp:54
static codeinfo * generate(methodinfo *m, functionptr f)
Wrapper for codegen_emit_stub_native.
Definition: stubs.cpp:282
#define STAT_DECLARE_VAR(type, var, init)
Declare an external statistics variable.
Definition: statistics.hpp:963
#define printf(...)
Definition: ssa2.cpp:40
Class for compiler stub generation.
Definition: stubs.hpp:39
u1 * entrypoint
Definition: code.hpp:84
void codegen_finish(jitdata *jd)
#define CNEW(type, num)
Definition: codememory.hpp:34