CACAO
patcher.cpp
Go to the documentation of this file.
1 /* src/vm/jit/s390/patcher.cpp - s390 code patching functions
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include <assert.h>
29 #include <stdint.h>
30 
31 #include "mm/memory.hpp"
32 #include "native/native.hpp"
33 
34 #include "vm/jit/builtin.hpp"
35 #include "vm/class.hpp"
36 #include "vm/field.hpp"
37 #include "vm/initialize.hpp"
38 #include "vm/options.hpp"
39 #include "vm/references.hpp"
40 #include "vm/resolve.hpp"
41 #include "vm/types.hpp"
42 
44 #include "vm/jit/s390/codegen.hpp"
45 #include "vm/jit/s390/md-abi.hpp"
46 
47 
48 #define PATCH_BACK_ORIGINAL_MCODE \
49  *((u2 *) pr->mpc) = (u2) pr->mcode;
50 
51 #define PATCHER_TRACE
52 
53 
54 /* patcher_patch_code **********************************************************
55 
56  Just patches back the original machine code.
57 
58 *******************************************************************************/
59 
61 {
63 }
64 
65 
66 /* patcher_get_putstatic *******************************************************
67 
68  Machine code:
69 
70 *******************************************************************************/
71 
73 {
74  unresolved_field *uf;
75  u1 *datap;
76  fieldinfo *fi;
77 
79 
80  /* get stuff from the stack */
81 
82  uf = (unresolved_field *) pr->ref;
83  datap = (u1 *) pr->datap;
84 
85  /* get the fieldinfo */
86 
87  if (!(fi = resolve_field_eager(uf)))
88  return false;
89 
90  /* check if the field's class is initialized */
91 
92  if (!(fi->clazz->state & CLASS_INITIALIZED))
93  if (!initialize_class(fi->clazz))
94  return false;
95 
97 
98  /* patch the field value's address */
99 
100  *((intptr_t *) datap) = (intptr_t) fi->value;
101 
102  return true;
103 }
104 
105 
106 /* patcher_get_putfield ********************************************************
107 
108  Machine code:
109 
110 *******************************************************************************/
111 
113 {
114  u1 *ra;
115  unresolved_field *uf;
116  fieldinfo *fi;
117  s4 disp;
118 
120 
121  /* get stuff from the stack */
122 
123  ra = (u1 *) pr->mpc;
124  uf = (unresolved_field *) pr->ref;
125  disp = pr->disp;
126 
127  /* get the fieldinfo */
128 
129  if (!(fi = resolve_field_eager(uf)))
130  return false;
131 
133 
134  /* If there is an operand load before, skip the load size passed in disp (see ICMD_PUTFIELD) */
135 
136  ra += disp;
137 
138  /* patch correct offset */
139 
140  if (fi->type == TYPE_LNG) {
141  ASSERT_VALID_DISP(fi->offset + 4);
142  /* 2 RX operations, for 2 words; each already contains a 0 or 4 offset. */
143  N_RX_SET_DISP(ra, fi->offset + N_RX_GET_DISP(ra));
144  ra += SZ_RX;
145  N_RX_SET_DISP(ra, fi->offset + N_RX_GET_DISP(ra));
146  } else {
148  /* 1 RX operation */
149  N_RX_SET_DISP(ra, fi->offset);
150  }
151 
152  return true;
153 }
154 
155 /* patcher_invokestatic_special ************************************************
156 
157  Machine code:
158 
159 *******************************************************************************/
160 
162 {
163  unresolved_method *um;
164  u1 *datap;
165  methodinfo *m;
166 
168 
169  /* get stuff from the stack */
170 
171  um = (unresolved_method *) pr->ref;
172  datap = (u1 *) pr->datap;
173 
174  /* get the fieldinfo */
175 
176  if (!(m = resolve_method_eager(um)))
177  return false;
178 
180 
181  /* patch stubroutine */
182 
183  *((ptrint *) datap) = (ptrint) m->stubroutine;
184 
185  return true;
186 }
187 
188 /* patcher_invokevirtual *******************************************************
189 
190  Machine code:
191 
192 *******************************************************************************/
193 
195 {
196  u1 *ra;
197  unresolved_method *um;
198  methodinfo *m;
199  s4 off;
200 
202 
203  /* get stuff from the stack */
204 
205  ra = (u1 *) pr->mpc;
206  um = (unresolved_method *) pr->ref;
207 
208  /* get the fieldinfo */
209 
210  if (!(m = resolve_method_eager(um)))
211  return false;
212 
213  /* patch back original code */
214 
216 
217  /* patch vftbl index */
218 
219 
220  off = (s4) (OFFSET(vftbl_t, table[0]) +
221  sizeof(methodptr) * m->vftblindex);
222 
223  ASSERT_VALID_DISP(off);
224 
225  N_RX_SET_DISP(ra + SZ_RX, off);
226 
227  return true;
228 }
229 
230 
231 /* patcher_invokeinterface *****************************************************
232 
233  Machine code:
234 
235 *******************************************************************************/
236 
238 {
239  u1 *ra;
240  unresolved_method *um;
241  methodinfo *m;
242  s4 idx, off;
243 
245 
246  /* get stuff from the stack */
247 
248  ra = (u1 *) pr->mpc;
249  um = (unresolved_method *) pr->ref;
250 
251  /* get the fieldinfo */
252 
253  if (!(m = resolve_method_eager(um)))
254  return false;
255 
256  /* patch back original code */
257 
259 
260  /* get interfacetable index */
261 
262  idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
263  sizeof(methodptr) * m->clazz->index);
264 
265  ASSERT_VALID_IMM(idx);
266 
267  /* get method offset */
268 
269  off =
270  (s4) (sizeof(methodptr) * (m - m->clazz->methods));
271 
272  ASSERT_VALID_DISP(off);
273 
274  /* patch them */
275 
276  N_RI_SET_IMM(ra + SZ_L, idx);
277  N_RX_SET_DISP(ra + SZ_L + SZ_LHI + SZ_L, off);
278 
279  return true;
280 }
281 
282 
283 /* patcher_resolve_classref_to_flags *******************************************
284 
285  CHECKCAST/INSTANCEOF:
286 
287  <patched call position>
288 
289 *******************************************************************************/
290 
292 {
293  constant_classref *cr;
294  u1 *datap;
295  classinfo *c;
296 
298 
299  /* get stuff from the stack */
300 
301  cr = (constant_classref *) pr->ref;
302  datap = (u1 *) pr->datap;
303 
304  /* get the fieldinfo */
305 
306  if (!(c = resolve_classref_eager(cr)))
307  return false;
308 
310 
311  /* patch class flags */
312 
313  *((s4 *) datap) = (s4) c->flags;
314 
315  return true;
316 }
317 
318 /* patcher_resolve_classref_to_classinfo ***************************************
319 
320  ACONST:
321  MULTIANEWARRAY:
322  ARRAYCHECKCAST:
323 
324 *******************************************************************************/
325 
327 {
328  constant_classref *cr;
329  u1 *datap;
330  classinfo *c;
331 
333 
334  /* get stuff from the stack */
335 
336  cr = (constant_classref *) pr->ref;
337  datap = (u1 *) pr->datap;
338 
339  /* get the classinfo */
340 
341  if (!(c = resolve_classref_eager(cr)))
342  return false;
343 
345 
346  /* patch the classinfo pointer */
347 
348  *((ptrint *) datap) = (ptrint) c;
349 
350  return true;
351 }
352 
353 /* patcher_resolve_classref_to_vftbl *******************************************
354 
355  CHECKCAST (class):
356  INSTANCEOF (class):
357 
358 *******************************************************************************/
359 
361 {
362  constant_classref *cr;
363  u1 *datap;
364  classinfo *c;
365 
367 
368  /* get stuff from the stack */
369 
370  cr = (constant_classref *) pr->ref;
371  datap = (u1 *) pr->datap;
372 
373  /* get the fieldinfo */
374 
375  if (!(c = resolve_classref_eager(cr)))
376  return false;
377 
379 
380  /* patch super class' vftbl */
381 
382  *((ptrint *) datap) = (ptrint) c->vftbl;
383 
384  return true;
385 }
386 
387 /* patcher_checkcast_instanceof_interface **************************************
388 
389  Machine code:
390 
391 *******************************************************************************/
392 
394 {
395 
396  u1 *ra;
397  constant_classref *cr;
398  classinfo *c;
399 
401 
402  /* get stuff from the stack */
403 
404  ra = (u1 *) pr->mpc;
405  cr = (constant_classref *) pr->ref;
406 
407  /* get the fieldinfo */
408 
409  if (!(c = resolve_classref_eager(cr)))
410  return false;
411 
412  /* patch back original code */
413 
415 
416  /* patch super class index */
417 
418  /* From here, split your editor and open codegen.c */
419 
420  switch (N_RX_GET_REG(ra)) {
421  case REG_ITMP1:
422  /* First M_ALD is into ITMP1 */
423  /* INSTANCEOF code */
424 
425  N_RI_SET_IMM(ra + SZ_L + SZ_L, - c->index);
426  N_RI_SET_IMM(
427  ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC,
428  (int16_t)(OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*))
429  );
430  break;
431 
432  case REG_ITMP2:
433  /* First M_ALD is into ITMP2 */
434  /* CHECKCAST code */
435 
436  N_RI_SET_IMM(ra + SZ_L + SZ_L, - c->index);
437  N_RI_SET_IMM(
438  ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC + SZ_ILL,
439  (int16_t)(OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*))
440  );
441  break;
442 
443  default:
444  assert(0);
445  break;
446  }
447 
448  return true;
449 }
450 
451 
452 /*
453  * These are local overrides for various environment variables in Emacs.
454  * Please do not remove this and leave it at the end of the file, where
455  * Emacs will automagically detect them.
456  * ---------------------------------------------------------------------
457  * Local variables:
458  * mode: c++
459  * indent-tabs-mode: t
460  * c-basic-offset: 4
461  * tab-width: 4
462  * End:
463  * vim:noexpandtab:sw=4:ts=4:
464  */
#define ASSERT_VALID_DISP(x)
Definition: codegen.hpp:337
bool patcher_invokestatic_special(patchref_t *pr)
Definition: patcher.cpp:392
bool patcher_get_putstatic(patchref_t *pr)
Definition: patcher.cpp:264
#define SZ_RX
Definition: codegen.hpp:232
#define ra
Definition: md-asm.hpp:62
bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
Definition: patcher.cpp:148
methodinfo * methods
Definition: class.hpp:113
bool patcher_invokeinterface(patchref_t *pr)
Definition: patcher.cpp:477
bool patcher_checkcast_instanceof_interface(patchref_t *pr)
Definition: patcher.cpp:393
#define PATCH_BACK_ORIGINAL_MCODE
Definition: patcher.cpp:48
s4 state
Definition: class.hpp:115
#define PATCHER_TRACE
Definition: patcher.cpp:51
uint8_t u1
Definition: types.hpp:40
u1 * methodptr
Definition: global.hpp:40
#define SZ_AHI
Definition: codegen.hpp:407
static uint16_t N_RX_GET_DISP(uint8_t *instrp)
Definition: codegen.hpp:250
u1 * stubroutine
Definition: method.hpp:102
s4 vftblindex
Definition: method.hpp:81
int32_t offset
Definition: field.hpp:66
classinfo * clazz
Definition: method.hpp:80
void patcher_patch_code(patchref_t *pr)
Definition: patcher.cpp:114
bool patcher_invokevirtual(patchref_t *pr)
Definition: patcher.cpp:433
imm_union * value
Definition: field.hpp:67
bool patcher_resolve_classref_to_flags(patchref_t *pr)
Definition: patcher.cpp:225
s4 flags
Definition: class.hpp:90
#define SZ_ILL
Definition: codegen.hpp:388
int32_t s4
Definition: types.hpp:45
classinfo * clazz
Definition: field.hpp:55
s4 index
Definition: class.hpp:116
bool initialize_class(classinfo *c)
Definition: initialize.cpp:110
bool patcher_get_putfield(patchref_t *pr)
Definition: patcher.cpp:308
#define REG_ITMP2
Definition: md-abi.hpp:47
#define SZ_L
Definition: codegen.hpp:482
static uint8_t N_RX_GET_REG(uint8_t *instrp)
Definition: codegen.hpp:238
vftbl_t * vftbl
Definition: class.hpp:121
fieldinfo * resolve_field_eager(unresolved_field *ref)
Definition: resolve.cpp:1497
static void N_RI_SET_IMM(uint8_t *instrp, int16_t imm)
Definition: codegen.hpp:265
s4 type
Definition: field.hpp:60
methodinfo * resolve_method_eager(unresolved_method *ref)
Definition: resolve.cpp:2236
uintptr_t datap
#define SZ_LHI
Definition: codegen.hpp:492
#define SZ_BRC
Definition: codegen.hpp:435
classinfo * resolve_classref_eager(constant_classref *ref)
Definition: resolve.cpp:961
#define ASSERT_VALID_IMM(x)
Definition: codegen.hpp:332
uintptr_t ptrint
Definition: types.hpp:54
static void N_RX_SET_DISP(uint8_t *instrp, uint16_t disp)
Definition: codegen.hpp:254
uintptr_t mpc
#define OFFSET(s, el)
Definition: memory.hpp:90
bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
Definition: patcher.cpp:188
#define REG_ITMP1
Definition: md-abi.hpp:46