f7923e3fa3f267dcffc106602e1d7789fd05e4ec
[cacao.git] / src / vm / jit / m68k / patcher.c
1 /* src/vm/jit/m68k/patcher.c - m68k patcher functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
26
27 */
28
29 #include "config.h"
30
31 #include <assert.h>
32
33 #include "vm/types.h"
34
35 #include "mm/memory.h"
36 #include "native/native.h"
37
38 #include "vm/builtin.h"
39 #include "vm/exceptions.h"
40 #include "vm/initialize.h"
41 #include "vm/resolve.h"
42
43 #include "vm/jit/asmpart.h"
44 #include "vm/jit/patcher.h"
45 #include "vm/jit/md.h"
46 #include "vm/jit/methodheader.h"
47 #include "vm/jit/stacktrace.h"
48
49 #include "vmcore/class.h"
50 #include "vmcore/field.h"
51 #include "vmcore/options.h"
52 #include "vmcore/references.h"
53
54 #include "codegen.h"
55
56 /* patcher_wrapper *************************************************************
57
58    Wrapper for all patchers.  It also creates the stackframe info
59    structure.
60
61    If the return value of the patcher function is false, it gets the
62    exception object, clears the exception pointer and returns the
63    exception.
64
65 *******************************************************************************/
66
67 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
68 {
69         stackframeinfo     sfi;
70         u1                *xpc;
71         java_objectheader *o;
72         functionptr        f;
73         bool               result;
74         java_objectheader *e;
75
76         /* define the patcher function */
77
78         bool (*patcher_function)(u1 *);
79
80         /* get stuff from the stack */
81
82         xpc = (u1 *)                *((ptrint *) (sp + 6 * 4));
83         /* REG_ITMP3                              sp + 5 * 4 */
84         o   = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
85         /*mcode =                                   *((u4*)      (sp + 3 * 4));*/
86         /*xmcode =                                      *((u4*)      (sp + 2 * 4));*/
87         /* unresolved file                        sp + 1 * 4 */
88         f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
89
90
91         /* calculate and set the new return address */
92         xpc = xpc - PATCHER_CALL_SIZE;
93         *((ptrint *) (sp + 6 * 4)) = (ptrint) xpc;
94
95
96         /* cast the passed function to a patcher function */
97         patcher_function = (bool (*)(u1 *)) (ptrint) f;
98
99         /* enter a monitor on the patching position */
100         PATCHER_MONITORENTER;
101
102         /* create the stackframeinfo */
103
104         /* RA is passed as NULL, but the XPC is correct and can be used in
105            stacktrace_create_extern_stackframeinfo for
106            md_codegen_get_pv_from_pc. */
107
108         /*
109         fprintf(stderr, "EXT STACKFRAME: sfi=%x pv=%x, sp=%x, xpc=%x\n", &sfi, pv, sp+7*4, xpc);
110         */
111         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 7 * 4, xpc, xpc);
112
113         /* call the proper patcher function */
114         result = (patcher_function)(sp);
115
116
117         /* remove the stackframeinfo */
118         stacktrace_remove_stackframeinfo(&sfi);
119
120         /* check for return value and exit accordingly */
121         if (result == false) {
122                 e = exceptions_get_and_clear_exception();
123
124                 PATCHER_MONITOREXIT;
125
126                 return e;
127         }
128         PATCHER_MARK_PATCHED_MONITOREXIT;
129
130         return NULL;
131 }
132
133 /*      Helper
134  */
135 static void patcher_patch_back(u1 *sp)  
136 {
137         u1* xpc    = (u1 *)      *((ptrint *) (sp + 6 * 4));
138         u4 mcode  = *((u4*)      (sp + 3 * 4));
139         u4 xmcode = *((u4*)      (sp + 2 * 4));
140
141         *((u4*)(xpc))   = mcode;
142         *((u4*)(xpc+4)) = xmcode;
143         md_icacheflush(xpc, 8);
144 }
145
146 /* patcher_initialize_class ****************************************************
147
148    Initalizes a given classinfo pointer.  This function does not patch
149    any data.
150
151 *******************************************************************************/
152
153 bool patcher_initialize_class(u1 *sp)
154 {
155         classinfo *c;
156         u4                 xpc, mcode, xmcode;
157
158         /* get stuff from the stack */
159         c = (classinfo *) *((ptrint *) (sp + 1 * 4));
160
161         /* check if the class is initialized */
162         if (!(c->state & CLASS_INITIALIZED))
163                 if (!initialize_class(c))
164                         return false;
165
166         /* patch back original code */
167         patcher_patch_back(sp);
168
169         return true;
170 }
171
172 /* patcher_invokevirtual *******************************************************
173
174    Machine code:
175 0x4029bc46:   61ff 0000 00ba    bsrl 0x4029bd02
176 0x4029bc4c:   246f 0000         moveal %sp@(0),%a2
177 0x4029bc50:   266a 0000         moveal %a2@(0),%a3
178 0x4029bc54:   246b 0000         moveal %a3@(0),%a2      <-- patch this (0) offset
179 0x4029bc58:   4e92              jsr %a2@
180
181 *******************************************************************************/
182
183 bool patcher_invokevirtual(u1 *sp)
184 {
185         u1                *ra;
186         unresolved_method *um;
187         methodinfo        *m;
188         s2                 disp;
189
190         /* get stuff from the stack */
191         ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
192         um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
193
194         /* get the fieldinfo */
195         if (!(m = resolve_method_eager(um)))
196                 return false;
197
198         /* patch back original code */
199         patcher_patch_back(sp);
200
201         /* if we show NOPs, we have to skip them */
202         if (opt_shownops) ra += PATCHER_CALL_SIZE;
203
204         assert( *((u2*)(ra+8)) == 0x286b);
205
206         /* patch vftbl index */
207         disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
208         *((s2 *) (ra + 10)) = disp;
209
210         /* synchronize instruction cache */
211         md_icacheflush(ra + 10, 2);
212
213         return true;
214 }
215
216 /* patcher_invokestatic_special ************************************************
217
218    Machine code:
219
220    INVOKESPECIAL
221 0x402902bc:   61ff 0000 0076    bsrl 0x40290334
222 0x402902c2:   247c 0000 0000    moveal #0,%a2           <-- this #0
223 0x402902c8:   4e92              jsr %a2@
224
225 ******************************************************************************/
226
227 bool patcher_invokestatic_special(u1 *sp)
228 {
229         unresolved_method *um;
230         s4                 disp;
231         methodinfo        *m;
232
233         /* get stuff from the stack */
234         disp =                       *((s4 *)     (sp + 6 * 4));
235         um   = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
236
237         /* get the fieldinfo */
238         if (!(m = resolve_method_eager(um)))
239                 return false;
240
241         /* patch back original code */
242         patcher_patch_back(sp);
243
244         /* patch stubroutine */
245         if (opt_shownops) disp += PATCHER_CALL_SIZE;
246
247         *((ptrint *) (disp+2)) = (ptrint) m->stubroutine;
248
249         /* synchronize inst cache */
250
251         md_icacheflush(disp+2, SIZEOF_VOID_P);
252
253         return true;
254 }
255
256
257 /* patcher_resolve_class *******************************************************
258
259    Resolves a given unresolved_class pointer.  This function does not
260    patch any data.
261
262 *******************************************************************************/
263
264 #ifdef ENABLE_VERIFIER
265 bool patcher_resolve_class(u1 *sp)
266 {
267         unresolved_class *uc;
268         classinfo        *c;
269         s4                              disp;
270
271         /* get stuff from the stack */
272         uc = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
273         disp =                    *((s4 *)     (sp + 6 * 4));
274
275         /* resolve the class */
276         if (!resolve_class(uc, resolveEager, false, &c))
277                 return false;
278
279         /* patch back original code */
280         patcher_patch_back(sp);
281
282         return true;
283 }
284 #endif /* ENABLE_VERIFIER */
285
286 /* patcher_resolve_classref_to_classinfo ***************************************
287   ACONST:
288         0x4028f2ca:   2479 0000 0000    moveal 0x00000000,%a2
289 *******************************************************************************/
290 bool patcher_resolve_classref_to_classinfo(u1 *sp)
291 {
292         constant_classref *cr;
293         s4                 disp;
294         u1                *pv;
295         classinfo         *c;
296
297         /* get stuff from the stack */
298         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
299         disp =                       *((s4 *)     (sp + 6 * 4));
300
301         /* get the classinfo */
302         if (!(c = resolve_classref_eager(cr)))
303                 return false;
304
305         /* patch back original code */
306         patcher_patch_back(sp);
307
308         /* patch the classinfo pointer */
309         if (opt_shownops) disp += PATCHER_CALL_SIZE;
310         *((ptrint *) (disp+2)) = (ptrint) c;
311
312         /* synchronize inst cache */
313         md_icacheflush(disp+2, SIZEOF_VOID_P);
314
315         return true;
316 }
317
318 /* patcher_get_putstatic *******************************************************
319
320    Machine code:
321
322 *******************************************************************************/
323
324 bool patcher_get_putstatic(u1 *sp)
325 {
326         u1               *ra;
327         unresolved_field *uf;
328         s4                disp;
329         u1               *pv;
330         fieldinfo        *fi;
331
332         /* get stuff from the stack */
333         uf    = (unresolved_field *)  *((ptrint *) (sp + 1 * 4));
334         disp  =                       *((s4 *)     (sp + 6 * 4));
335
336         /* get the fieldinfo */
337         if (!(fi = resolve_field_eager(uf)))
338                 return false;
339
340         /* check if the field's class is initialized */
341         if (!(fi->class->state & CLASS_INITIALIZED))
342                 if (!initialize_class(fi->class))
343                         return false;
344
345         /* patch back original code */
346         patcher_patch_back(sp);
347
348         /* patch the field value's address */
349         if (opt_shownops) disp += PATCHER_CALL_SIZE;
350         assert(*((uint16_t*)(disp)) == 0x247c);
351         *((ptrint *) (disp+2)) = (ptrint) &(fi->value);
352
353         /* synchronize inst cache */
354         md_icacheflush(disp+2, SIZEOF_VOID_P);
355
356         return true;
357 }
358
359 /* patcher_get_putfield ********************************************************
360
361    Machine code:
362
363    <patched call position>
364
365 *******************************************************************************/
366
367 bool patcher_get_putfield(u1 *sp)
368 {
369         u1               *ra;
370         unresolved_field *uf;
371         fieldinfo        *fi;
372         s2                disp;
373
374         ra = (u1 *)               *((ptrint *) (sp + 6 * 4));
375         uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
376
377         /* get the fieldinfo */
378         if (!(fi = resolve_field_eager(uf)))
379                 return false;
380
381         /* patch back original code */
382         patcher_patch_back(sp);
383
384         /* if we show NOPs, we have to skip them */
385         if (opt_shownops) ra += PATCHER_CALL_SIZE;
386
387         /* patch the field's offset */
388         if (IS_LNG_TYPE(fi->type)) {
389                 /*
390                  *      0x40d05bb2:     0x25440000      movel %d4,%a2@(0)
391                  *      0x40d05bb6:     0x25430004      movel %d3,%a2@(4)
392                  *                                            ^^^^
393                  *                                            both 0000 and 0004 have to be patched
394                  */
395
396                 assert( (fi->offset & 0x0000ffff) == fi->offset );
397
398                 assert( (*((uint32_t*)ra) & 0xffff0000) == *((uint32_t*)ra) );
399                 assert( (*((uint32_t*)(ra+4)) & 0xffff0004) == *((uint32_t*)(ra+4)) );
400
401                 *((int16_t *) (ra + 2)) = (int16_t) ((fi->offset) & 0x0000ffff);
402                 *((int16_t *) (ra + 6)) = (int16_t) ((fi->offset + 4) & 0x0000ffff);
403
404                 md_icacheflush(ra, 2 * 4);
405         } else  {
406                 /*      Multiple cases here, int, adr, flt and dbl. */
407                 if ( (*((uint32_t*)ra) & 0xfff00000) == 0xf2200000 )    {
408                         /* flt/dbl case 
409                          * 0x40d3ddc2:     0xf22944c0 0x0000xxxx        fsmoves %a1@(0),%fp1
410                          *                                  ^^^^
411                          *                                  patch here 
412                          */
413                         assert( (fi->offset & 0x0000ffff) == fi->offset );
414                         assert( (*((uint32_t*)(ra+4)) & 0x0000ffff) == *((uint32_t*)(ra+4)) );
415                         *((int16_t*)(ra+4)) = (int16_t)fi->offset;
416
417                         md_icacheflush(ra+4, 1 * 4);
418                 } else  {
419                         /*      int/adr case
420                          *      0x40adb3f6:     0x254d0000      movel %a5,%a2@(0)
421                          *                            ^^^^                     ^
422                          *                            to be patched
423                          */
424                         assert( (*((uint32_t*)ra) & 0xffff0000) == *((uint32_t*)ra) );
425                         assert( (fi->offset & 0x0000ffff) == fi->offset );
426                         *((int16_t*)(ra+2)) = (int16_t)fi->offset;
427
428                         /* synchronize instruction cache */
429                         md_icacheflush(ra, 1 * 4);
430                 }
431         }
432
433         return true;
434 }
435 /* patcher_resolve_classref_to_flags *******************************************
436
437    CHECKCAST/INSTANCEOF:
438
439
440 CHECKCAST:
441 0x4029b056:   61ff 0000 013e    bsrl 0x4029b196
442 0x4029b05c:   263c 0000 0000    movel #0,%d3            <-- patch this #0
443 0x4029b062:   0283 0000 0200    andil #512,%d3
444
445 INSTANCEOF:
446 0x402a4aa8:   61ff 0000 05c4    bsrl 0x402a506e
447 0x402a4aae:   283c 0000 0000    movel #0,%d4            <-- same here
448 0x402a4ab4:   0284 0000 0200    andil #512,%d4
449
450
451 *******************************************************************************/
452
453 bool patcher_resolve_classref_to_flags(u1 *sp)
454 {
455         constant_classref *cr;
456         s4                 disp;
457         classinfo         *c;
458
459         /* get stuff from the stack */
460         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
461         disp =                       *((s4 *)     (sp + 6 * 4));
462
463         /* get the fieldinfo */
464         if (!(c = resolve_classref_eager(cr)))
465                 return false;
466
467         /* patch back original code */
468         patcher_patch_back(sp);
469
470         /* patch class flags */
471         if (opt_shownops) disp += PATCHER_CALL_SIZE;
472         assert( (*((u2*)(disp)) == 0x263c) || (*((u2*)(disp)) == 0x283c) );
473         *((s4 *) (disp + 2)) = (s4) c->flags;
474
475         /* synchronize insn cache */
476         md_icacheflush(disp + 2, SIZEOF_VOID_P);
477
478         return true;
479 }
480
481 /* patcher_resolve_classref_to_vftbl *******************************************
482
483    CHECKCAST (class):
484 0x4029b094:   61ff 0000 00b4    bsrl 0x4029b14a
485 0x4029b09a:   287c 0000 0000    moveal #0,%a4           <-- patch this #0
486 0x4029b0a0:   2668 0000         moveal %a0@(0),%a3
487
488    INSTANCEOF (class):
489 0x402a9300:   61ff 0000 0574    bsrl 0x402a9876
490 0x402a9306:   267c 0000 0000    moveal #0,%a3
491 0x402a930c:   246a 0000         moveal %a2@(0),%a2
492
493
494 *******************************************************************************/
495
496 bool patcher_resolve_classref_to_vftbl(u1 *sp)
497 {
498         constant_classref *cr;
499         s4                 disp;
500         classinfo         *c;
501
502         /* get stuff from the stack */
503         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
504         disp =                       *((s4 *)     (sp + 6 * 4));
505
506         /* get the fieldinfo */
507         if (!(c = resolve_classref_eager(cr)))
508                 return false;
509
510         /* patch back original code */
511         patcher_patch_back(sp);
512
513         /* patch super class' vftbl */
514         if (opt_shownops) disp += PATCHER_CALL_SIZE;
515         assert( (*((u2*)disp) == 0x287c) || (*((u2*)disp)== 0x267c) );
516
517         *((s4 *) (disp+2)) = (s4) c->vftbl;
518
519         /* synchronize insin cache */
520         md_icacheflush(disp+2, SIZEOF_VOID_P);
521
522         return true;
523 }
524
525 /* patcher_instanceof_interface ************************************************
526
527    Machine code:
528
529 0x402a92da:   61ff 0000 05c0    bsrl 0x402a989c
530 0x402a92e0:   246a 0000         moveal %a2@(0),%a2
531 0x402a92e4:   282a 0010         movel %a2@(16),%d4
532 0x402a92e8:   d8bc 0000 0000    addl #0,%d4             <-- this const
533 0x402a92ee:   4a84              tstl %d4
534 0x402a92f0:   6e0a              bles 0x402a92fc
535 0x402a92f2:   246a 0000         moveal %a2@(0),%a2      <-- this offset
536
537 *******************************************************************************/
538
539 bool patcher_instanceof_interface(u1 *sp)
540 {
541         u1                *ra;
542         constant_classref *cr;
543         classinfo         *c;
544         s4                 disp;
545
546         /* get stuff from the stack */
547
548         ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
549         cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
550
551         /* get the fieldinfo */
552         if (!(c = resolve_classref_eager(cr)))
553                 return false;
554
555         /* patch back original code */
556         patcher_patch_back(sp);
557
558         /* if we show NOPs, we have to skip them */
559         if (opt_shownops) ra += PATCHER_CALL_SIZE;
560                 
561         /* patch super class index */
562         disp = -(c->index);
563         assert( *((u2*)(ra + 8)) == 0xd8bc );
564         *((s4 *) (ra + 10 )) = disp;
565
566         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
567
568         assert( (s2)disp  == disp);
569         assert ( *((s2*)(ra+18)) == 0x246a );
570
571         *((s2 *) (ra + 20)) = disp;
572
573         /* synchronize instruction cache */
574         md_icacheflush(ra + 10, 12);
575
576         return true;
577 }
578
579 /* patcher_checkcast_interface *************************************************
580
581 0x402a9400:   61ff 0000 03b6    bsrl 0x402a97b8
582 0x402a9406:   266a 0000         moveal %a2@(0),%a3
583 0x402a940a:   282b 0010         movel %a3@(16),%d4
584 0x402a940e:   d8bc 0000 0000    addl #0,%d4             <-- this 0
585 0x402a9414:   4a84              tstl %d4
586 0x402a9416:   6e02              bgts 0x402a941a
587               1234              tstb %d0
588 0x402a9418:   4afc              illegal
589 0x402a941a:   286b 0000         moveal %a3@(0),%a4      <-- and this 0 offset
590
591 *******************************************************************************/
592
593 bool patcher_checkcast_interface(u1 *sp)
594 {
595         u1                *ra;
596         constant_classref *cr;
597         classinfo         *c;
598         s4                 disp;
599
600         /* get stuff from the stack */
601         ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
602         cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
603
604         /* get the fieldinfo */
605         if (!(c = resolve_classref_eager(cr)))
606                 return false;
607
608         /* patch back original code */
609         patcher_patch_back(sp);
610
611         /* if we show NOPs, we have to skip them */
612         if (opt_shownops) ra += PATCHER_CALL_SIZE;
613
614         /* patch super class index */
615         disp = -(c->index);
616         assert ( *((u2 *)(ra + 8)) == 0xd8bc );
617         *((s4 *) (ra + 10)) = disp;
618
619         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
620         assert( *((u2 *)(ra + 22)) == 0x286b );
621         assert( (s2)disp == disp);
622         *((s2 *) (ra + 24)) = disp;
623         
624         /* synchronize instruction cache */
625         md_icacheflush(ra + 10, 16);
626
627         return true;
628 }
629
630 /* patcher_resolve_native_function *********************************************
631
632    XXX
633
634 *******************************************************************************/
635
636 #if !defined(WITH_STATIC_CLASSPATH)
637 bool patcher_resolve_native_function(u1 *sp)
638 {
639         methodinfo  *m;
640         s4           disp;
641         functionptr  f;
642
643         /* get stuff from the stack */
644         m    = (methodinfo *) *((ptrint *) (sp + 1 * 4));
645         disp =                *((s4 *)     (sp + 6 * 4));
646
647         /* resolve native function */
648         if (!(f = native_resolve_function(m)))
649                 return false;
650
651         /* patch back original code */
652         patcher_patch_back(sp);
653
654         /* patch native function pointer */
655         if (opt_shownops) disp += PATCHER_CALL_SIZE;
656         *((ptrint *) (disp + 2)) = (ptrint) f;
657
658         /* synchronize data cache */
659         md_icacheflush(disp + 2, SIZEOF_VOID_P);
660
661         return true;
662 }
663 #endif /* !defined(WITH_STATIC_CLASSPATH) */
664
665
666 /* patcher_invokeinterface *****************************************************
667
668    Machine code:
669 0x40adb03e:     moveal %a2@(0),%a3              0x266a0000              <-- no patching
670 0x40adb042:     moveal %a3@(0),%a3              0x266b0000              <-- patch this 0000
671 0x40adb046:     moveal %a3@(0),%a4              0xxxxx0000              <-- patch this 0000
672 0x40adb04a:     jsr %a4@                                0xxxxx                  
673
674
675 *******************************************************************************/
676
677 bool patcher_invokeinterface(u1 *sp)
678 {
679         u1                *ra;
680         unresolved_method *um;
681         methodinfo        *m;
682         s4                 disp;
683
684         /* get stuff from the stack */
685         ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
686         um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
687
688
689         /* get the fieldinfo */
690         if (!(m = resolve_method_eager(um)))
691                 return false;
692
693         /* patch back original code */
694         patcher_patch_back(sp);
695
696         /* if we show NOPs, we have to skip them */
697         if (opt_shownops) ra += PATCHER_CALL_SIZE;
698         assert( *((uint32_t*)ra) == 0x246f0000 );
699
700         /* patch interfacetable index (first #0) */
701         disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index;
702         /* XXX this disp is negative, check! 
703          * assert( (disp & 0x0000ffff) == disp);*/
704         *((uint16_t *) (ra + 5 * 2)) = disp;
705
706         /* patch method offset (second #0) */
707         disp = sizeof(methodptr) * (m - m->class->methods);
708         assert( (disp & 0x0000ffff) == disp);
709         *((uint16_t *) (ra + 7 * 2)) = disp;
710
711         /* synchronize instruction cache */
712         md_icacheflush(ra + 5 * 2, 2 * 2);
713
714         return true;
715 }
716 /*
717  * These are local overrides for various environment variables in Emacs.
718  * Please do not remove this and leave it at the end of the file, where
719  * Emacs will automagically detect them.
720  * ---------------------------------------------------------------------
721  * Local variables:
722  * mode: c
723  * indent-tabs-mode: t
724  * c-basic-offset: 4
725  * tab-width: 4
726  * End:
727  * vim:noexpandtab:sw=4:ts=4:
728  */