- created jitcache-arm-x86 branch
[cacao.git] / src / vm / jit / jitcache.c
1 /* src/vm/jit/jitcache.c - JIT caching stuff
2
3    Copyright (C) 2008
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 #include "config.h"
26
27 #if defined(ENABLE_JITCACHE)
28
29 /* for mkdir() */
30 #include <sys/stat.h>
31
32 #include <assert.h>
33 #include <stdint.h>
34
35 #include "md.h"
36
37 #include "toolbox/list.h"
38 #include "toolbox/logging.h"
39
40 #include "mm/memory.h"
41 #include "mm/codememory.h"
42
43 #include "vm/types.h"
44 #include "vm/resolve.h"
45 #include "vm/builtin.h"
46 #include "vm/stringlocal.h"
47
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/jit.h"
50 #include "vm/jit/code.h"
51 #include "vm/jit/patcher-common.h"
52 #include "vm/jit/codegen-common.h"
53 #include "vm/jit/linenumbertable.h"
54 #include "vm/jit/exceptiontable.h"
55 #include "vm/jit/methodtree.h"
56
57 #include "vmcore/references.h"
58 #include "vmcore/method.h"
59 #include "vmcore/system.h"
60 #include "vmcore/field.h"
61 #include "vmcore/utf8.h"
62 #include "vmcore/options.h"
63
64 #include "vm/jit/jitcache.h"
65
66 #include "threads/mutex.h"
67
68 /* TODO: Wrap this in vm/system.h" */
69 #include "unistd.h"
70
71 #define CACHEROOT "/tmp/cacao-jitcache/"
72
73 /* small grained helper functions */
74 char *get_dest_dir(methodinfo *);
75 char *get_dest_file(methodinfo *);
76
77 int mkdir_hier(char *, mode_t);
78 int open_to_read(char *);
79 int open_to_write(char *);
80
81 u1 *to_abs(u1 *, u1 *);
82 u1 *to_offset(u1 *, u1 *);
83
84 void store_utf(int, utf *);
85 void store_classinfo(int, classinfo *);
86 void store_builtin(int, builtintable_entry *);
87 void store_string(int, java_object_t *);
88 void store_methodinfo(int, methodinfo *);
89 void store_fieldinfo(int, fieldinfo *);
90 void store_cachedref(int, cachedref_t *);
91
92 void load_utf(utf **, int);
93 void load_classinfo(classinfo **, int, methodinfo *);
94 void load_builtin(builtintable_entry **, int);
95 void load_string(java_object_t **, int);
96 void load_methodinfo(methodinfo **, int, methodinfo *);
97 void load_fieldinfo(fieldinfo **, int, methodinfo *);
98 void load_cachedref(cachedref_t **, int, codeinfo *);
99
100 /* medium grained helper functions */
101 void load_from_file_patchers(codeinfo *, int);
102 void load_from_file_cachedrefs(codeinfo *, int);
103 void load_from_file_exceptiontable(codeinfo *, int);
104 void load_from_file_linenumbertable(codeinfo *, int);
105
106 void store_to_file_patchers(int, codeinfo *);
107 void store_to_file_cachedrefs(int, codeinfo *);
108 void store_to_file_linenumbertable(int, codeinfo *);
109 void store_to_file_exceptiontable(int, codeinfo *);
110
111 /* file handling functions */
112 void update_method_table(methodinfo *, int);
113 int seek_method_table(methodinfo *, int);
114 int get_cache_file_readable(methodinfo *);
115 int get_cache_file_writable(methodinfo *);
116
117 /* serializer forward declarations */
118 void s_dummy(int, patchref_t *, methodinfo *);
119 void s_unresolved_class(int, patchref_t *, methodinfo *);
120 void s_unresolved_field(int, patchref_t *, methodinfo *);
121 void s_unresolved_method(int, patchref_t *, methodinfo *);
122 void s_constant_classref(int, patchref_t *, methodinfo *);
123 void s_classinfo(int, patchref_t *, methodinfo *);
124 void s_methodinfo(int, patchref_t *, methodinfo *);
125 void s_fieldinfo(int, patchref_t *, methodinfo *);
126 void s_string(int, patchref_t *, methodinfo *);
127
128 /* deserializer forward declarations */
129 void d_dummy(patchref_t *, int, methodinfo *);
130 void d_unresolved_class(patchref_t *, int, methodinfo *);
131 void d_unresolved_field(patchref_t *, int, methodinfo *);
132 void d_unresolved_method(patchref_t *, int, methodinfo *);
133 void d_constant_classref(patchref_t *, int, methodinfo *);
134 void d_classinfo(patchref_t *, int, methodinfo *);
135 void d_methodinfo(patchref_t *, int, methodinfo *);
136 void d_fieldinfo(patchref_t *, int, methodinfo *);
137 void d_string(patchref_t *, int, methodinfo *);
138
139 /* The order of entries follows the order of
140  * declarations in patcher-common.h
141  */
142
143 static jitcache_patcher_function_list_t patcher_functions[] = {
144                 { PATCHER_resolve_class, s_unresolved_class, d_unresolved_class },
145                 { PATCHER_initialize_class, s_classinfo, d_classinfo },
146                 { PATCHER_resolve_classref_to_classinfo, s_constant_classref, d_constant_classref },
147                 { PATCHER_resolve_classref_to_vftbl, s_constant_classref, d_constant_classref },
148                 { PATCHER_resolve_classref_to_index, s_constant_classref, d_constant_classref },
149                 { PATCHER_resolve_classref_to_flags, s_constant_classref, d_constant_classref },
150                 { PATCHER_resolve_native_function, s_methodinfo, d_methodinfo },
151
152                 /* old patcher functions */
153                 { PATCHER_get_putstatic, s_unresolved_field, d_unresolved_field },
154
155 #if defined(__I386__)
156                 { PATCHER_getfield, s_unresolved_field, d_unresolved_field },
157                 { PATCHER_putfield, s_unresolved_field, d_unresolved_field },
158 #else
159                 { PATCHER_get_putfield, s_unresolved_field, d_unresolved_field },
160 #endif
161
162 #if defined(__I386__) || defined(__X86_64__)
163                 { PATCHER_putfieldconst, s_unresolved_field, d_unresolved_field }, /* 10 */
164 #endif
165
166                 { PATCHER_invokestatic_special, s_unresolved_method, d_unresolved_method },
167                 { PATCHER_invokevirtual, s_unresolved_method, d_unresolved_method },
168                 { PATCHER_invokeinterface, s_unresolved_method, d_unresolved_method },
169
170 #if defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
171                 { PATCHER_checkcast_interface, s_constant_classref, d_constant_classref },
172                 { PATCHER_instanceof_interface, s_constant_classref, d_constant_classref },
173 #endif
174
175 #if defined(__S390__)
176                 { PATCHER_checkcast_instanceof_interface, s_dummy, d_dummy },
177 #endif
178
179 #if defined(__I386__)
180                 { PATCHER_aconst, s_constant_classref, d_constant_classref }, /* 16 */
181                 { PATCHER_builtin_multianewarray, s_constant_classref, d_constant_classref },
182                 { PATCHER_builtin_arraycheckcast, s_constant_classref, d_constant_classref },
183                 { PATCHER_checkcast_instanceof_flags, s_constant_classref, d_constant_classref },
184                 { PATCHER_checkcast_class, s_constant_classref, d_constant_classref },
185                 { PATCHER_instanceof_class, s_constant_classref, d_constant_classref },
186 #endif
187
188                 { NULL, s_dummy, d_dummy }
189 };
190
191 #define JC_MRU_SIZE 100
192 static classinfo *jc_mru_list[JC_MRU_SIZE];
193 int mru_last_free = 0;
194 int mru_start = 0;
195
196 /* jitcache_mru_add ************************************************************
197
198    Adds a classinfo to the most recently used (MRU) list. The MRU uses a simple
199    strategy: it will store entries until it is full, further candidates replace
200    the 
201
202 *******************************************************************************/
203
204 void jitcache_mru_add(classinfo *c, int fd)
205 {
206         classinfo *old_c;
207         assert(!c->cache_file_fd);
208
209         c->cache_file_fd = fd;
210
211         if (mru_last_free < JC_MRU_SIZE) {
212                 jc_mru_list[mru_last_free] = c;
213
214                 mru_last_free++;
215
216                 return;
217         }
218         else {
219                 mru_start--;
220                 if (mru_start < 0)
221                         mru_start = JC_MRU_SIZE - 1;
222
223                 old_c = jc_mru_list[mru_start];
224
225                 assert (old_c);
226                 assert (old_c->cache_file_fd);
227                 system_close(old_c->cache_file_fd);
228                 old_c->cache_file_fd = 0;
229
230                 jc_mru_list[mru_start] = c;
231         }
232         
233 }
234
235 void jitcache_mru_remove(classinfo *c)
236 {
237         int i, j;
238
239         for (i = 0; i < JC_MRU_SIZE; i++)
240                 if (jc_mru_list[i] == c) {
241                         jc_mru_list[j] = NULL;
242
243                         for (j = i; i < mru_last_free - 1; j++)
244                                 jc_mru_list[j] = jc_mru_list[j+1];
245
246                         mru_last_free--;
247                 }
248
249         assert (0);
250 }
251
252 /* jitcache_list_create ********************************************************
253
254    Creates an empty cached reference list for the given codeinfo.
255
256 *******************************************************************************/
257
258 void jitcache_list_create(codeinfo *code)
259 {
260         code->cachedrefs = list_create(OFFSET(cachedref_t, linkage));
261 }
262
263
264 /* jitcache_list_reset **********************************************************
265
266    Resets the cached reference list inside a codeinfo.
267
268 *******************************************************************************/
269
270 void jitcache_list_reset(codeinfo *code)
271 {
272         cachedref_t *pr;
273
274         /* free all elements of the list */
275
276         while((pr = list_first(code->cachedrefs)) != NULL) {
277                 list_remove(code->cachedrefs, pr);
278
279                 FREE(pr, cachedref_t);
280
281 #if defined(ENABLE_STATISTICS)
282                 if (opt_stat)
283                         size_cachedref -= sizeof(cachedref_t);
284 #endif
285         }
286 }
287
288
289 /* jitcache_list_free ***********************************************************
290
291    Frees the cached reference list and all its entries for the given codeinfo.
292
293 *******************************************************************************/
294
295 void jitcache_list_free(codeinfo *code)
296 {
297         /* free all elements of the list */
298
299         jitcache_list_reset(code);
300
301         /* free the list itself */
302
303         FREE(code->cachedrefs, list_t);
304 }
305
306
307 /* jitcache_list_find ***********************************************************
308
309    Find an entry inside the cached reference list for the given codeinfo
310    by specifying the displacement in the code/data segment.
311
312    NOTE: Caller should hold the patcher list lock or maintain
313    exclusive access otherwise.
314
315 *******************************************************************************/
316
317 static cachedref_t *jitcache_list_find(codeinfo *code, s4 disp)
318 {
319         cachedref_t *cr;
320
321         /* walk through all cached references for the given codeinfo */
322
323         cr = list_first(code->cachedrefs);
324         while (cr) {
325
326                 if (cr->disp == disp)
327                         return cr;
328
329                 cr = list_next(code->cachedrefs, cr);
330         }
331
332         return NULL;
333 }
334
335
336 /* jitcache_new_cachedref ******************************************************
337
338    Creates and initializes a new cachedref
339
340 *******************************************************************************/
341
342 cachedref_t *jitcache_new_cached_ref(cachedreftype type, s4 md_patch, voidptr ref, s4 disp)
343 {
344         cachedref_t *cr;
345
346         /* allocate cachedref on heap (at least freed together with codeinfo) */
347
348         cr = NEW(cachedref_t);
349
350 #if defined(ENABLE_STATISTICS)
351         if (opt_stat)
352                 size_cachedref += sizeof(cachedref_t);
353 #endif
354
355         /* set reference information */
356
357         cr->type    = type;
358         cr->md_patch= md_patch;
359         cr->disp    = disp;
360         cr->ref     = ref;
361
362         return cr;
363 }
364 /* jitcache_add_cachedref_jd ***************************************************
365
366    Creates a new cached ref appends it to the list in the codeinfo structure
367    *or* attaches it to the *last* patchref_t if it overlaps with the address
368    of the cached reference.
369
370 *******************************************************************************/
371
372 void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t *cachedref)
373 {
374         cachedref_t *list_cr;
375
376         list_cr = (cachedref_t *) list_first(code->cachedrefs);
377
378         while (list_cr)
379         {
380                 if (list_cr->disp == cachedref->disp)
381                 {
382                         assert(list_cr->type == cachedref->type);
383                         assert(list_cr->ref == cachedref->ref);
384
385                         /* Cachedref for already existing object found. No need to store
386                          * it.
387              */
388                         return;
389                 }
390
391                 list_cr = list_next(code->cachedrefs, list_cr);
392         }
393
394         list_add_first(code->cachedrefs, cachedref);
395 }
396
397 /* jitcache_add_cachedref_jd ***************************************************
398
399    Creates a new cached ref appends it to the list in the codeinfo structure
400    *or* attaches it to the *last* patchref_t if it overlaps with the address
401    of the cached reference.
402
403 *******************************************************************************/
404
405 void jitcache_add_cached_ref_jd(jitdata *jd, cachedreftype type, voidptr ref)
406 {
407         jitcache_add_cached_ref_md_jd(jd, type, 0, ref);
408 }
409
410
411 /* jitcache_add_cachedref_md_jd ************************************************
412
413    Creates a new cached ref appends it to the list in the codeinfo structure
414    *or* attaches it to the *last* patchref_t if it overlaps with the address
415    of the cached reference.
416
417 *******************************************************************************/
418
419 void jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch, voidptr ref)
420 {
421         patchref_t       *patchref;
422         codegendata      *cd;
423         s4                       disp;
424         cachedref_t *cachedref;
425
426         if (type >= CRT_OBJECT_HEADER && !ref)
427                 return;
428
429         cd = jd->cd;
430
431         disp = (s4) (cd->mcodeptr - cd->mcodebase) - SIZEOF_VOID_P;
432         cachedref = jitcache_new_cached_ref(type, md_patch, ref, disp);
433
434         patchref = (patchref_t *) list_first(jd->code->patchers);
435
436         if (patchref
437                 && (patchref->mpc) <= disp
438                 && (patchref->mpc + sizeof(patchref->mcode)) >= disp)
439         {
440                 /* patchers and cachedref overlap: cached ref must
441                  * be handled after the patcher.
442          */
443
444                 if (opt_DebugJitCache)
445                 {
446                         log_message_method("cached ref overlaps with patchref: ", jd->m);
447                 }
448
449                 /* There can be only one cached ref per patcher currently.
450          * If the need arises to handle more cached refs a list can
451          * be used.
452          */
453                 assert(!patchref->attached_ref);
454
455                 patchref->attached_ref = cachedref;
456         }
457         else
458                 jitcache_add_cached_ref_intern(jd->code, cachedref);
459 }
460
461
462 /* jitcache_add_cachedref ******************************************************
463
464    Creates a new cached references and appends it to the list.
465
466 *******************************************************************************/
467
468 void jitcache_add_cached_ref(codeinfo *code, cachedreftype type, voidptr ref, s4 disp)
469 {
470         cachedref_t *cr;
471
472         /* allocate cachedref on heap (at least freed together with codeinfo) */
473         cr = jitcache_new_cached_ref(type, 0, ref,disp);
474
475         jitcache_add_cached_ref_intern(code, cr);
476 }
477
478
479
480 /* jitcache_handle_cached_ref **************************************************
481
482    Creates a new cached references and appends it to the list.
483
484 *******************************************************************************/
485
486 void jitcache_handle_cached_ref(cachedref_t *cr, codeinfo *code)
487 {
488         u1 **location;
489
490         location = (u1 **) (code->entrypoint + cr->disp);
491
492         /* Write the restored reference into the code. */
493         if (cr->md_patch)
494                 patch_md(cr->md_patch, (ptrint) location, cr->ref);
495         else
496                 *location = cr->ref;
497
498         md_cacheflush(location, SIZEOF_VOID_P);
499
500         FREE(cr, cachedref_t);
501 }
502
503 #include <stdlib.h>
504 #include <stdio.h>
505
506 bool filter(utf *classname)
507 {
508         static bool printed = false;
509         char *buf = NULL;
510         int i = 0;
511         int max_index = 30000;
512         const char *classes[] = {
513                 "Test$FooBar",
514                 "Test",
515                 "FieldTest",
516                 "UnresolvedClass",
517                 "java/lang/ThreadGroup",
518                 "java/lang/Object",
519                 "java/util/Vector",
520                 "java/util/Vector$1",
521                 "java/util/AbstractList", 
522                 "java/util/AbstractCollection",
523                 "java/lang/Thread",
524                 "java/lang/String",
525                 "java/lang/ClassLoader",
526                 "java/lang/VMClassLoader",
527                 "java/util/HashMap",
528                 "java/util/HashSet",
529                 "java/util/AbstractSet",
530                 "gnu/classpath/SystemProperties",
531                 "java/util/Properties",
532                 "java/util/Hashtable",
533                 "java/util/Dictionary",
534                 "java/util/Hashtable$HashEntry",
535                 "java/util/AbstractMap$SimpleEntry",
536                 "java/lang/StringBuilder",
537                 "java/lang/AbstractStringBuffer",
538                 "java/util/Collections$SynchronizedSet",
539                 "java/util/Collections$SynchronizedCollection",
540                 "java/util/Hashtable$3",
541                 "java/util/Hashtable$EntryIterator",
542                 "java/util/Collections$SynchronizedIterator",
543                 "java/lang/Boolean",
544                 "java/util/Collections",
545                 "java/util/Collections$EmptySet",
546                 "java/util/Collections$EmptyList",
547                 "java/util/Collections$EmptyMap",
548                 "java/util/Collections$ReverseComparator",
549                 "java/util/Collections$UnmodifiableMap",
550                 "java/io/File",
551                 "java/util/StringTokenizer",
552                 "java/util/ArrayList",
553                 "java/io/VMFile",
554                 "java/lang/System",
555                 "java/lang/VMSystem",
556                 "java/io/FileDescriptor",
557                 "gnu/java/io/FileChannelImpl",
558                 "java/lang/Runtime",
559                 "gnu/classpath/VMStackWalker",
560                 "gnu/java/io/VMChannel",
561                 "gnu/java/io/VMChannel$State",
562                 "gnu/java/io/VMChannel$Kind",
563                 "java/nio/channels/FileChannelImpl",
564                 "java/nio/channels/spi/AbstractInterruptibleChannel",
565                 "java/lang/Number",
566                 "java/io/FileInputStream",
567                 "java/io/InputStream",
568                 "java/io/BufferedInputStream",
569                 "java/io/FilterInputStream",
570                 "java/io/PrintStream",
571                 "java/io/OutputStream",
572                 "java/io/BufferedOutputStream",
573                 "java/io/FilterOutputStream",
574                 "java/net/URL",
575                 "java/util/Locale",
576                 "java/lang/Math",
577                 "gnu/java/lang/CharData",
578                 "java/lang/Character",
579                 "java/net/URL$1",
580                 "java/security/VMAccessController",
581                 "java/lang/ThreadLocal",
582                 "java/security/CodeSource",
583                 "**placeholder**",
584                 "java/security/PermissionCollection",
585                 "Test$1",
586                 "java/security/ProtectionDomain",
587                 "java/security/AccessControlContext",
588                 "gnu/java/util/WeakIdentityHashMap",
589                 "gnu/java/util/WeakIdentityHashMap$WeakEntrySet",
590                 "java/lang/ref/ReferenceQueue",
591                 "java/util/LinkedList",
592                 "java/util/AbstractSequentialList",
593                 "gnu/java/util/WeakIdentityHashMap$WeakBucket$WeakEntry",
594                 "java/util/LinkedList$Entry",
595                 "java/lang/Class",
596                 "java/lang/reflect/VMConstructor",
597                 "java/lang/reflect/Constructor",
598                 "java/lang/reflect/Modifier",
599                 "gnu/java/net/protocol/file/Handler",
600                 "java/net/URLStreamHandler",
601                 "java/util/ArrayList",
602                 "java/security/SecureClassLoader",
603                 "java/lang/Exception",
604                 "java/lang/Throwable",
605                 "java/lang/VMThrowable",
606                 "gnu/java/net/loader/FileURLLoader",
607                 "gnu/java/net/loader/URLLoader",
608                 "java/security/Policy",
609                 "gnu/java/security/provider/DefaultPolicy",
610                 "gnu/java/net/loader/Resource",
611                 "gnu/java/net/loader/FileResource", 
612                 "java/io/FileInputStream", 
613                 "gnu/java/nio/FileChannelImpl",
614                 "java/nio/ByteBuffer",
615                 "java/nio/Buffer",
616                 "java/nio/ByteOrder",
617                 "java/security/Permissions$PermissionsHash",
618                 "java/nio/charset/Charset",
619                 "gnu/java/nio/charset/Provider",
620                 "gnu/java/nio/charset/Provider$1",
621                 "gnu/java/nio/charset/US_ASCII",
622                 "java/util/Collections$UnmodifiableSet/",
623                 "java/util/Collections$UnmodifiableCollection",
624                 "java/util/Collections$UnmodifiableIterator",
625                 "gnu/java/nio/charset/ISO_8859_1",
626                 "gnu/java/nio/charset/UTF_8",
627                 "gnu/java/nio/charset/UTF_16BE",
628                 "gnu/java/nio/charset/UTF_16LE",
629                 "gnu/java/nio/charset/UTF_16",
630                 "gnu/java/nio/charset/UnicodeLittle",
631                 "gnu/java/nio/charset/Windows1250",
632                 "gnu/java/nio/charset/Windows1250",
633                 "gnu/java/nio/charset/ByteCharset",
634                 "gnu/java/nio/charset/Windows1251",
635                 "gnu/java/nio/charset/Windows1252",
636                 "gnu/java/nio/charset/Windows1253",
637                 "gnu/java/nio/charset/Windows1254",
638                 "gnu/java/nio/charset/Windows1257",
639                 "gnu/java/nio/charset/ISO_8859_2",
640                 "gnu/java/nio/charset/ISO_8859_4",
641                 "gnu/java/nio/charset/ISO_8859_5",
642                 "gnu/java/nio/charset/ISO_8859_7",
643                 "gnu/java/nio/charset/ISO_8859_9",
644                 "gnu/java/nio/charset/ISO_8859_13",
645                 "gnu/java/nio/charset/ISO_8859_15",
646                 "gnu/java/nio/charset/KOI_8",
647                 "gnu/java/nio/charset/ISO_8859_1$Encoder",
648                 "java/nio/charset/CharsetEncoder",
649                 "gnu/java/nio/charset/ByteEncodeLoopHelper",
650                 "java/nio/charset/CodingErrorAction",
651                 "java/nio/CharBuffer",
652                 "java/nio/CharBufferImpl",
653                 "gnu/java/nio/charset/ByteEncodeLoopHelper",
654                 "java/nio/charset/CoderResult",
655                 "java/nio/charset/CoderResult$1",
656                 "java/nio/charset/CoderResult$2",
657                 "java/nio/charset/CoderResult$Cache",
658                 "java/awt/Toolkit",
659                 "gnu/java/awt/peer/gtk/GtkToolkit",
660                 "gnu/java/awt/peer/gtk/GtkGenericPeer",
661                 "java/util/WeakHashMap",
662                 "java/util/WeakHashMap$1", 
663                 "java/util/WeakHashMap$WeakEntrySet",
664                 "gnu/java/awt/peer/gtk/GtkWindowPeer",
665                 "gnu/java/awt/peer/gtk/GtkCheckboxPeer",
666                 "gnu/java/awt/peer/gtk/GtkFileDialogPeer",
667                 "gnu/java/awt/peer/gtk/GtkMainThread",
668                 "java/security/AccessController",
669                 "java/security/Permission",
670                 "java/lang/ClassLoader$StaticData",
671                 "java/lang/VMString",
672                 "gnu/java/lang/CPStringBuilder",
673                 "gnu/java/lang/VMCPStringBuilder",
674                 "java/io/FileOutputStream",
675                 "gnu/java/nio/VMChannel",
676                 "gnu/java/nio/VMChannel$State",
677                 "gnu/java/nio/VMChannel$Kind",
678                 "java/nio/channels/FileChannel",
679                 "gnu/classpath/VMSystemProperties",
680                 "java/lang/StringBuffer",
681                 "java/lang/VMRuntime",
682                 "java/lang/VMObject",
683                 "java/lang/VMThread",
684                 "java/lang/VMClass",
685                 "java/lang/InheritableThreadLocal",
686                 "java/lang/ClassNotFoundException",
687                 "java/net/URLClassLoader",
688                 "java/lang/ClassLoader$1",
689                 "java/nio/ByteBufferImpl",
690                 "java/io/FilePermission",
691                 "gnu/java/nio/charset/ISO_8859_1$Encoder$1",
692                 "java/nio/charset/spi/CharsetProvider",
693                 "gnu/java/net/loader/URLStreamHandlerCache",
694                 "java/util/HashMap$HashIterator",
695                 "java/util/HashMap$HashEntry",
696                 "java/util/AbstractMap",
697                 "java/util/AbstractMap$1",
698                 "java/lang/RuntimeException",
699                 "java/util/Collections$UnmodifiableSet",
700                 "java/lang/ref/Reference",
701                 "java/lang/ref/WeakReference",
702                 "gnu/java/util/WeakIdentityHashMap$WeakBucket",
703                 "gnu/java/util/WeakIdentityHashMap$WeakEntrySet$1",
704                 "java/lang/String$CaseInsensitiveComparator",
705                 "java/lang/Throwable$StaticData",
706                 "java/lang/StackTraceElement",
707                 "java/lang/VMMath",
708                 "java/lang/Double",
709                 "java/lang/VMDouble",
710                 "java/lang/Long",
711                 "java/lang/Float",
712                 "java/lang/VMFloat",
713                 "java/security/Permissions", /* 200 */
714                 "java/security/AllPermission", 
715                 "java/security/AllPermission$AllPermissionCollection",
716                 "java/util/AbstractMap$1$1", /* 203 */
717                 "java/lang/Integer",
718                 
719                 NULL };
720
721         if (getenv("FILTER_VERBOSE") && !printed)
722         {
723                 i = 0;
724                 while (classes[i])
725                 {
726                         log_println("[%d] - %s", i, classes[i]);
727                         i++;
728                 }
729
730                 printed = true;
731         }
732
733         buf = getenv("INDEX");
734         if (buf)
735                 sscanf(buf, "%d", &max_index);
736
737         i = 0;
738         while (classes[i] && i <= max_index)
739         {
740
741                 if (!strcmp(classes[i], classname->text))
742                         return true;
743
744                 i++;
745         }
746
747         if ((buf = getenv("FILTER_VERBOSE")))
748         {
749                 log_println("filtered: %s", classname->text);
750         }
751
752         return false;
753 }
754
755 void filter_match()
756 {
757         /* Wohoo! */
758 }
759
760 /**
761  * Causes filter_match() on which one can set a breakpoint in the debugger
762  * in the following conditions:
763  *
764  * If the environment variable NO_FILTER is set, then filter_match() is not
765  * called at all. This disables filter capabilities.
766  *
767  * If environment variable TEST_CLASS is set and the method belong to this
768  * class and there is no variable TEST_METHOD then filter_match() is called.
769  *
770  * If TEST_CLASS and TEST_METHOD match the methodinfo and TEST_DESCRIPTOR is
771  * not set.
772  *
773  * If TEST_CLASS, TEST_METHOD and TEST_DESCRIPTOR match the methodinfo's values.
774  */
775 void filter_single(methodinfo *m)
776 {
777         char *buf = NULL;
778
779         buf = getenv("NO_FILTER");
780         if (buf)
781                 return;
782
783         buf = getenv("TEST_CLASS");
784         if (!buf || strcmp(m->clazz->name->text, buf))
785                 return;
786
787         buf = getenv("TEST_METHOD");
788         if (!buf)
789         {
790                 filter_match();
791                 return;
792         }
793         else if (strcmp(m->name->text, buf))
794                 return;
795
796         buf = getenv("TEST_DESCRIPTOR");
797         if (!buf)
798         {
799                 filter_match();
800                 return;
801         }
802         else if (strcmp(m->descriptor->text, buf))
803                 return;
804
805         filter_match();
806 }
807
808 mutex_t jitcache_lock;
809
810 /* jitcache_store **************************************************************
811
812    Saves the generated machine code to disk.
813
814 *******************************************************************************/
815 void jitcache_store (methodinfo *m)
816 {
817         static int init_lock = true;
818         u1 *temp;
819         int fd;
820
821         if (init_lock)
822         {
823                 mutex_init(&jitcache_lock);
824                 init_lock = false;
825         }
826
827 /*
828         filter_single(m);
829
830         if (!filter(m->clazz->name))
831                 return;
832 */
833
834         /* Never try to store native method stubs because those include a reference
835          * a dynamically resolved function.
836      *
837      * TODO: Handle those, too.
838          */
839         if (m->flags & ACC_NATIVE)
840                 return;
841
842         fd = get_cache_file_writable(m);
843         if (!fd)
844         {
845                 if (opt_DebugJitCache)
846               log_message_method("[jitcache] store: got no file descriptor for ", m);
847
848       return;
849         }
850
851         /* Write (and some read) file operations beyond this point.
852          * Acquire lock first because another thread may try to load a different
853      * method from this class.
854      */
855 /*      mutex_lock(&m->clazz->cache_file_lock);*/
856         mutex_lock(&jitcache_lock);
857
858         if (opt_DebugJitCache)
859       log_message_method("[jitcache] store: ", m);
860
861         update_method_table(m, fd);
862
863         /* flags, optlevel, basicblockcount, synchronizedoffset, stackframesize, entrypoint, mcodelength, mcode
864     */
865         system_write(fd, (const void *) &m->code->flags, sizeof(m->code->flags));
866
867         system_write(fd, (const void *) &m->code->optlevel, sizeof(m->code->optlevel));
868         system_write(fd, (const void *) &m->code->basicblockcount, sizeof(m->code->basicblockcount));
869
870         system_write(fd, (const void *)  &m->code->synchronizedoffset, sizeof(m->code->synchronizedoffset));
871
872         system_write(fd, (const void *)  &m->code->stackframesize, sizeof(m->code->stackframesize));
873
874         temp = to_offset(m->code->mcode, m->code->entrypoint);
875         system_write(fd, (const void *) &temp, sizeof(temp));
876
877         system_write(fd, (const void *) &m->code->mcodelength, sizeof(m->code->mcodelength));
878
879         system_write(fd, (const void *) m->code->mcode, m->code->mcodelength);
880
881         store_to_file_exceptiontable(fd, m->code);
882
883         store_to_file_linenumbertable(fd, m->code);
884
885         store_to_file_patchers(fd, m->code);
886
887         store_to_file_cachedrefs(fd, m->code);
888
889 /*      mutex_unlock(&m->clazz->cache_file_lock);*/
890         mutex_unlock(&jitcache_lock);
891
892 }
893
894 /* jitcache_load ***************************************************************
895
896    Try to load previously generated machine code from disk.
897
898    Returns non-zero if successfull.
899
900 *******************************************************************************/
901
902 u1 jitcache_load (methodinfo *m)
903 {
904         codeinfo *code;
905         u1 *endpc;
906         int fd;
907
908 /*
909         if (!filter(m->clazz->name))
910                 return false;
911 */
912
913         /* Never try to store native method stubs because those include a reference
914          * a dynamically resolved function.
915          */
916         if (m->flags & ACC_NATIVE)
917                 return false;
918
919         fd = get_cache_file_readable(m);
920         if (fd <= 0)
921         {
922                 if (opt_DebugJitCache)
923               log_message_method("[jitcache] load: got no file descriptor for ", m);
924
925       return false;
926         }
927
928         if(!seek_method_table(m, fd))
929         {
930                 system_close(fd);
931
932                 return false;
933         }
934
935         if (opt_DebugJitCache)
936                 log_message_method("[jitcache] load: ", m);
937
938         code = code_codeinfo_new(m);
939         m->code = code;
940
941         /* flags, optlevel, basicblockcount, synchronizedoffset, stackframesize, entrypoint, mcodelength, mcode
942     */
943         system_read(fd, (void *) &code->flags, sizeof(code->flags));
944
945         system_read(fd, (void *) &code->optlevel, sizeof(code->optlevel));
946         system_read(fd, (void *) &code->basicblockcount, sizeof(code->basicblockcount));
947
948         system_read(fd, (void *) &code->synchronizedoffset, sizeof(code->synchronizedoffset));
949
950         system_read(fd, (void *) &code->stackframesize, sizeof(code->stackframesize));
951
952         system_read(fd, (void *) &code->entrypoint, sizeof(code->entrypoint));
953
954         system_read(fd, (void *) &code->mcodelength, sizeof(code->mcodelength));
955
956         code->mcode = CNEW(u1, code->mcodelength);
957         system_read(fd, (void *) code->mcode, code->mcodelength);
958         code->entrypoint = to_abs(code->mcode, code->entrypoint);
959
960         load_from_file_exceptiontable(code, fd);
961
962         load_from_file_linenumbertable(code, fd);
963
964         load_from_file_patchers(code, fd);
965
966         load_from_file_cachedrefs(code, fd);
967
968         system_close(fd);
969
970         endpc = (u1 *) ((ptrint) code->mcode) + code->mcodelength;
971
972         /* Insert method into methodtree to find the entrypoint. */
973
974         methodtree_insert(code->entrypoint, endpc);
975
976         /* flush the instruction and data caches */
977
978         md_cacheflush(code->mcode, code->mcodelength);
979
980         if (opt_DebugJitCache)
981         {
982                 log_println("[jitcache] load - registered method: %x -> %x", code->entrypoint, endpc);
983         }
984
985         return true;
986 }
987
988 void jitcache_quit()
989 {
990         int i;
991
992         for (i = 0; i < mru_last_free; i++)
993         {
994                 system_close(jc_mru_list[i]->cache_file_fd);
995                 jc_mru_list[i]->cache_file_fd = 0;
996                 jc_mru_list[i] = 0;
997         }
998
999         mru_last_free = 0;
1000
1001         /* Closes all open file descriptors. */
1002 }
1003
1004 void jitcache_freeclass(classinfo *c)
1005 {
1006         if (c->cache_file_fd)
1007                 jitcache_mru_remove(c);
1008 }
1009
1010 /* Helper functions */
1011 void update_method_table(methodinfo *m, int fd)
1012 {
1013         int state = 0, i, temp, offset = 0;
1014
1015         system_lseek(fd, 0, SEEK_SET);
1016
1017         system_read(fd, (void *) &state, sizeof(state));
1018
1019         /* table does not exist yet and needs to be created first */
1020         if (state != 1)
1021         {
1022                 system_lseek(fd, 0, SEEK_SET);
1023                 state = 1;
1024                 system_write(fd, &state, sizeof(state));
1025
1026                 temp = -1;
1027                 for (i = 0; i < m->clazz->methodscount; i++)
1028                         system_write(fd, &temp, sizeof(temp));
1029         }
1030
1031         /* get last offset in file */
1032         offset = system_lseek(fd, 0, SEEK_END);
1033
1034         /* find out the index in the methods array */
1035         temp = -1;
1036         for (i = 0; i < m->clazz->methodscount; i++)
1037                 if (&m->clazz->methods[i] == m)
1038                 {
1039                         temp = i;
1040                         break;
1041                 }
1042         assert(temp != -1);
1043
1044         /* seek to the method's entry in the table */
1045         system_lseek(fd, temp * sizeof(int) + sizeof(int), SEEK_SET);
1046
1047         /* enter the location */
1048         system_write(fd, &offset, sizeof(offset));
1049
1050         system_lseek(fd, offset, SEEK_SET);
1051 }
1052
1053 int seek_method_table(methodinfo *m, int fd)
1054 {
1055         int state = 0, i, temp, offset;
1056
1057         system_lseek(fd, 0, SEEK_SET);
1058
1059         system_read(fd, (void *) &state, sizeof(state));
1060
1061         /* if table does not exist, we cannot load any machine code from this file */
1062         if (state != 1)
1063                 return 0;
1064
1065         /* find out the index in the methods array */
1066         temp = -1;
1067         for (i = 0; i < m->clazz->methodscount; i++)
1068                 if (&m->clazz->methods[i] == m)
1069                 {
1070                         temp = i;
1071                         break;
1072                 }
1073         assert(temp != -1);
1074
1075         /* seek to the method's entry in the table */
1076         system_lseek(fd, temp * sizeof(int) + sizeof(int), SEEK_SET);
1077
1078         /* get the location */
1079         system_read(fd, &offset, sizeof(offset));
1080
1081         if (offset > 0)
1082         {
1083                 system_lseek(fd, offset, SEEK_SET);
1084                 return offset;
1085         }
1086
1087         return 0;
1088 }
1089
1090 int get_cache_file_readable(methodinfo *m)
1091 {
1092         char *dest_file;
1093         int fd;
1094
1095         if (m->clazz->cache_file_fd)
1096                 return dup(m->clazz->cache_file_fd);
1097
1098
1099         /* load from filesystem */
1100         dest_file = get_dest_file(m);
1101
1102         if (system_access(dest_file, F_OK) != 0)
1103         {
1104                 if (opt_DebugJitCache)
1105                         log_message_method("[jitcache] no cache file found for ", m);
1106
1107                 system_free(dest_file);
1108
1109                 return 0;
1110         }
1111
1112 /*
1113         filter_single(m);
1114 */
1115
1116         fd = open_to_read(dest_file);
1117
1118         system_free(dest_file);
1119
1120 /*
1121         if (fd > 0)
1122                 jitcache_mru_add(m->clazz, fd);
1123 */
1124         return fd;
1125 }
1126
1127 int get_cache_file_writable(methodinfo *m)
1128 {
1129         char *dest_file, *dest_dir;
1130         int fd;
1131
1132         if (m->clazz->cache_file_fd)
1133                 return m->clazz->cache_file_fd;
1134
1135         /* try to get the file first */
1136         dest_file = get_dest_file(m);
1137         fd = open_to_write(dest_file);
1138
1139         /* file does not exist. We need to create it and possibly
1140          * the directory hierarchy as well.
1141          */
1142         if (fd <= 0) {
1143                 dest_dir = get_dest_dir(m);
1144
1145                 if (system_access(dest_dir, F_OK) != 0)
1146                 {
1147                         if (mkdir_hier(dest_dir, S_IRWXU | S_IRWXG) != 0)
1148                         {
1149                                 if (opt_DebugJitCache)
1150                                         log_println("[jitcache] unable to create cache directory: %s", dest_dir);
1151
1152                                 system_free(dest_dir);
1153                                 system_free(dest_file);
1154
1155                                 return 0;
1156                         }
1157                 }
1158
1159                 system_free(dest_dir);
1160
1161                 /* try to open the file again. */
1162                 fd = open_to_write(dest_file);
1163                 system_free(dest_file);
1164
1165                 if (fd <= 0)
1166                         return 0;
1167         }
1168
1169         system_free(dest_file);
1170
1171         jitcache_mru_add(m->clazz, fd);
1172
1173         return fd;
1174 }
1175
1176 /* mkdir_hier ******************************************************************
1177
1178    Creates a directory hierarchy on the filesystem.
1179
1180 *******************************************************************************/
1181 int mkdir_hier(char *path, mode_t mode)
1182 {
1183         int index;
1184         int length = system_strlen(path);
1185
1186         for (index = 0; index < length; index++)
1187         {
1188                 if (path[index] == '/')
1189                 {
1190                         path[index] = 0;
1191                         mkdir(path, mode);
1192
1193                         path[index] = '/';
1194                 }
1195         }
1196
1197         return mkdir(path, mode);
1198 }
1199
1200 /* get_dest_file ****************************************************************
1201
1202    Returns a string denoting the file in which the method's machine code
1203    (along with the other data) is stored.
1204
1205 *******************************************************************************/
1206
1207 char *get_dest_file(methodinfo *m)
1208 {
1209         int len_cacheroot = system_strlen(CACHEROOT);
1210         int len_classname = utf_bytes(m->clazz->name);
1211
1212         char *dest_file = system_calloc(sizeof(u1),
1213                                                                    len_cacheroot
1214                                        + len_classname
1215                                        + 2);
1216
1217         strcat(dest_file, CACHEROOT);
1218         utf_cat(dest_file, m->clazz->name);
1219
1220         return dest_file;
1221 }
1222
1223 /* get_dest_dir ****************************************************************
1224
1225    Returns a string denoting the directory in which the method's machine code
1226    (along with the other data) is stored.
1227
1228 *******************************************************************************/
1229
1230 char *get_dest_dir(methodinfo *m)
1231 {
1232         int len_cacheroot = system_strlen(CACHEROOT);
1233         int len_packagename = utf_bytes(m->clazz->packagename);
1234
1235         char *dest_dir = system_calloc(sizeof(u1),
1236                                                                    len_cacheroot
1237                                        + len_packagename + 2);
1238
1239         strcat(dest_dir, CACHEROOT);
1240         utf_cat(dest_dir, m->clazz->packagename);
1241
1242         /* Make trailing slash from package name to 0 */
1243         dest_dir[len_cacheroot + len_packagename + 2 - 1] = 0;
1244
1245         return dest_dir;
1246 }
1247
1248 /* to_abs **********************************************************************
1249
1250    Generates an absolute pointer from an offset. You need this after loading
1251    a value from the disk which is absolute at runtime.
1252
1253 *******************************************************************************/
1254
1255 u1 *to_abs(u1 *base, u1 *offset)
1256 {
1257         return (u1 *) ((ptrint) base + (ptrint) offset);
1258 }
1259
1260 /* to_offset *******************************************************************
1261
1262    Generates an offset from an absolute pointer. This has to be done to each
1263    absolute pointer before storing it to disk.
1264
1265 *******************************************************************************/
1266
1267 u1 *to_offset(u1 *base, u1 *abs)
1268 {
1269         return (u1 *) ((ptrint) abs - (ptrint) base);
1270 }
1271
1272 /* open_to_read ****************************************************************
1273
1274    Open a file for reading.
1275
1276 *******************************************************************************/
1277
1278 int open_to_read(char *dest_file)
1279 {
1280         int fd;
1281 /*
1282         fd = system_open(dest_file, O_RDONLY, 0);
1283 */
1284         fd = system_open(dest_file,
1285                                          O_RDWR,
1286                                          S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1287
1288         return fd;
1289 }
1290
1291 /* open_to_write ***************************************************************
1292
1293    Open a file for writing.
1294
1295 *******************************************************************************/
1296
1297 int open_to_write(char *dest_file)
1298 {
1299         int fd;
1300
1301 /*      fd = system_open(filename,
1302                                          O_CREAT | O_WRONLY,
1303                                          S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1304 */
1305         fd = system_open(dest_file,
1306                                          O_CREAT | O_RDWR,
1307                                          S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1308
1309         return fd;
1310 }
1311
1312 /* store_utf *******************************************************************
1313
1314    Writes a utf object to disk (via filedescriptor).
1315
1316 *******************************************************************************/
1317 void store_utf(int fd, utf *s)
1318 {
1319         int len;
1320
1321         if (!s)
1322         {
1323                 len = -1;
1324                 system_write(fd, (const void *) &len, sizeof(len));
1325         }
1326         else
1327         {
1328                 len = utf_bytes(s);
1329                 system_write(fd, (const void *) &len, sizeof(len));
1330                 system_write(fd, s->text, len);
1331         }
1332 }
1333
1334 /* load_utf ********************************************************************
1335
1336    Loads a UTF8 constant from the given filedescriptor and initializes
1337    the given pointer with it.
1338    In case the stored constant's length is -1 the returned string is NULL.
1339
1340 *******************************************************************************/
1341 void load_utf(utf **s, int fd)
1342 {
1343         int len = 0;
1344         char *tmp;
1345
1346         system_read(fd, (void *) &len, sizeof(len));
1347
1348         if (len == -1)
1349                 *s = NULL;
1350         else
1351         {
1352                 tmp = system_calloc(sizeof(char), len);
1353
1354                 system_read(fd, tmp, len);
1355
1356                 *s = utf_new(tmp, len);
1357
1358 /*              system_free(tmp);*/
1359         }
1360 }
1361
1362
1363 /* store_to_file_patchers ******************************************************
1364
1365    Writes the patchers structure of a codeinfo to disk.
1366
1367 *******************************************************************************/
1368 void store_to_file_patchers(int fd, codeinfo *code)
1369 {
1370         int temp = 0;
1371         u1 *temp_ptr;
1372         patchref_t *pr;
1373         int j;
1374
1375         list_t *patchers = code->patchers;
1376
1377         /* serialize patchers list */
1378         system_write(fd, (const void *) &patchers->size, sizeof(patchers->size));
1379         if (opt_DebugJitCache)
1380                 log_println("store_to_file_patchers - patchers size %d", patchers->size);
1381
1382         for (pr = (patchref_t *) list_first(patchers); pr != NULL; pr = (patchref_t *) list_next(patchers, pr))
1383         {
1384                 temp_ptr = to_offset(code->mcode, (u1 *) pr->mpc);
1385                 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1386
1387                 temp_ptr = to_offset(code->mcode, (u1 *) pr->datap);
1388                 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1389
1390                 system_write(fd, (const void *) &pr->disp, sizeof(pr->disp));
1391
1392                 temp = -1;
1393                 j = 0;
1394                 while (patcher_functions[j].patcher)
1395                 {
1396                         if (patcher_functions[j].patcher == pr->patcher)
1397                         {
1398                                 temp = j;
1399                                 system_write(fd, (const void *) &j, sizeof(j));
1400
1401                                 (*patcher_functions[j].serializer)(fd, pr, code->m);
1402
1403                                 if (patcher_functions[j].serializer == s_dummy)
1404                                         log_println("store_to_file_patchers: unhandled patcher function for %d", j);
1405                                 break;
1406                         }
1407                         j++;
1408                 }
1409                 
1410                 if (temp == -1)
1411                 {
1412                         log_println("warning! unknown patcher function stored!");
1413                         system_write(fd, (const void *) &temp, sizeof(temp));
1414                 }
1415
1416                 system_write(fd, (const void *) &pr->attached_ref, sizeof(pr->attached_ref));
1417
1418                 if (pr->attached_ref)
1419                 {
1420                         store_cachedref(fd, pr->attached_ref);
1421
1422                         /* Release the cached reference now because it should not be used
1423                          * in the current Cacao process.
1424                          */
1425                         FREE(pr->attached_ref, cachedref_t);
1426                         pr->attached_ref = NULL;
1427                 }
1428
1429                 system_write(fd, (const void *) &pr->mcode, sizeof(pr->mcode));
1430         }
1431 }
1432
1433
1434 /* store_to_file_cachedrefs *****************************************************
1435
1436    Writes the cachedrefs structure of a codeinfo to disk.
1437
1438 *******************************************************************************/
1439 void store_to_file_cachedrefs(int fd, codeinfo *code)
1440 {
1441         cachedref_t *cr;
1442
1443         list_t *cachedrefs = code->cachedrefs;
1444         if (opt_DebugJitCache)
1445                 log_println("store_to_file_cachedrefs - cachedrefs size %d", cachedrefs->size);
1446
1447         /* serialize cachedrefs list */
1448         system_write(fd, (const void *) &cachedrefs->size, sizeof(cachedrefs->size));
1449
1450         for (cr = (cachedref_t *) list_first(cachedrefs);
1451                  cr != NULL;
1452                  cr = (cachedref_t *) list_next(cachedrefs, cr))
1453                 store_cachedref(fd, cr);
1454 }
1455
1456 /* store_cachedref *************************************************************
1457
1458    Stores a single cachedref_t instance to disk.
1459
1460 *******************************************************************************/
1461
1462 void store_cachedref(int fd, cachedref_t *cr)
1463 {
1464         system_write(fd, (const void *) &cr->type, sizeof(cr->type));
1465         system_write(fd, (const void *) &cr->md_patch, sizeof(cr->md_patch));
1466         system_write(fd, (const void *) &cr->disp, sizeof(cr->disp));
1467
1468         switch (cr->type) {
1469                 case CRT_CODEINFO:
1470                 case CRT_ENTRYPOINT:
1471                 case CRT_CODEGEN_FINISH_NATIVE_CALL:
1472                 case CRT_ASM_HANDLE_EXCEPTION:
1473                 case CRT_ASM_HANDLE_NAT_EXCEPTION:
1474                         /* Nothing to store. */
1475                         break;
1476                 case CRT_NUM:
1477                         system_write(fd, (const void *) &cr->ref, sizeof(s4));
1478                         break;
1479                 case CRT_OBJECT_HEADER:
1480                 case CRT_CLASSINFO:
1481                 case CRT_CLASSINFO_INDEX:
1482                 case CRT_CLASSINFO_INTERFACETABLE:
1483                 case CRT_CLASSINFO_VFTBL:
1484                         /* Store classinfo */
1485                         store_classinfo(fd, (classinfo *) cr->ref);
1486                         break;
1487                 case CRT_BUILTIN:
1488                 case CRT_BUILTIN_FP:
1489                         store_builtin(fd, (builtintable_entry *) cr->ref);
1490                         break;
1491                 case CRT_STRING:
1492                         store_string(fd, (java_object_t *) cr->ref);
1493                         break;
1494                 case CRT_METHODINFO_STUBROUTINE:
1495                 case CRT_METHODINFO_TABLE:
1496                 case CRT_METHODINFO_INTERFACETABLE:
1497                 case CRT_METHODINFO_METHODOFFSET:
1498                         store_methodinfo(fd, (methodinfo *) cr->ref);
1499                         break;
1500                 case CRT_FIELDINFO_VALUE:
1501                 case CRT_FIELDINFO_OFFSET:
1502                 case CRT_FIELDINFO_OFFSET_HIGH:
1503                         store_fieldinfo(fd, (fieldinfo *) cr->ref);
1504                         break;
1505                 case CRT_JUMPREFERENCE:
1506                         system_write(fd, (const void *) &cr->ref, sizeof(cr->ref));
1507                         
1508                         break;
1509                 default:
1510                         log_println("store_cachedref: Invalid cachedref type: %d", cr->type);
1511                         assert(0);
1512         }
1513 }
1514
1515
1516 /* store_to_file_exceptiontable ************************************************
1517
1518    Writes the exceptiontable structure of a codeinfo to disk.
1519
1520 *******************************************************************************/
1521 void store_to_file_exceptiontable(int fd, codeinfo *code)
1522 {
1523         int count = 0;
1524         u1 *temp_ptr;
1525         int i;
1526         utf *name;
1527
1528         /* serialize exceptiontable */
1529
1530         /* temp will contain the amount of exceptiontable entries or zero
1531          * if none exists.
1532      */
1533         if (code->exceptiontable)
1534                 count = code->exceptiontable->length;
1535
1536         system_write(fd, (const void *) &count, sizeof(count));
1537         if (opt_DebugJitCache)
1538                 log_println("store_exceptiontable - exceptiontable size %d", count);
1539
1540         for (i = 0; i < count; i++)
1541         {
1542                 exceptiontable_entry_t *entry = &code->exceptiontable->entries[i];
1543
1544                 temp_ptr = to_offset(code->mcode, entry->endpc);
1545                 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1546
1547                 temp_ptr = to_offset(code->mcode, entry->startpc);
1548                 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1549
1550                 temp_ptr = to_offset(code->mcode, entry->handlerpc);
1551                 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1552
1553                 /* store class name of entry->catchtype */
1554                 if (entry->catchtype.any)
1555                 {
1556                         name = CLASSREF_OR_CLASSINFO_NAME(entry->catchtype);
1557                         store_utf(fd, name);
1558                 }
1559                 else
1560                         store_utf(fd, NULL);
1561
1562         }
1563
1564 }
1565
1566
1567 /* store_to_file_linenumbertable ***********************************************
1568
1569    Writes the linenumbertable structure of a codeinfo to disk.
1570
1571 *******************************************************************************/
1572 void store_to_file_linenumbertable(int fd, codeinfo *code)
1573 {
1574         void *temp_ptr;
1575         linenumbertable_entry_t *lte;
1576         int count = 0;
1577         int i;
1578         linenumbertable_t *linenumbertable;
1579
1580         linenumbertable = code->linenumbertable;
1581
1582         if (code->linenumbertable)
1583                 count = code->linenumbertable->length;
1584
1585         /* serialize patchers list */
1586         system_write(fd, (const void *) &count, sizeof(count));
1587
1588         if (opt_DebugJitCache)
1589                 log_println("store_to_file_linenumbertable - linenumbertable size %d", count);
1590
1591         if (count)
1592         {
1593                 lte = linenumbertable->entries;
1594                 for (i = 0; i < count; i++)
1595                 {
1596                         system_write(fd, (const void *) &lte->linenumber, sizeof(lte->linenumber));
1597         
1598                         temp_ptr = to_offset(code->entrypoint, lte->pc);
1599                         system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1600
1601                         lte++;
1602                 }
1603         }
1604
1605 }
1606
1607
1608 /* load_from_file_patchers *****************************************************
1609
1610    Loads the patchers structure of codeinfo from a file.
1611
1612 *******************************************************************************/
1613 void load_from_file_patchers(codeinfo *code, int fd)
1614 {
1615         int temp = 0;
1616         u1 *temp_ptr;
1617         int count = 0;
1618         int i;
1619
1620         /* serialize patchers list */
1621         system_read(fd, (void *) &count, sizeof(count));
1622
1623         if (opt_DebugJitCache   /* Insert method into methodtree to find the entrypoint. */
1624 )
1625                 log_println("load_from_file_patchers - patcher size %d", count);
1626
1627         patcher_list_create(code);
1628
1629         for (i = 0;i < count; i++)
1630         {
1631                 patchref_t *pr = NEW(patchref_t);
1632
1633                 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1634                 pr->mpc = (ptrint) to_abs(code->mcode, temp_ptr);
1635
1636                 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1637                 pr->datap = (ptrint) to_abs(code->mcode, temp_ptr);
1638
1639                 system_read(fd, (void *) &pr->disp, sizeof(pr->disp));
1640
1641                 system_read(fd, (void *) &temp, sizeof(temp));
1642                 if (temp == -1)
1643                 {
1644                         vm_abort("Invalid patcher function index loaded!");
1645                         temp = 0;
1646                 }
1647                 pr->patcher = patcher_functions[temp].patcher;
1648
1649                 (*patcher_functions[temp].deserializer)(pr, fd, code->m);
1650
1651                 /* Load the pointer value to decide whether a cached reference must
1652          * be loaded or not. */
1653                 system_read(fd, (void *) &pr->attached_ref, sizeof(pr->attached_ref));
1654
1655                 if (pr->attached_ref)
1656                 {
1657                         pr->attached_ref = NULL;
1658                         load_cachedref(&pr->attached_ref, fd, code);
1659                 }
1660
1661                 system_read(fd, (void *) &pr->mcode, sizeof(pr->mcode));
1662
1663                 pr->done = false;
1664
1665                 list_add_first(code->patchers, pr);
1666         }
1667 }
1668
1669 /* load_from_file_cachedrefs ***************************************************
1670
1671    Loads the cachedrefs structure of codeinfo from a file.
1672
1673    Note: code->entrypoint *must* be valid at this point!
1674
1675    Binary format:
1676    int - number of cachedref_t instances in the file
1677    cachedref_t - see load_cachedref
1678
1679 *******************************************************************************/
1680 void load_from_file_cachedrefs(codeinfo *code, int fd)
1681 {
1682         cachedref_t *cr;
1683         int count = 0;
1684         int i;
1685
1686         /* serialize cachedrefs list */
1687         system_read(fd, (void *) &count, sizeof(count));
1688
1689         if (opt_DebugJitCache)
1690                 log_println("load_from_file_cachedrefs - cachedrefs size %d", count);
1691
1692         jitcache_list_reset(code);
1693
1694         cr = NEW(cachedref_t);
1695
1696         for (i = 0;i < count; i++)
1697         {
1698                 load_cachedref(&cr, fd, code);
1699
1700                 /* Write the restored reference into the code. */
1701                 if (cr->md_patch)
1702                         patch_md(cr->md_patch, ((ptrint) code->entrypoint) + cr->disp, cr->ref);
1703                 else
1704                 {
1705                   *((u1 **) (code->entrypoint + cr->disp)) = cr->ref;
1706                 }
1707
1708         }
1709
1710         FREE(cr, cachedref_t);
1711 }
1712
1713
1714 /* load_cachedref **************************************************************
1715
1716         Loads a cached reference from disk and 
1717
1718         Binary format:
1719      s4 - disp value
1720      cachedreftype - type value
1721      * - cached ref specific (depends on type)
1722
1723 *******************************************************************************/
1724
1725 void load_cachedref(cachedref_t **result_cr, int fd, codeinfo *code)
1726 {
1727         cachedref_t                     *cr;
1728         classinfo                       *ci;
1729         methodinfo                      *mi;
1730         fieldinfo                       *fi;
1731         builtintable_entry  *bte;
1732         java_object_t           *h;
1733
1734         if (*result_cr)
1735                 cr = *result_cr;
1736         else
1737                 *result_cr = cr = NEW(cachedref_t);
1738
1739         system_read(fd, (void *) &cr->type, sizeof(cr->type));
1740         system_read(fd, (void *) &cr->md_patch, sizeof(cr->md_patch));
1741         system_read(fd, (void *) &cr->disp, sizeof(cr->disp));
1742
1743         switch (cr->type) {
1744                 case CRT_CODEINFO:
1745                         /* Just set the current codeinfo. */
1746                         cr->ref = (voidptr) code;
1747                         break;
1748                 case CRT_NUM:
1749                         system_read(fd, (void *) &cr->ref, sizeof(s4));
1750                         break;
1751                 case CRT_ENTRYPOINT:
1752                         /* Just set the current entrypoint. */
1753                         cr->ref = (voidptr) code->entrypoint;
1754                         break;
1755                 case CRT_CODEGEN_FINISH_NATIVE_CALL:
1756                         /* Just set the pointer to codegen_finish_native_call. */
1757                         cr->ref = (voidptr) (ptrint) codegen_finish_native_call;
1758                         break;
1759                 case CRT_ASM_HANDLE_EXCEPTION:
1760                         /* Just set the pointer to asm_handle_exception. */
1761                         cr->ref = (voidptr) (ptrint) asm_handle_exception;
1762                         break;
1763                 case CRT_ASM_HANDLE_NAT_EXCEPTION:
1764                         /* Just put the pointer to asm_handle_nat_exception. */
1765                         cr->ref = (voidptr) (ptrint) asm_handle_nat_exception;
1766                         break;
1767                 case CRT_OBJECT_HEADER:
1768                         /* Load classinfo */
1769                         load_classinfo(&ci, fd, code->m);
1770                         cr->ref = &ci->object.header;
1771                         break;
1772                 case CRT_BUILTIN:
1773                         load_builtin(&bte, fd);
1774                         /* TODO: For the time being prefer the stub if it exists, otherwise
1775                          * use the function pointer directlty.
1776                          * This should go away with a moving garbage collector.
1777              */
1778                         cr->ref = (voidptr) (bte->stub == NULL ? (ptrint) bte->fp : (ptrint) bte->stub);
1779
1780                         break;
1781                 case CRT_BUILTIN_FP:
1782                         load_builtin(&bte, fd);
1783                         cr->ref = (voidptr) (ptrint) bte->fp;
1784
1785                         break;
1786                 case CRT_STRING:
1787                         load_string(&h, fd);
1788                         cr->ref = (voidptr) h;
1789                         break;
1790                 case CRT_CLASSINFO:
1791                         /* Load classinfo */
1792                         load_classinfo(&ci, fd, code->m);
1793                         cr->ref = (voidptr) ci;
1794
1795                         break;
1796                 case CRT_CLASSINFO_INDEX:
1797                         /* Load classinfo */
1798                         load_classinfo(&ci, fd, code->m);
1799                         cr->ref = (voidptr) ci->index;
1800                         break;
1801                 case CRT_CLASSINFO_INTERFACETABLE:
1802                         /* Load classinfo */
1803                         load_classinfo(&ci, fd, code->m);
1804                         cr->ref = (voidptr) (OFFSET(vftbl_t, interfacetable[0]) -
1805                                                 ci->index * sizeof(methodptr*));
1806                         break;
1807                 case CRT_CLASSINFO_VFTBL:
1808                         /* Load classinfo */
1809                         load_classinfo(&ci, fd, code->m);
1810                         cr->ref = (voidptr) ci->vftbl;
1811                         break;
1812                 case CRT_METHODINFO_STUBROUTINE:
1813                         load_methodinfo(&mi, fd, code->m);
1814                         cr->ref = (voidptr) mi->stubroutine;
1815                         break;
1816                 case CRT_METHODINFO_TABLE:
1817                         load_methodinfo(&mi, fd, code->m);
1818                         cr->ref = (voidptr) ((OFFSET(vftbl_t, table[0]) +
1819                                                            sizeof(methodptr) * mi->vftblindex));
1820                         break;
1821                 case CRT_METHODINFO_INTERFACETABLE:
1822                         load_methodinfo(&mi, fd, code->m);
1823                         cr->ref = (voidptr) (OFFSET(vftbl_t, interfacetable[0]) -
1824                                         sizeof(methodptr) * mi->clazz->index);
1825                         break;
1826                 case CRT_METHODINFO_METHODOFFSET:
1827                         load_methodinfo(&mi, fd, code->m);
1828                         cr->ref = (voidptr) ((sizeof(methodptr) * (mi - mi->clazz->methods)));
1829                         break;
1830                 case CRT_FIELDINFO_VALUE:
1831                         load_fieldinfo(&fi, fd, code->m);
1832
1833                         cr->ref = (voidptr) fi->value;
1834                         break;
1835                 case CRT_FIELDINFO_OFFSET:
1836                         load_fieldinfo(&fi, fd, code->m);
1837
1838                         cr->ref = (voidptr) fi->offset;
1839                         break;
1840                 case CRT_FIELDINFO_OFFSET_HIGH:
1841                         /* Should be used on 32 bit archs only. */
1842                         load_fieldinfo(&fi, fd, code->m);
1843
1844                         cr->ref = (voidptr) fi->offset + 4;
1845                         break;
1846                 case CRT_JUMPREFERENCE:
1847                         system_read(fd, (void *) &cr->ref, sizeof(cr->ref));
1848
1849                         cr->ref = (voidptr) ((ptrint) cr->ref + (ptrint) code->entrypoint);
1850                         break;
1851                 default:
1852                         log_println("Invalid (or unhandled) cachedreference type: %d", cr->type);
1853                         assert(0);
1854                         break;
1855         }
1856
1857
1858         if (opt_DebugJitCache)
1859         {
1860                 if (cr->md_patch)
1861                         log_println("[%X, %d]: replace (md) %X with %X", code->entrypoint + cr->disp, cr->type, 0xFFF & (u4) (*(u1 **) (code->entrypoint + cr->disp)), cr->ref);
1862                 else
1863                 {
1864                 log_println("[%X, %d]: replace %X with %X", code->entrypoint + cr->disp, cr->type, *((u1 **) (code->entrypoint + cr->disp)), cr->ref);
1865                 if ((cr->type == CRT_BUILTIN || cr->type == CRT_BUILTIN_FP) && (voidptr) (*((u1 **) (code->entrypoint + cr->disp))) != cr->ref)
1866                         log_println("[!!!] differing builtin function pointer: %s", bte->cname);
1867                 }
1868         }
1869
1870
1871 }
1872
1873 /* load_from_file_exceptiontable ***********************************************
1874
1875    Loads the exceptiontable structure of codeinfo from a file.
1876
1877 *******************************************************************************/
1878 void load_from_file_exceptiontable(codeinfo *code, int fd)
1879 {
1880         int i;
1881         u1 *temp_ptr;
1882         utf *classname;
1883         constant_classref *classref;
1884         exceptiontable_entry_t *ete;
1885
1886         code->exceptiontable = NEW(exceptiontable_t);
1887
1888         system_read(fd, (void *) &code->exceptiontable->length, sizeof(code->exceptiontable->length));
1889
1890         if (opt_DebugJitCache)
1891                 log_println("load_exceptiontable - exceptiontable size %d", code->exceptiontable->length);
1892
1893
1894         ete = MNEW(exceptiontable_entry_t, code->exceptiontable->length);
1895         code->exceptiontable->entries = ete;
1896
1897         for (i = 0; i < code->exceptiontable->length; i++)
1898         {
1899                 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1900                 ete->endpc = to_abs(code->mcode, temp_ptr);
1901
1902                 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1903                 ete->startpc = to_abs(code->mcode, temp_ptr);
1904
1905                 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1906                 ete->handlerpc = to_abs(code->mcode, temp_ptr);
1907
1908                 /* load class name of entry->catchtype */
1909                 load_utf(&classname, fd);
1910
1911                 if (classname)
1912                 {
1913                         classref = NEW(constant_classref);
1914                         CLASSREF_INIT(*classref, code->m->clazz, classname);
1915
1916                         ete->catchtype = CLASSREF_OR_CLASSINFO(classref);
1917                 }
1918                 else
1919                         ete->catchtype.any = NULL;
1920
1921                 ete++;
1922         }
1923
1924 }
1925
1926
1927 /* load_from_file_linenumbertable **********************************************
1928
1929    Loads the linenumbertable structure of codeinfo from a file.
1930
1931 *******************************************************************************/
1932 void load_from_file_linenumbertable(codeinfo *code, int fd)
1933 {
1934         linenumbertable_entry_t *lte;
1935         void *temp_ptr;
1936         int i;
1937
1938         code->linenumbertable = NEW(linenumbertable_t);
1939
1940         system_read(fd, (void *) &code->linenumbertable->length, sizeof(code->linenumbertable->length));
1941
1942         if (opt_DebugJitCache)
1943                 log_println("load_linenumbertable - linenumbertable size %d", code->linenumbertable->length);
1944
1945         lte = MNEW(linenumbertable_entry_t, code->linenumbertable->length);
1946         code->linenumbertable->entries = lte;
1947
1948         for (i = 0;i < code->linenumbertable->length; i++)
1949         {
1950                 system_read(fd, (void *) &lte->linenumber, sizeof(lte->linenumber));
1951
1952                 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1953                 lte->pc = to_abs(code->entrypoint, temp_ptr);
1954
1955                 lte++;
1956         }
1957 }
1958
1959
1960 /* s_dummy *********************************************************************
1961
1962    Patcher serialization function which does nothing and can therefore be used
1963    as a placeholder for not yet written serializers.
1964
1965 *******************************************************************************/
1966 void s_dummy(int fd, patchref_t *pr, methodinfo *m)
1967 {
1968   /* Intentionally does nothing. */
1969 }
1970
1971 /* s_unresolved_class **********************************************************
1972
1973    Serializes a unresolved_class reference.
1974
1975    Binary format:
1976    - utf string - classname
1977
1978 *******************************************************************************/
1979 void s_unresolved_class(int fd, patchref_t *pr, methodinfo *m)
1980 {
1981         unresolved_class *uc;
1982
1983         uc = (unresolved_class *) pr->ref;
1984
1985         /* Store the class name ... */
1986         store_utf(fd, uc->classref->name);
1987
1988 /*
1989         log_println("s_unresolved_class:");
1990         log_message_utf("class:", uc->classref->name);
1991 */
1992 }
1993
1994 /* s_unresolved_field **********************************************************
1995
1996         Serializes a unresolved_field reference.
1997
1998         Binary format:
1999         s4  - unresolved_field.flags
2000         int - index into class' cpinfo that denotes the unresolved_field's
2001                   constant_FMIref
2002
2003 *******************************************************************************/
2004 void s_unresolved_field(int fd, patchref_t *pr, methodinfo *m)
2005 {
2006         int i;
2007
2008         unresolved_field *ref = (unresolved_field *) pr->ref;
2009
2010 /*
2011         log_println("s_unresolved_field:");
2012         log_message_utf("field name: ", ref->fieldref->name);
2013         log_message_utf("field desc: ", ref->fieldref->descriptor);
2014         log_message_utf("field's class: ", FIELDREF_CLASSNAME(ref->fieldref));
2015 */
2016         system_write(fd, (const void *) &ref->flags, sizeof(ref->flags));
2017
2018         for (i = 0; i < m->clazz->cpcount; i++)
2019         {
2020                 if (m->clazz->cpinfos[i] == (voidptr) ref->fieldref)
2021                 {
2022                         system_write(fd, (const void *) &i, sizeof(i));
2023
2024                         return;
2025                 }
2026         }
2027         /* We should be out at this point. */
2028
2029         vm_abort("fieldref not found");
2030 }
2031
2032 /* s_unresolved_method **********************************************************
2033
2034    Serializes a unresolved_method reference.
2035
2036    Binary format:
2037    undecided
2038
2039 *******************************************************************************/
2040 void s_unresolved_method(int fd, patchref_t *pr, methodinfo *m)
2041 {
2042         int i;
2043
2044         unresolved_method *ref = (unresolved_method *) pr->ref;
2045
2046         system_write(fd, (const void *) &ref->flags, sizeof(ref->flags));
2047
2048         for (i = 0; i < m->clazz->cpcount; i++)
2049         {
2050                 if (m->clazz->cpinfos[i] == (voidptr) ref->methodref)
2051                 {
2052                         system_write(fd, (const void *) &i, sizeof(i));
2053
2054                         return;
2055                 }
2056         }
2057         /* We should be out at this point. */
2058
2059         vm_abort("methodref not found");
2060 }
2061
2062 /* s_classinfo *****************************************************************
2063
2064    Serializes a classinfo reference.
2065
2066 *******************************************************************************/
2067 void s_classinfo(int fd, patchref_t *pr, methodinfo *m)
2068 {
2069         classinfo *ci;
2070
2071         ci = (classinfo *) pr->ref;
2072
2073         store_classinfo(fd, ci);
2074 }
2075
2076 /* s_methodinfo ****************************************************************
2077
2078         Serializes a methodinfo reference.
2079
2080 *******************************************************************************/
2081 void s_methodinfo(int fd, patchref_t *pr, methodinfo *m)
2082 {
2083         methodinfo *mi;
2084
2085         mi = (methodinfo *) pr->ref;
2086
2087         store_methodinfo(fd, mi);
2088 }
2089
2090 /* store_methodinfo ************************************************************
2091
2092         Serializes a methodinfo reference.
2093
2094         Binary format:
2095         utf - method name
2096         utf - method descriptor
2097         utf - class to which method belongs
2098
2099 *******************************************************************************/
2100 void store_methodinfo(int fd, methodinfo *mi)
2101 {
2102         store_utf(fd, mi->name);
2103         store_utf(fd, mi->descriptor);
2104         store_utf(fd, mi->clazz->name);
2105 }
2106
2107 /* s_fieldinfo ****************************************************************
2108
2109         Serializes a fieldinfo reference.
2110
2111         Binary format:
2112         utf - field name
2113         utf - field descriptor
2114         utf - class to which field belongs
2115
2116 *******************************************************************************/
2117 void s_fieldinfo(int fd, patchref_t *pr, methodinfo *m)
2118 {
2119         fieldinfo *fi;
2120
2121         fi = (fieldinfo *) pr->ref;
2122
2123         store_fieldinfo(fd, fi);
2124 }
2125
2126 void store_fieldinfo(int fd, fieldinfo *fi)
2127 {
2128         store_utf(fd, fi->name);
2129         store_utf(fd, fi->descriptor);
2130         store_utf(fd, fi->clazz->name);
2131 }
2132
2133 /* s_constant_classref *********************************************************
2134
2135    Serializes a constant_classref reference.
2136
2137    Binary format:
2138    - utf string - constant_classref's classname
2139
2140 *******************************************************************************/
2141 void s_constant_classref(int fd, patchref_t *pr, methodinfo *m)
2142 {
2143         constant_classref *cr = (constant_classref *) pr->ref;
2144
2145         store_utf(fd, cr->name);
2146 }
2147
2148
2149 /* store_builtin *******************************************************************
2150
2151    Serializes a constant_classref reference.
2152
2153    Binary format:
2154    - s4 - key from builtintable_get_key()
2155
2156 *******************************************************************************/
2157 void store_builtin(int fd, builtintable_entry *bte)
2158 {
2159         s4                                      key;
2160
2161         key = builtintable_get_key(bte);
2162
2163         system_write(fd, (const void *) &key, sizeof(key));
2164 }
2165
2166 /* store_string ****************************************************************
2167
2168    Serializes a java_object_t reference which denotes a string.
2169
2170    Binary format:
2171    - utf - utf bytes of the string instance
2172
2173 *******************************************************************************/
2174 void store_string(int fd, java_object_t *h)
2175 {
2176         utf                             *string;
2177
2178         string = javastring_toutf((java_handle_t *) h, false);
2179
2180         store_utf(fd, string);
2181 }
2182
2183
2184 /* d_dummy *********************************************************************
2185
2186    Patcher deserialization function which does nothing and can therefore be used
2187    as a placeholder for not yet written deserializers.
2188
2189 *******************************************************************************/
2190 void d_dummy(patchref_t *pr, int fd, methodinfo *m)
2191 {
2192   /* Intentionally do nothing. */
2193 }
2194
2195 /*
2196  * Loads UTF8 classname and creates an unresolved_class for it
2197  * using the class to which the patchref_t belongs as the referer.
2198  */
2199 void d_unresolved_class(patchref_t *pr, int fd, methodinfo *m)
2200 {
2201         utf *classname;
2202         constant_classref *classref;
2203         unresolved_class *uc;
2204
2205         classref = NEW(constant_classref);
2206
2207         load_utf(&classname, fd);
2208
2209         CLASSREF_INIT(*classref, m->clazz, classname);
2210
2211         uc = create_unresolved_class(m, classref, NULL);
2212
2213         pr->ref = (voidptr) uc;
2214
2215 /*      FREE(classref, constant_classref);*/
2216
2217 /*      system_free(classname); */
2218 }
2219
2220 void d_unresolved_field(patchref_t *pr, int fd, methodinfo *m)
2221 {
2222         int i;
2223
2224         unresolved_field *ref = NEW(unresolved_field);
2225
2226         system_read(fd, (void *) &ref->flags, sizeof(ref->flags));
2227
2228         system_read(fd, (void *) &i, sizeof(i));
2229         ref->fieldref = (constant_FMIref *) m->clazz->cpinfos[i];
2230
2231         ref->referermethod = m;
2232
2233         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
2234
2235         pr->ref = (voidptr) ref;
2236 }
2237
2238 void d_unresolved_method(patchref_t *pr, int fd, methodinfo *m)
2239 {
2240         int i;
2241
2242         unresolved_method *ref = NEW(unresolved_method);
2243
2244         system_read(fd, (void *) &ref->flags, sizeof(ref->flags));
2245
2246         system_read(fd, (void *) &i, sizeof(i));
2247         ref->methodref = (constant_FMIref *) m->clazz->cpinfos[i];
2248
2249         ref->referermethod = m;
2250         ref->paramconstraints = NULL;
2251         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
2252
2253         pr->ref = (voidptr) ref;
2254 }
2255
2256 void d_classinfo(patchref_t *pr, int fd, methodinfo *m)
2257 {
2258         classinfo *ci;
2259
2260         load_classinfo(&ci, fd, m);
2261
2262         pr->ref = (voidptr) ci;
2263 }
2264
2265 void d_methodinfo(patchref_t *pr, int fd, methodinfo *m)
2266 {
2267         methodinfo *lm;
2268
2269         load_methodinfo(&lm, fd, m);
2270
2271         pr->ref = (voidptr) lm;
2272 }
2273
2274 void load_methodinfo(methodinfo **lm, int fd, methodinfo *m)
2275 {
2276         utf *m_name;
2277         utf *m_desc;
2278         utf *classname;
2279         classinfo *class;
2280         constant_classref ref;
2281
2282         load_utf(&m_name, fd);
2283         load_utf(&m_desc, fd);
2284         load_utf(&classname, fd);
2285
2286         CLASSREF_INIT(ref, m->clazz, classname);
2287
2288         class = resolve_classref_eager(&ref);
2289
2290         *lm = class_findmethod(class, m_name, m_desc);
2291 }
2292
2293 void d_fieldinfo(patchref_t *pr, int fd, methodinfo *m)
2294 {
2295         fieldinfo *fi;
2296
2297         load_fieldinfo(&fi, fd, m);
2298         
2299         pr->ref = (voidptr) fi;
2300 }
2301
2302 void load_fieldinfo(fieldinfo **fi, int fd, methodinfo *m)
2303 {
2304         utf *f_name;
2305         utf *f_desc;
2306         utf *classname;
2307         classinfo *class;
2308         constant_classref ref;
2309
2310         load_utf(&f_name, fd);
2311         load_utf(&f_desc, fd);
2312         load_utf(&classname, fd);
2313
2314         CLASSREF_INIT(ref, m->clazz, classname);
2315
2316         class = resolve_classref_eager(&ref);
2317 /*
2318         if (!(class->state & CLASS_INITIALIZED))
2319                 if (!initialize_class(class))
2320 */
2321         *fi = class_findfield(class, f_name, f_desc);
2322 }
2323
2324 /*
2325  * Loads UTF8 classname and initializes a constant_classref for it
2326  * using the class to which the patchref_t belongs as the referer.
2327  */
2328 void d_constant_classref(patchref_t *pr, int fd, methodinfo *m)
2329 {
2330         utf *classname;
2331         constant_classref *cr = NEW(constant_classref);
2332
2333         load_utf(&classname, fd);
2334
2335         CLASSREF_INIT(*cr, m->clazz, classname);
2336
2337         pr->ref = (voidptr) cr;
2338
2339 /*      system_free(classname);*/
2340 }
2341
2342 void load_builtin(builtintable_entry **bte, int fd)
2343 {
2344         s4                                      key;
2345
2346         system_read(fd, (void *) &key, sizeof(key));
2347
2348         *bte = builtintable_get_by_key(key);
2349 }
2350
2351 void load_string(java_object_t **h, int fd)
2352 {
2353         utf *string;
2354
2355         load_utf(&string, fd);
2356
2357 /*      *h = javastring_new(string);*/
2358         *h = literalstring_new(string);
2359 }
2360
2361 /* store_classinfo *************************************************************
2362
2363    Serializes a classinfo reference.
2364
2365    Binary format:
2366    - utf string - classinfo's classname
2367
2368 *******************************************************************************/
2369 void store_classinfo(int fd, classinfo *ci)
2370 {
2371         /* Store the class name ... */
2372         store_utf(fd, ci->name);
2373 }
2374
2375
2376 /* load_classinfo *************************************************************
2377
2378    Deserializes a classinfo reference.
2379
2380    Binary format: see store_classinfo
2381
2382 *******************************************************************************/
2383 void load_classinfo(classinfo **ci, int fd, methodinfo *m)
2384 {
2385         utf *classname;
2386         constant_classref *classref;
2387
2388         classref = NEW(constant_classref);
2389
2390         load_utf(&classname, fd);
2391
2392         CLASSREF_INIT(*classref, m->clazz, classname);
2393
2394         *ci = resolve_classref_eager(classref);
2395 }
2396 #endif
2397
2398 /*
2399  * These are local overrides for various environment variables in Emacs.
2400  * Please do not remove this and leave it at the end of the file, where
2401  * Emacs will automagically detect them.
2402  * ---------------------------------------------------------------------
2403  * Local variables:
2404  * mode: c
2405  * indent-tabs-mode: t
2406  * c-basic-offset: 4
2407  * tab-width: 4
2408  * End:
2409  * vim:noexpandtab:sw=4:ts=4:
2410  */