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