Use proper class load and link functions.
[cacao.git] / src / vm / builtin.c
1 /* src/vm/builtin.c - functions for unsupported operations
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28             Andreas Krall
29             Mark Probst
30
31    Changes: Christian Thalinger
32
33    Contains C functions for JavaVM Instructions that cannot be
34    translated to machine language directly. Consequently, the
35    generated machine code for these instructions contains function
36    calls instead of machine instructions, using the C calling
37    convention.
38
39    $Id: builtin.c 2148 2005-03-30 16:49:40Z twisti $
40
41 */
42
43
44 #include <assert.h>
45 #include <string.h>
46 #include <math.h>
47
48 #include "config.h"
49 #include "arch.h"
50 #include "types.h"
51 #include "mm/boehm.h"
52 #include "mm/memory.h"
53 #include "native/native.h"
54 #include "native/include/java_lang_Cloneable.h"
55 #include "native/include/java_lang_VMObject.h"
56
57 #if defined(USE_THREADS)
58 # if defined(NATIVE_THREADS)
59 #  include "threads/native/threads.h"
60 # else
61 #  include "threads/green/threads.h"
62 #  include "threads/green/locks.h"
63 # endif
64 #endif
65
66 #include "toolbox/logging.h"
67 #include "vm/builtin.h"
68 #include "vm/exceptions.h"
69 #include "vm/global.h"
70 #include "vm/loader.h"
71 #include "vm/options.h"
72 #include "vm/stringlocal.h"
73 #include "vm/tables.h"
74 #include "vm/jit/asmpart.h"
75
76
77 #undef DEBUG /*define DEBUG 1*/
78
79 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
80 THREADSPECIFIC void *_thread_nativestackframeinfo = NULL;
81
82
83 #if defined(USEBUILTINTABLE)
84
85 #if 0
86 stdopdescriptor builtintable[] = {
87         { ICMD_LCMP,   TYPE_LONG, TYPE_LONG, TYPE_INT, ICMD_BUILTIN2,
88           (functionptr) builtin_lcmp , SUPPORT_LONG && SUPPORT_LONG_CMP, false },
89         { ICMD_LAND,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
90           (functionptr) builtin_land , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
91         { ICMD_LOR,    TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
92           (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
93         { ICMD_LXOR,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
94           (functionptr) builtin_lxor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
95         { ICMD_LSHL,   TYPE_LONG, TYPE_INT,  TYPE_LONG, ICMD_BUILTIN2,
96           (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
97         { ICMD_LSHR,   TYPE_LONG, TYPE_INT,  TYPE_LONG, ICMD_BUILTIN2,
98           (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
99         { ICMD_LUSHR,  TYPE_LONG, TYPE_INT,  TYPE_LONG, ICMD_BUILTIN2,
100           (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
101         { ICMD_LADD,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
102           (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
103         { ICMD_LSUB,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
104           (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
105         { ICMD_LNEG,   TYPE_LONG, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1, 
106           (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, true },
107         { ICMD_LMUL,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
108           (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MUL, false },
109         { ICMD_I2F,    TYPE_INT, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
110           (functionptr) builtin_i2f, SUPPORT_FLOAT && SUPPORT_IFCVT, true },
111         { ICMD_I2D,    TYPE_INT, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1, 
112           (functionptr) builtin_i2d, SUPPORT_DOUBLE && SUPPORT_IFCVT, true },
113         { ICMD_L2F,    TYPE_LONG, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
114           (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
115         { ICMD_L2D,    TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1, 
116           (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
117         { ICMD_F2L,    TYPE_FLOAT, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
118           (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
119         { ICMD_D2L,    TYPE_DOUBLE, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
120           (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
121         { ICMD_F2I,    TYPE_FLOAT, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
122           (functionptr) builtin_f2i, SUPPORT_FLOAT && SUPPORT_FICVT, true },
123         { ICMD_D2I,    TYPE_DOUBLE, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
124           (functionptr) builtin_d2i, SUPPORT_DOUBLE && SUPPORT_FICVT, true },
125         { 255, 0, 0, 0, 0, NULL, true, false },
126 };
127
128 #endif
129
130 static int builtintablelen;
131
132 #endif /* USEBUILTINTABLE */
133
134
135 /*****************************************************************************
136                                                  TABLE OF BUILTIN FUNCTIONS
137
138     This table lists the builtin functions which are used inside
139     BUILTIN* opcodes.
140
141     The first part of the table (up to the 255-marker) lists the
142     opcodes which are automatically replaced in stack.c.
143
144     The second part lists the builtin functions which are "manually"
145     used for BUILTIN* opcodes in parse.c and stack.c.
146
147 *****************************************************************************/
148
149 builtin_descriptor builtin_desc[] = {
150 #if defined(USEBUILTINTABLE)
151         {ICMD_LCMP , BUILTIN_lcmp ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_INT   ,
152                      SUPPORT_LONG && SUPPORT_LONG_CMP,false,"lcmp"},
153         
154         {ICMD_LAND , BUILTIN_land ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
155                      SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"land"},
156         {ICMD_LOR  , BUILTIN_lor  ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
157                      SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lor"},
158         {ICMD_LXOR , BUILTIN_lxor ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
159                      SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lxor"},
160         
161         {ICMD_LSHL , BUILTIN_lshl ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_INT   ,TYPE_VOID ,TYPE_LONG  ,
162                      SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshl"},
163         {ICMD_LSHR , BUILTIN_lshr ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_INT   ,TYPE_VOID ,TYPE_LONG  ,
164                      SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshr"},
165         {ICMD_LUSHR, BUILTIN_lushr,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_INT   ,TYPE_VOID ,TYPE_LONG  ,
166                      SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lushr"},
167         
168         {ICMD_LADD , BUILTIN_ladd ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
169                      SUPPORT_LONG && SUPPORT_LONG_ADD,false,"ladd"},
170         {ICMD_LSUB , BUILTIN_lsub ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
171                      SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lsub"},
172         {ICMD_LNEG , BUILTIN_lneg ,ICMD_BUILTIN1,TYPE_LONG  ,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,
173                      SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lneg"},
174         {ICMD_LMUL , BUILTIN_lmul ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
175                      SUPPORT_LONG && SUPPORT_LONG_MUL,false,"lmul"},
176         
177         {ICMD_I2F  , BUILTIN_i2f  ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID ,TYPE_FLOAT ,
178                      SUPPORT_FLOAT && SUPPORT_IFCVT,true ,"i2f"},
179         {ICMD_I2D  , BUILTIN_i2d  ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID ,TYPE_DOUBLE,
180                      SUPPORT_DOUBLE && SUPPORT_IFCVT,true ,"i2d"},
181         {ICMD_L2F  , BUILTIN_l2f  ,ICMD_BUILTIN1,TYPE_LONG  ,TYPE_VOID  ,TYPE_VOID ,TYPE_FLOAT ,
182                      SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT,true ,"l2f"},
183         {ICMD_L2D  , BUILTIN_l2d  ,ICMD_BUILTIN1,TYPE_LONG  ,TYPE_VOID  ,TYPE_VOID ,TYPE_DOUBLE,
184                      SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT,true ,"l2d"},
185         {ICMD_F2L  , BUILTIN_f2l  ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,
186                      SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"f2l"},
187         {ICMD_D2L  , BUILTIN_d2l  ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,
188                      SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"d2l"},
189         {ICMD_F2I  , BUILTIN_f2i  ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID  ,TYPE_VOID ,TYPE_INT   ,
190                      SUPPORT_FLOAT && SUPPORT_FICVT,true ,"f2i"},
191         {ICMD_D2I  , BUILTIN_d2i  ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID  ,TYPE_VOID ,TYPE_INT   ,
192                      SUPPORT_DOUBLE && SUPPORT_FICVT,true ,"d2i"},
193
194         { ICMD_FADD , BUILTIN_fadd  , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fadd"  },
195         { ICMD_FSUB , BUILTIN_fsub  , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fsub"  },
196         { ICMD_FMUL , BUILTIN_fmul  , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fmul"  },
197         { ICMD_FDIV , BUILTIN_fdiv  , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fdiv"  },
198         { ICMD_FNEG , BUILTIN_fneg  , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fneg"  },
199         { ICMD_FCMPL, BUILTIN_fcmpl , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpl" },
200         { ICMD_FCMPG, BUILTIN_fcmpg , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpg" },
201
202         { ICMD_DADD , BUILTIN_dadd  , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dadd"  },
203         { ICMD_DSUB , BUILTIN_dsub  , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dsub"  },
204         { ICMD_DMUL , BUILTIN_dmul  , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dmul"  },
205         { ICMD_DDIV , BUILTIN_ddiv  , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "ddiv"  },
206         { ICMD_DNEG , BUILTIN_dneg  , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dneg"  },
207         { ICMD_DCMPL, BUILTIN_dcmpl , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpl" },
208         { ICMD_DCMPG, BUILTIN_dcmpg , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpg" },
209
210         { ICMD_F2D,  BUILTIN_f2d  , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "f2d" },
211         { ICMD_D2F,  BUILTIN_d2f  , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "d2f" },
212 #endif
213
214         /* this record marks the end of the automatically replaced opcodes */
215         {255,NULL,0,0,0,0,0,0,0,"<INVALID>"},
216
217         /* the following functions are not replaced automatically */
218         
219 #if defined(__ALPHA__)
220         {255, BUILTIN_f2l  ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,0,0,"f2l"},
221         {255, BUILTIN_d2l  ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,0,0,"d2l"},
222         {255, BUILTIN_f2i  ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID  ,TYPE_VOID ,TYPE_INT   ,0,0,"f2i"},
223         {255, BUILTIN_d2i  ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID  ,TYPE_VOID ,TYPE_INT   ,0,0,"d2i"},
224 #endif
225
226         {255,BUILTIN_instanceof      ,ICMD_BUILTIN2,TYPE_ADR   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_INT   ,0,0,"instanceof"},
227         {255,BUILTIN_arrayinstanceof ,ICMD_BUILTIN2,TYPE_ADR   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_INT   ,0,0,"arrayinstanceof"},
228         {255,BUILTIN_checkarraycast  ,ICMD_BUILTIN2,TYPE_ADR   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,0,0,"checkarraycast"},
229         {255,BUILTIN_aastore         ,ICMD_BUILTIN3,TYPE_ADR   ,TYPE_INT   ,TYPE_ADR   ,TYPE_VOID  ,0,0,"aastore"},
230         {255,BUILTIN_new             ,ICMD_BUILTIN1,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"new"},
231         {255,BUILTIN_newarray        ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray"},
232         {255,BUILTIN_newarray_boolean,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_boolean"},
233         {255,BUILTIN_newarray_char   ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_char"},
234         {255,BUILTIN_newarray_float  ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_float"},
235         {255,BUILTIN_newarray_double ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_double"},
236         {255,BUILTIN_newarray_byte   ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_byte"},
237         {255,BUILTIN_newarray_short  ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_short"},
238         {255,BUILTIN_newarray_int    ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_int"},
239         {255,BUILTIN_newarray_long   ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_long"},
240         {255,BUILTIN_anewarray       ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_ADR   ,0,0,"anewarray"},
241 #if defined(USE_THREADS)
242         {255,BUILTIN_monitorenter    ,ICMD_BUILTIN1,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_VOID  ,0,0,"monitorenter"},
243         {255,BUILTIN_monitorexit     ,ICMD_BUILTIN1,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_VOID  ,0,0,"monitorexit"},
244 #endif
245 #if !SUPPORT_DIVISION
246         {255,BUILTIN_idiv            ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_INT   ,TYPE_VOID  ,TYPE_INT   ,0,0,"idiv"},
247         {255,BUILTIN_irem            ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_INT   ,TYPE_VOID  ,TYPE_INT   ,0,0,"irem"},
248 #endif
249 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
250         {255,BUILTIN_ldiv            ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID  ,TYPE_LONG  ,0,0,"ldiv"},
251         {255,BUILTIN_lrem            ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID  ,TYPE_LONG  ,0,0,"lrem"},
252 #endif
253         {255,BUILTIN_frem            ,ICMD_BUILTIN2,TYPE_FLOAT ,TYPE_FLOAT ,TYPE_VOID  ,TYPE_FLOAT ,0,0,"frem"},
254         {255,BUILTIN_drem            ,ICMD_BUILTIN2,TYPE_DOUBLE,TYPE_DOUBLE,TYPE_VOID  ,TYPE_DOUBLE,0,0,"drem"},
255
256         /* this record marks the end of the list */
257         {  0,NULL,0,0,0,0,0,0,0,"<END>"}
258 };
259
260
261 #if defined(USEBUILTINTABLE)
262
263 static int stdopcompare(const void *a, const void *b)
264 {
265         builtin_descriptor *o1 = (builtin_descriptor *) a;
266         builtin_descriptor *o2 = (builtin_descriptor *) b;
267         if (!o1->supported && o2->supported)
268                 return -1;
269         if (o1->supported && !o2->supported)
270                 return 1;
271         return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
272 }
273
274
275 void sort_builtintable(void)
276 {
277         int len;
278
279         len = 0;
280         while (builtin_desc[len].opcode != 255) len++;
281         qsort(builtin_desc, len, sizeof(builtin_descriptor), stdopcompare);
282
283         for (--len; len>=0 && builtin_desc[len].supported; len--);
284         builtintablelen = ++len;
285 }
286
287
288 builtin_descriptor *find_builtin(int icmd)
289 {
290         builtin_descriptor *first = builtin_desc;
291         builtin_descriptor *last = builtin_desc + builtintablelen;
292         int len = last - first;
293         int half;
294         builtin_descriptor *middle;
295
296         while (len > 0) {
297                 half = len / 2;
298                 middle = first + half;
299                 if (middle->opcode < icmd) {
300                         first = middle + 1;
301                         len -= half + 1;
302                 } else
303                         len = half;
304         }
305         return first != last ? first : NULL;
306 }
307
308 #endif /* defined(USEBUILTINTABLE) */
309
310
311 /*****************************************************************************
312                                                                 TYPE CHECKS
313 *****************************************************************************/
314
315
316
317 /*************** internal function: builtin_isanysubclass *********************
318
319         Checks a subclass relation between two classes. Implemented interfaces
320         are interpreted as super classes.
321         Return value:  1 ... sub is subclass of super
322                                    0 ... otherwise
323                                         
324 *****************************************************************************/                                  
325 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
326 {
327         s4 res;
328         castinfo classvalues;
329
330         if (sub == super)
331                 return 1;
332
333         if (super->flags & ACC_INTERFACE)
334                 return (sub->vftbl->interfacetablelength > super->index) &&
335                         (sub->vftbl->interfacetable[-super->index] != NULL);
336
337         asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
338
339         res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
340                 (u4) classvalues.super_diffval;
341
342         return res;
343 }
344
345
346 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
347 {
348         s4 res;
349         s4 base;
350         castinfo classvalues;
351
352         if (sub == super)
353                 return 1;
354
355         asm_getclassvalues_atomic(super, sub, &classvalues);
356
357         if ((base = classvalues.super_baseval) <= 0)
358                 /* super is an interface */
359                 res = (sub->interfacetablelength > -base) &&
360                         (sub->interfacetable[base] != NULL);
361         else
362             res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
363                         <= (u4) classvalues.super_diffval;
364
365         return res;
366 }
367
368
369 /****************** function: builtin_instanceof *****************************
370
371         Checks if an object is an instance of some given class (or subclass of
372         that class). If class is an interface, checks if the interface is
373         implemented.
374         Return value:  1 ... obj is an instance of class or implements the interface
375                                    0 ... otherwise or if obj == NULL
376                          
377 *****************************************************************************/
378
379 /* XXX should use vftbl */
380 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
381 {
382 #ifdef DEBUG
383         log_text ("builtin_instanceof called");
384 #endif  
385         if (!obj)
386                 return 0;
387
388         return builtin_isanysubclass(obj->vftbl->class, class);
389 }
390
391
392
393 /**************** function: builtin_checkcast *******************************
394
395         The same as builtin_instanceof except that 1 is returned when
396         obj == NULL
397                           
398 ****************************************************************************/
399
400 /* XXX should use vftbl */
401 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
402 {
403 #ifdef DEBUG
404         log_text("builtin_checkcast called");
405 #endif
406
407         if (obj == NULL)
408                 return 1;
409         if (builtin_isanysubclass(obj->vftbl->class, class))
410                 return 1;
411
412 #if DEBUG
413         printf("#### checkcast failed ");
414         utf_display(obj->vftbl->class->name);
415         printf(" -> ");
416         utf_display(class->name);
417         printf("\n");
418 #endif
419
420         return 0;
421 }
422
423
424 /*********** internal function: builtin_descriptorscompatible ******************
425
426         Checks if two array type descriptors are assignment compatible
427         Return value:  1 ... target = desc is possible
428                                    0 ... otherwise
429                         
430 ******************************************************************************/
431
432 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
433 {
434         if (desc==target) return 1;
435         if (desc->arraytype != target->arraytype) return 0;
436         if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
437         
438         /* {both arrays are arrays of references} */
439         if (desc->dimension == target->dimension) {
440                 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
441                 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
442                 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
443         }
444         if (desc->dimension < target->dimension) return 0;
445
446         /* {desc has higher dimension than target} */
447         return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
448 }
449
450
451 /******************** function: builtin_checkarraycast ***********************
452
453         Checks if an object is really a subtype of the requested array type.
454         The object has to be an array to begin with. For simple arrays (int, short,
455         double, etc.) the types have to match exactly.
456         For arrays of objects, the type of elements in the array has to be a
457         subtype (or the same type) of the requested element type. For arrays of
458         arrays (which in turn can again be arrays of arrays), the types at the
459         lowest level have to satisfy the corresponding sub class relation.
460         
461         Return value:  1 ... cast is possible
462                                    0 ... otherwise
463         
464         ATTENTION: a cast with a NULL pointer is always possible.
465                         
466 *****************************************************************************/
467
468 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
469 {
470         arraydescriptor *desc;
471         
472         if (!o) return 1;
473         if ((desc = o->vftbl->arraydesc) == NULL) return 0;
474
475         return builtin_descriptorscompatible(desc, target->arraydesc);
476 }
477
478
479 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
480 {
481         if (!obj) return 1;
482         return builtin_checkarraycast(obj, target);
483 }
484
485
486 /************************** exception functions *******************************
487
488 ******************************************************************************/
489
490 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
491 {
492         if (opt_verbose) {
493                 char logtext[MAXLOGTEXT];
494                 sprintf(logtext, "Builtin exception thrown: ");
495
496                 if (xptr) {
497                         java_lang_Throwable *t = (java_lang_Throwable *) xptr;
498
499                         utf_sprint_classname(logtext + strlen(logtext),
500                                                                  xptr->vftbl->class->name);
501
502                         if (t->detailMessage) {
503                                 char *buf;
504
505                                 buf = javastring_tochar((java_objectheader *) t->detailMessage);
506                                 sprintf(logtext + strlen(logtext), ": %s", buf);
507                                 MFREE(buf, char, strlen(buf));
508                         }
509
510                 } else {
511                         sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
512                 }
513
514                 log_text(logtext);
515         }
516
517         *exceptionptr = xptr;
518
519         return xptr;
520 }
521
522
523
524 /******************* function: builtin_canstore *******************************
525
526         Checks, if an object can be stored in an array.
527         Return value:  1 ... possible
528                                    0 ... otherwise
529
530 ******************************************************************************/
531
532 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
533 {
534         arraydescriptor *desc;
535         arraydescriptor *valuedesc;
536         vftbl_t *componentvftbl;
537         vftbl_t *valuevftbl;
538     int dim_m1;
539         int base;
540         castinfo classvalues;
541         
542         if (!o) return 1;
543
544         /* The following is guaranteed (by verifier checks):
545          *
546          *     *) a->...vftbl->arraydesc != NULL
547          *     *) a->...vftbl->arraydesc->componentvftbl != NULL
548          *     *) o->vftbl is not an interface vftbl
549          */
550         
551         desc = a->header.objheader.vftbl->arraydesc;
552     componentvftbl = desc->componentvftbl;
553         valuevftbl = o->vftbl;
554
555     if ((dim_m1 = desc->dimension - 1) == 0) {
556                 s4 res;
557
558                 /* {a is a one-dimensional array} */
559                 /* {a is an array of references} */
560                 
561                 if (valuevftbl == componentvftbl)
562                         return 1;
563
564                 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
565
566                 if ((base = classvalues.super_baseval) <= 0)
567                         /* an array of interface references */
568                         return (valuevftbl->interfacetablelength > -base &&
569                                         valuevftbl->interfacetable[base] != NULL);
570                 
571                 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
572                         <= (unsigned) classvalues.super_diffval;
573
574                 return res;
575     }
576     /* {a has dimension > 1} */
577         /* {componentvftbl->arraydesc != NULL} */
578
579         /* check if o is an array */
580         if ((valuedesc = valuevftbl->arraydesc) == NULL)
581                 return 0;
582         /* {o is an array} */
583
584         return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
585 }
586
587
588 /* This is an optimized version where a is guaranteed to be one-dimensional */
589 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
590 {
591         arraydescriptor *desc;
592         vftbl_t *elementvftbl;
593         vftbl_t *valuevftbl;
594         s4 res;
595         int base;
596         castinfo classvalues;
597         
598         if (!o) return 1;
599
600         /* The following is guaranteed (by verifier checks):
601          *
602          *     *) a->...vftbl->arraydesc != NULL
603          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
604          *     *) a->...vftbl->arraydesc->dimension == 1
605          *     *) o->vftbl is not an interface vftbl
606          */
607
608         desc = a->header.objheader.vftbl->arraydesc;
609     elementvftbl = desc->elementvftbl;
610         valuevftbl = o->vftbl;
611
612         /* {a is a one-dimensional array} */
613         
614         if (valuevftbl == elementvftbl)
615                 return 1;
616
617         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
618
619         if ((base = classvalues.super_baseval) <= 0)
620                 /* an array of interface references */
621                 return (valuevftbl->interfacetablelength > -base &&
622                                 valuevftbl->interfacetable[base] != NULL);
623
624         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
625                 <= (unsigned) classvalues.super_diffval;
626
627         return res;
628 }
629
630
631 /* This is an optimized version where a is guaranteed to be a
632  * one-dimensional array of a class type */
633 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
634 {
635         vftbl_t *elementvftbl;
636         vftbl_t *valuevftbl;
637         s4 res;
638         castinfo classvalues;
639         
640         if (!o) return 1;
641
642         /* The following is guaranteed (by verifier checks):
643          *
644          *     *) a->...vftbl->arraydesc != NULL
645          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
646          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
647          *     *) a->...vftbl->arraydesc->dimension == 1
648          *     *) o->vftbl is not an interface vftbl
649          */
650
651     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
652         valuevftbl = o->vftbl;
653
654         /* {a is a one-dimensional array} */
655         
656         if (valuevftbl == elementvftbl)
657                 return 1;
658
659         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
660
661         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
662                 <= (unsigned) classvalues.super_diffval;
663
664         return res;
665 }
666
667
668 /* builtin_new *****************************************************************
669
670    Creates a new instance of class c on the heap.
671
672    Return value: pointer to the object or NULL if no memory is
673    available
674                         
675 *******************************************************************************/
676
677 java_objectheader *builtin_new(classinfo *c)
678 {
679         java_objectheader *o;
680
681         /* is the class loaded */
682         if (!c->loaded)
683                 if (!load_class_bootstrap(c))
684                         return NULL;
685
686         /* is the class linked */
687         if (!c->linked)
688                 if (!link_class(c))
689                         return NULL;
690
691         if (!c->initialized) {
692                 if (initverbose)
693                         log_message_class("Initialize class (from builtin_new): ", c);
694
695                 if (!class_init(c))
696                         return NULL;
697         }
698
699         o = heap_allocate(c->instancesize, true, c->finalizer);
700
701         if (!o)
702                 return NULL;
703
704         MSET(o, 0, u1, c->instancesize);
705
706         o->vftbl = c->vftbl;
707
708 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
709         initObjectLock(o);
710 #endif
711
712         return o;
713 }
714
715
716 /* builtin_newarray ************************************************************
717
718    Creates an array with the given vftbl on the heap.
719
720    Return value:  pointer to the array or NULL if no memory is available
721
722    CAUTION: The given vftbl must be the vftbl of the *array* class,
723    not of the element class.
724
725 *******************************************************************************/
726
727 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
728 {
729         java_arrayheader *a;
730         arraydescriptor *desc;
731         s4 dataoffset;
732         s4 componentsize;
733         s4 actualsize;
734
735         desc = arrayvftbl->arraydesc;
736         dataoffset = desc->dataoffset;
737         componentsize = desc->componentsize;
738
739         if (size < 0) {
740                 *exceptionptr = new_negativearraysizeexception();
741                 return NULL;
742         }
743
744         actualsize = dataoffset + size * componentsize;
745
746         if (((u4) actualsize) < ((u4) size)) { /* overflow */
747                 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
748                 return NULL;
749         }
750
751         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
752
753         if (!a)
754                 return NULL;
755
756         MSET(a, 0, u1, actualsize);
757
758         a->objheader.vftbl = arrayvftbl;
759
760 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
761         initObjectLock(&a->objheader);
762 #endif
763
764         a->size = size;
765
766         return a;
767 }
768
769
770 /********************** Function: builtin_anewarray *************************
771
772         Creates an array of references to the given class type on the heap.
773
774         Return value: pointer to the array or NULL if no memory is available
775
776     XXX This function does not do The Right Thing, because it uses a
777     classinfo pointer at runtime. builtin_newarray should be used
778     instead.
779
780 *****************************************************************************/
781
782 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
783 {
784         /* is class loaded */
785         if (!component->loaded)
786                 if (!load_class_bootstrap(component))
787                         return NULL;
788
789         /* is class linked */
790         if (!component->linked)
791                 if (!link_class(component))
792                         return NULL;
793
794         return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
795 }
796
797
798 /******************** Function: builtin_newarray_int ***********************
799
800         Creates an array of 32 bit Integers on the heap.
801
802         Return value:  pointer to the array or NULL if no memory is available
803
804 *****************************************************************************/
805
806 java_intarray *builtin_newarray_int(s4 size)
807 {
808         return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
809 }
810
811
812 /******************** Function: builtin_newarray_long ***********************
813
814         Creates an array of 64 bit Integers on the heap.
815
816         Return value:  pointer to the array or NULL if no memory is available
817
818 *****************************************************************************/
819
820 java_longarray *builtin_newarray_long(s4 size)
821 {
822         return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
823 }
824
825
826 /******************** function: builtin_newarray_float ***********************
827
828         Creates an array of 32 bit IEEE floats on the heap.
829
830         Return value:  pointer to the array or NULL if no memory is available
831
832 *****************************************************************************/
833
834 java_floatarray *builtin_newarray_float(s4 size)
835 {
836         return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
837 }
838
839
840 /******************** function: builtin_newarray_double ***********************
841
842         Creates an array of 64 bit IEEE floats on the heap.
843
844         Return value:  pointer to the array or NULL if no memory is available
845
846 *****************************************************************************/
847
848 java_doublearray *builtin_newarray_double(s4 size)
849 {
850         return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
851 }
852
853
854 /******************** function: builtin_newarray_byte ***********************
855
856         Creates an array of 8 bit Integers on the heap.
857
858         Return value:  pointer to the array or NULL if no memory is available
859
860 *****************************************************************************/
861
862 java_bytearray *builtin_newarray_byte(s4 size)
863 {
864         return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
865 }
866
867
868 /******************** function: builtin_newarray_char ************************
869
870         Creates an array of characters on the heap.
871
872         Return value:  pointer to the array or NULL if no memory is available
873
874 *****************************************************************************/
875
876 java_chararray *builtin_newarray_char(s4 size)
877 {
878         return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
879 }
880
881
882 /******************** function: builtin_newarray_short ***********************
883
884         Creates an array of 16 bit Integers on the heap.
885
886         Return value:  pointer to the array or NULL if no memory is available
887
888 *****************************************************************************/
889
890 java_shortarray *builtin_newarray_short(s4 size)
891 {
892         return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
893 }
894
895
896 /******************** function: builtin_newarray_boolean ************************
897
898         Creates an array of bytes on the heap. The array is designated as an array
899         of booleans (important for casts)
900         
901         Return value:  pointer to the array or NULL if no memory is available
902
903 *****************************************************************************/
904
905 java_booleanarray *builtin_newarray_boolean(s4 size)
906 {
907         return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
908 }
909
910
911 /**************** function: builtin_nmultianewarray ***************************
912
913         Creates a multi-dimensional array on the heap. The dimensions are passed in
914         an array of longs.
915
916     Arguments:
917         n............number of dimensions to create
918         arrayvftbl...vftbl of the array class
919         dims.........array containing the size of each dimension to create
920
921         Return value:  pointer to the array or NULL if no memory is available
922
923 ******************************************************************************/
924
925 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
926 /*  java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
927 {
928         s4 size, i;
929         java_arrayheader *a;
930         vftbl_t *componentvftbl;
931
932 /*      utf_display(arrayclass->name); */
933
934 /*      class_load(arrayclass); */
935 /*      class_link(arrayclass); */
936         
937         /* create this dimension */
938         size = (s4) dims[0];
939         a = builtin_newarray(size, arrayvftbl);
940 /*      a = builtin_newarray(size, arrayclass->vftbl); */
941
942         if (!a)
943                 return NULL;
944
945         /* if this is the last dimension return */
946         if (!--n)
947                 return a;
948
949         /* get the vftbl of the components to create */
950         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
951 /*      component = arrayclass->vftbl->arraydesc; */
952
953         /* The verifier guarantees this. */
954         /* if (!componentvftbl) */
955         /*      panic ("multianewarray with too many dimensions"); */
956
957         /* create the component arrays */
958         for (i = 0; i < size; i++) {
959                 java_arrayheader *ea = 
960                         builtin_nmultianewarray(n, componentvftbl, dims + 1);
961
962                 if (!ea)
963                         return NULL;
964                 
965                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
966         }
967
968         return a;
969 }
970
971
972 /*****************************************************************************
973                                           METHOD LOGGING
974
975         Various functions for printing a message at method entry or exit (for
976         debugging)
977         
978 *****************************************************************************/
979
980 u4 methodindent = 0;
981
982 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
983                                                                                    methodinfo *m,
984                                                                                    void *pos,
985                                                                                    s4 line,
986                                                                                    s4 noindent)
987 {
988         if (!noindent) {
989                 if (methodindent)
990                         methodindent--;
991                 else
992                         log_text("WARNING: unmatched methodindent--");
993         }
994         if (opt_verbose || runverbose || verboseexception) {
995                 if (xptr) {
996                         printf("Exception ");
997                         utf_display_classname(xptr->vftbl->class->name);
998
999                 } else {
1000                         printf("Some Throwable");
1001                 }
1002                 printf(" thrown in ");
1003
1004                 if (m) {
1005                         utf_display_classname(m->class->name);
1006                         printf(".");
1007                         utf_display(m->name);
1008                         if (m->flags & ACC_SYNCHRONIZED) {
1009                                 printf("(SYNC");
1010
1011                         } else{
1012                                 printf("(NOSYNC");
1013                         }
1014
1015                         if (m->flags & ACC_NATIVE) {
1016                                 printf(",NATIVE");
1017 #if POINTERSIZE == 8
1018                                 printf(")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1019 #else
1020                                 printf(")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1021 #endif
1022
1023                         } else {
1024 #if POINTERSIZE == 8
1025                                 printf(")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1026 #else
1027                                 printf(")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1028 #endif
1029                                 if (m->class->sourcefile == NULL) {
1030                                         printf("<NO CLASSFILE INFORMATION>");
1031
1032                                 } else {
1033                                         utf_display(m->class->sourcefile);
1034                                 }
1035                                 printf(":%d)\n", line);
1036                         }
1037
1038                 } else
1039                         printf("call_java_method\n");
1040                 fflush(stdout);
1041         }
1042
1043         return xptr;
1044 }
1045
1046
1047 #ifdef TRACE_ARGS_NUM
1048 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1049 #if TRACE_ARGS_NUM >= 6
1050                                                 s8 a4, s8 a5,
1051 #endif
1052 #if TRACE_ARGS_NUM == 8
1053                                                 s8 a6, s8 a7,
1054 #endif
1055                                                 methodinfo *m)
1056 {
1057         s4 i;
1058         char logtext[MAXLOGTEXT];
1059         for (i = 0; i < methodindent; i++)
1060                 logtext[i] = '\t';
1061         if (methodindent == 0) 
1062                         sprintf(logtext + methodindent, "1st_call: ");
1063         else
1064                 sprintf(logtext + methodindent, "called: ");
1065
1066         utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1067         sprintf(logtext + strlen(logtext), ".");
1068         utf_sprint(logtext + strlen(logtext), m->name);
1069         utf_sprint(logtext + strlen(logtext), m->descriptor);
1070
1071         if (m->flags & ACC_PUBLIC)       sprintf(logtext + strlen(logtext), " PUBLIC");
1072         if (m->flags & ACC_PRIVATE)      sprintf(logtext + strlen(logtext), " PRIVATE");
1073         if (m->flags & ACC_PROTECTED)    sprintf(logtext + strlen(logtext), " PROTECTED");
1074         if (m->flags & ACC_STATIC)       sprintf(logtext + strlen(logtext), " STATIC");
1075         if (m->flags & ACC_FINAL)        sprintf(logtext + strlen(logtext), " FINAL");
1076         if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1077         if (m->flags & ACC_VOLATILE)     sprintf(logtext + strlen(logtext), " VOLATILE");
1078         if (m->flags & ACC_TRANSIENT)    sprintf(logtext + strlen(logtext), " TRANSIENT");
1079         if (m->flags & ACC_NATIVE)       sprintf(logtext + strlen(logtext), " NATIVE");
1080         if (m->flags & ACC_INTERFACE)    sprintf(logtext + strlen(logtext), " INTERFACE");
1081         if (m->flags & ACC_ABSTRACT)     sprintf(logtext + strlen(logtext), " ABSTRACT");
1082         
1083
1084         sprintf(logtext + strlen(logtext), "(");
1085
1086         switch (m->paramcount) {
1087         case 0:
1088                 break;
1089
1090 #if defined(__I386__) || defined(__POWERPC__)
1091         case 1:
1092                 sprintf(logtext+strlen(logtext), "%llx", a0);
1093                 break;
1094
1095         case 2:
1096                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1097                 break;
1098
1099         case 3:
1100                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1101                 break;
1102
1103         case 4:
1104                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1105                                 a0,   a1,   a2,   a3);
1106                 break;
1107
1108 #if TRACE_ARGS_NUM >= 6
1109         case 5:
1110                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1111                                 a0,   a1,   a2,   a3,   a4);
1112                 break;
1113
1114         case 6:
1115                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1116                                 a0,   a1,   a2,   a3,   a4,   a5);
1117                 break;
1118 #endif /* TRACE_ARGS_NUM >= 6 */
1119
1120 #if TRACE_ARGS_NUM == 8
1121         case 7:
1122                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1123                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
1124                 break;
1125
1126         case 8:
1127                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1128                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
1129                 break;
1130
1131         default:
1132                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1133                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   m->paramcount - 8);
1134                 break;
1135 #else /* TRACE_ARGS_NUM == 8 */
1136         default:
1137                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1138                                 a0,   a1,   a2,   a3,   a4,   a5,   m->paramcount - 6);
1139                 break;
1140 #endif /* TRACE_ARGS_NUM == 8 */
1141 #else /* defined(__I386__) || defined(__POWERPC__) */
1142         case 1:
1143                 sprintf(logtext+strlen(logtext), "%lx", a0);
1144                 break;
1145
1146         case 2:
1147                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1148                 break;
1149
1150         case 3:
1151                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1152                 break;
1153
1154         case 4:
1155                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1156                                 a0,  a1,  a2,  a3);
1157                 break;
1158
1159 #if TRACE_ARGS_NUM >= 6
1160         case 5:
1161                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1162                                 a0,  a1,  a2,  a3,  a4);
1163                 break;
1164
1165         case 6:
1166                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1167                                 a0,  a1,  a2,  a3,  a4,  a5);
1168                 break;
1169 #endif /* TRACE_ARGS_NUM >= 6 */
1170
1171 #if TRACE_ARGS_NUM == 8
1172         case 7:
1173                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1174                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
1175                 break;
1176
1177         case 8:
1178                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1179                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
1180                 break;
1181 #endif /* TRACE_ARGS_NUM == 8 */
1182
1183         default:
1184 #if TRACE_ARGS_NUM == 4
1185                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1186                                 a0,  a1,  a2,  a3,   m->paramcount - 4);
1187
1188 #elif TRACE_ARGS_NUM == 6
1189                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1190                                 a0,  a1,  a2,  a3,  a4,  a5,  m->paramcount - 6);
1191
1192 #elif TRACE_ARGS_NUM == 8
1193                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1194                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  m->paramcount - 8);
1195 #endif
1196                 break;
1197 #endif /* defined(__I386__) || defined(__POWERPC__) */
1198         }
1199
1200         sprintf(logtext + strlen(logtext), ")");
1201         log_text(logtext);
1202
1203         methodindent++;
1204 }
1205 #endif
1206
1207
1208 void builtin_displaymethodstart(methodinfo *m)
1209 {
1210         char logtext[MAXLOGTEXT];
1211         sprintf(logtext, "                                                                                              ");
1212         sprintf(logtext + methodindent, "called: ");
1213         utf_sprint(logtext + strlen(logtext), m->class->name);
1214         sprintf(logtext + strlen(logtext), ".");
1215         utf_sprint(logtext + strlen(logtext), m->name);
1216         utf_sprint(logtext + strlen(logtext), m->descriptor);
1217
1218         if (m->flags & ACC_PUBLIC)       sprintf(logtext + strlen(logtext), " PUBLIC");
1219         if (m->flags & ACC_PRIVATE)      sprintf(logtext + strlen(logtext), " PRIVATE");
1220         if (m->flags & ACC_PROTECTED)    sprintf(logtext + strlen(logtext), " PROTECTED");
1221         if (m->flags & ACC_STATIC)       sprintf(logtext + strlen(logtext), " STATIC");
1222         if (m->flags & ACC_FINAL)        sprintf(logtext + strlen(logtext), " FINAL");
1223         if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1224         if (m->flags & ACC_VOLATILE)     sprintf(logtext + strlen(logtext), " VOLATILE");
1225         if (m->flags & ACC_TRANSIENT)    sprintf(logtext + strlen(logtext), " TRANSIENT");
1226         if (m->flags & ACC_NATIVE)       sprintf(logtext + strlen(logtext), " NATIVE");
1227         if (m->flags & ACC_INTERFACE)    sprintf(logtext + strlen(logtext), " INTERFACE");
1228         if (m->flags & ACC_ABSTRACT)     sprintf(logtext + strlen(logtext), " ABSTRACT");
1229
1230         log_text(logtext);
1231         methodindent++;
1232 }
1233
1234
1235 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1236 {
1237         int i;
1238         char logtext[MAXLOGTEXT];
1239         for (i = 0; i < methodindent; i++)
1240                 logtext[i] = '\t';
1241         if (methodindent)
1242                 methodindent--;
1243         else
1244                 log_text("WARNING: unmatched methodindent--");
1245
1246         sprintf(logtext + methodindent, "finished: ");
1247         utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1248         sprintf(logtext + strlen(logtext), ".");
1249         utf_sprint(logtext + strlen(logtext), m->name);
1250         utf_sprint(logtext + strlen(logtext), m->descriptor);
1251
1252         switch (m->returntype) {
1253         case TYPE_INT:
1254                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1255                 break;
1256
1257         case TYPE_LONG:
1258 #if defined(__I386__) || defined(__POWERPC__)
1259                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1260 #else
1261                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1262 #endif
1263                 break;
1264
1265         case TYPE_ADDRESS:
1266 #if defined(__I386__) || defined(__POWERPC__)
1267                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1268 #else
1269                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1270 #endif
1271                 break;
1272
1273         case TYPE_FLOAT:
1274                 sprintf(logtext + strlen(logtext), "->%g", f);
1275                 break;
1276
1277         case TYPE_DOUBLE:
1278                 sprintf(logtext + strlen(logtext), "->%g", d);
1279                 break;
1280         }
1281         log_text(logtext);
1282 }
1283
1284
1285 /****************************************************************************
1286                          SYNCHRONIZATION FUNCTIONS
1287 *****************************************************************************/
1288
1289 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1290 /*
1291  * Lock the mutex of an object.
1292  */
1293 void internal_lock_mutex_for_object(java_objectheader *object)
1294 {
1295         mutexHashEntry *entry;
1296         int hashValue;
1297
1298         assert(object != 0);
1299
1300         hashValue = MUTEX_HASH_VALUE(object);
1301         entry = &mutexHashTable[hashValue];
1302
1303         if (entry->object != 0) {
1304                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1305                         entry->object = 0;
1306                         entry->mutex.holder = 0;
1307                         entry->mutex.count = 0;
1308                         entry->mutex.muxWaiters = 0;
1309
1310                 } else {
1311                         while (entry->next != 0 && entry->object != object)
1312                                 entry = entry->next;
1313
1314                         if (entry->object != object) {
1315                                 entry->next = firstFreeOverflowEntry;
1316                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1317
1318                                 entry = entry->next;
1319                                 entry->object = 0;
1320                                 entry->next = 0;
1321                                 assert(entry->conditionCount == 0);
1322                         }
1323                 }
1324
1325         } else {
1326                 entry->mutex.holder = 0;
1327                 entry->mutex.count = 0;
1328                 entry->mutex.muxWaiters = 0;
1329         }
1330
1331         if (entry->object == 0)
1332                 entry->object = object;
1333         
1334         internal_lock_mutex(&entry->mutex);
1335 }
1336 #endif
1337
1338
1339 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1340 /*
1341  * Unlocks the mutex of an object.
1342  */
1343 void internal_unlock_mutex_for_object (java_objectheader *object)
1344 {
1345         int hashValue;
1346         mutexHashEntry *entry;
1347
1348         hashValue = MUTEX_HASH_VALUE(object);
1349         entry = &mutexHashTable[hashValue];
1350
1351         if (entry->object == object) {
1352                 internal_unlock_mutex(&entry->mutex);
1353
1354         } else {
1355                 while (entry->next != 0 && entry->next->object != object)
1356                         entry = entry->next;
1357
1358                 assert(entry->next != 0);
1359
1360                 internal_unlock_mutex(&entry->next->mutex);
1361
1362                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1363                         mutexHashEntry *unlinked = entry->next;
1364
1365                         entry->next = unlinked->next;
1366                         unlinked->next = firstFreeOverflowEntry;
1367                         firstFreeOverflowEntry = unlinked;
1368                 }
1369         }
1370 }
1371 #endif
1372
1373
1374 #if defined(USE_THREADS)
1375 void builtin_monitorenter(java_objectheader *o)
1376 {
1377 #if !defined(NATIVE_THREADS)
1378         int hashValue;
1379
1380         ++blockInts;
1381
1382         hashValue = MUTEX_HASH_VALUE(o);
1383         if (mutexHashTable[hashValue].object == o 
1384                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1385                 ++mutexHashTable[hashValue].mutex.count;
1386         else
1387                 internal_lock_mutex_for_object(o);
1388
1389         --blockInts;
1390 #else
1391         monitorEnter((threadobject *) THREADOBJECT, o);
1392 #endif
1393 }
1394 #endif
1395
1396
1397 #if defined(USE_THREADS)
1398 /*
1399  * Locks the class object - needed for static synchronized methods.
1400  * The use_class_as_object call is needed in order to circumvent a
1401  * possible deadlock with builtin_monitorenter called by another
1402  * thread calling use_class_as_object.
1403  */
1404 void builtin_staticmonitorenter(classinfo *c)
1405 {
1406         use_class_as_object(c);
1407         builtin_monitorenter(&c->header);
1408 }
1409 #endif
1410
1411
1412 #if defined(USE_THREADS)
1413 void *builtin_monitorexit(java_objectheader *o)
1414 {
1415 #if !defined(NATIVE_THREADS)
1416         int hashValue;
1417
1418         ++blockInts;
1419
1420         hashValue = MUTEX_HASH_VALUE(o);
1421         if (mutexHashTable[hashValue].object == o) {
1422                 if (mutexHashTable[hashValue].mutex.count == 1
1423                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1424                         internal_unlock_mutex_for_object(o);
1425                 else
1426                         --mutexHashTable[hashValue].mutex.count;
1427
1428         } else
1429                 internal_unlock_mutex_for_object(o);
1430
1431         --blockInts;
1432         return o;
1433 #else
1434         monitorExit((threadobject *) THREADOBJECT, o);
1435         return o;
1436 #endif
1437 }
1438 #endif
1439
1440
1441 /*****************************************************************************
1442                           MISCELLANEOUS HELPER FUNCTIONS
1443 *****************************************************************************/
1444
1445
1446
1447 /*********** Functions for integer divisions *****************************
1448  
1449         On some systems (eg. DEC ALPHA), integer division is not supported by the
1450         CPU. These helper functions implement the missing functionality.
1451
1452 ******************************************************************************/
1453
1454 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1455 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1456
1457
1458 /************** Functions for long arithmetics *******************************
1459
1460         On systems where 64 bit Integers are not supported by the CPU, these
1461         functions are needed.
1462
1463 ******************************************************************************/
1464
1465
1466 s8 builtin_ladd(s8 a, s8 b)
1467
1468 #if U8_AVAILABLE
1469         return a + b; 
1470 #else
1471         return builtin_i2l(0);
1472 #endif
1473 }
1474
1475 s8 builtin_lsub(s8 a, s8 b) 
1476
1477 #if U8_AVAILABLE
1478         return a - b; 
1479 #else
1480         return builtin_i2l(0);
1481 #endif
1482 }
1483
1484 s8 builtin_lmul(s8 a, s8 b) 
1485
1486 #if U8_AVAILABLE
1487         return a * b; 
1488 #else
1489         return builtin_i2l(0);
1490 #endif
1491 }
1492
1493 s8 builtin_ldiv(s8 a, s8 b) 
1494
1495 #if U8_AVAILABLE
1496         return a / b; 
1497 #else
1498         return builtin_i2l(0);
1499 #endif
1500 }
1501
1502 s8 builtin_lrem(s8 a, s8 b) 
1503
1504 #if U8_AVAILABLE
1505         return a % b; 
1506 #else
1507         return builtin_i2l(0);
1508 #endif
1509 }
1510
1511 s8 builtin_lshl(s8 a, s4 b) 
1512
1513 #if U8_AVAILABLE
1514         return a << (b & 63);
1515 #else
1516         return builtin_i2l(0);
1517 #endif
1518 }
1519
1520 s8 builtin_lshr(s8 a, s4 b) 
1521
1522 #if U8_AVAILABLE
1523         return a >> (b & 63);
1524 #else
1525         return builtin_i2l(0);
1526 #endif
1527 }
1528
1529 s8 builtin_lushr(s8 a, s4 b) 
1530
1531 #if U8_AVAILABLE
1532         return ((u8) a) >> (b & 63);
1533 #else
1534         return builtin_i2l(0);
1535 #endif
1536 }
1537
1538 s8 builtin_land(s8 a, s8 b) 
1539
1540 #if U8_AVAILABLE
1541         return a & b; 
1542 #else
1543         return builtin_i2l(0);
1544 #endif
1545 }
1546
1547 s8 builtin_lor(s8 a, s8 b) 
1548
1549 #if U8_AVAILABLE
1550         return a | b; 
1551 #else
1552         return builtin_i2l(0);
1553 #endif
1554 }
1555
1556 s8 builtin_lxor(s8 a, s8 b) 
1557
1558 #if U8_AVAILABLE
1559         return a ^ b; 
1560 #else
1561         return builtin_i2l(0);
1562 #endif
1563 }
1564
1565 s8 builtin_lneg(s8 a) 
1566
1567 #if U8_AVAILABLE
1568         return -a;
1569 #else
1570         return builtin_i2l(0);
1571 #endif
1572 }
1573
1574 s4 builtin_lcmp(s8 a, s8 b) 
1575
1576 #if U8_AVAILABLE
1577         if (a < b) return -1;
1578         if (a > b) return 1;
1579         return 0;
1580 #else
1581         return 0;
1582 #endif
1583 }
1584
1585
1586
1587
1588
1589 /*********** Functions for floating point operations *************************/
1590
1591 float builtin_fadd(float a, float b)
1592 {
1593         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1594         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1595         if (finitef(a)) {
1596                 if (finitef(b))
1597                         return a + b;
1598                 else
1599                         return b;
1600         }
1601         else {
1602                 if (finitef(b))
1603                         return a;
1604                 else {
1605                         if (copysignf(1.0, a) == copysignf(1.0, b))
1606                                 return a;
1607                         else
1608                                 return intBitsToFloat(FLT_NAN);
1609                 }
1610         }
1611 }
1612
1613
1614 float builtin_fsub(float a, float b)
1615 {
1616         return builtin_fadd(a, builtin_fneg(b));
1617 }
1618
1619
1620 float builtin_fmul(float a, float b)
1621 {
1622         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1623         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1624         if (finitef(a)) {
1625                 if (finitef(b)) return a * b;
1626                 else {
1627                         if (a == 0) return intBitsToFloat(FLT_NAN);
1628                         else return copysignf(b, copysignf(1.0, b)*a);
1629                 }
1630         }
1631         else {
1632                 if (finitef(b)) {
1633                         if (b == 0) return intBitsToFloat(FLT_NAN);
1634                         else return copysignf(a, copysignf(1.0, a)*b);
1635                 }
1636                 else {
1637                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1638                 }
1639         }
1640 }
1641
1642
1643 float builtin_fdiv(float a, float b)
1644 {
1645         if (finitef(a) && finitef(b)) {
1646                 if (b != 0)
1647                         return a / b;
1648                 else {
1649                         if (a > 0)
1650                                 return intBitsToFloat(FLT_POSINF);
1651                         else if (a < 0)
1652                                 return intBitsToFloat(FLT_NEGINF);
1653                 }
1654         }
1655         return intBitsToFloat(FLT_NAN);
1656 }
1657
1658
1659 float builtin_frem(float a, float b)
1660 {
1661         return fmodf(a, b);
1662 }
1663
1664
1665 float builtin_fneg(float a)
1666 {
1667         if (isnanf(a)) return a;
1668         else {
1669                 if (finitef(a)) return -a;
1670                 else return copysignf(a, -copysignf(1.0, a));
1671         }
1672 }
1673
1674
1675 s4 builtin_fcmpl(float a, float b)
1676 {
1677         if (isnanf(a)) return -1;
1678         if (isnanf(b)) return -1;
1679         if (!finitef(a) || !finitef(b)) {
1680                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1681                 b = finitef(b) ? 0 : copysignf(1.0, b);
1682         }
1683         if (a > b) return 1;
1684         if (a == b) return 0;
1685         return -1;
1686 }
1687
1688
1689 s4 builtin_fcmpg(float a, float b)
1690 {
1691         if (isnanf(a)) return 1;
1692         if (isnanf(b)) return 1;
1693         if (!finitef(a) || !finitef(b)) {
1694                 a = finitef(a) ? 0 : copysignf(1.0, a);
1695                 b = finitef(b) ? 0 : copysignf(1.0, b);
1696         }
1697         if (a > b) return 1;
1698         if (a == b) return 0;
1699         return -1;
1700 }
1701
1702
1703
1704 /************************* Functions for doubles ****************************/
1705
1706 double builtin_dadd(double a, double b)
1707 {
1708         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1709         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1710         if (finite(a)) {
1711                 if (finite(b)) return a + b;
1712                 else return b;
1713         }
1714         else {
1715                 if (finite(b)) return a;
1716                 else {
1717                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1718                         else return longBitsToDouble(DBL_NAN);
1719                 }
1720         }
1721 }
1722
1723
1724 double builtin_dsub(double a, double b)
1725 {
1726         return builtin_dadd(a, builtin_dneg(b));
1727 }
1728
1729
1730 double builtin_dmul(double a, double b)
1731 {
1732         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1733         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1734         if (finite(a)) {
1735                 if (finite(b)) return a * b;
1736                 else {
1737                         if (a == 0) return longBitsToDouble(DBL_NAN);
1738                         else return copysign(b, copysign(1.0, b) * a);
1739                 }
1740         }
1741         else {
1742                 if (finite(b)) {
1743                         if (b == 0) return longBitsToDouble(DBL_NAN);
1744                         else return copysign(a, copysign(1.0, a) * b);
1745                 }
1746                 else {
1747                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1748                 }
1749         }
1750 }
1751
1752
1753 double builtin_ddiv(double a, double b)
1754 {
1755         if (finite(a)) {
1756                 if (finite(b)) {
1757                         return a / b;
1758
1759                 } else {
1760                         if (isnan(b))
1761                                 return longBitsToDouble(DBL_NAN);
1762                         else
1763                                 return copysign(0.0, b);
1764                 }
1765
1766         } else {
1767                 if (finite(b)) {
1768                         if (a > 0)
1769                                 return longBitsToDouble(DBL_POSINF);
1770                         else if (a < 0)
1771                                 return longBitsToDouble(DBL_NEGINF);
1772
1773                 } else
1774                         return longBitsToDouble(DBL_NAN);
1775         }
1776
1777 /*      if (finite(a) && finite(b)) { */
1778 /*              if (b != 0) */
1779 /*                      return a / b; */
1780 /*              else { */
1781 /*                      if (a > 0) */
1782 /*                              return longBitsToDouble(DBL_POSINF); */
1783 /*                      else if (a < 0) */
1784 /*                              return longBitsToDouble(DBL_NEGINF); */
1785 /*              } */
1786 /*      } */
1787
1788         /* keep compiler happy */
1789         return 0;
1790 }
1791
1792
1793 double builtin_drem(double a, double b)
1794 {
1795         return fmod(a, b);
1796 }
1797
1798
1799 double builtin_dneg(double a)
1800 {
1801         if (isnan(a)) return a;
1802         else {
1803                 if (finite(a)) return -a;
1804                 else return copysign(a, -copysign(1.0, a));
1805         }
1806 }
1807
1808
1809 s4 builtin_dcmpl(double a, double b)
1810 {
1811         if (isnan(a)) return -1;
1812         if (isnan(b)) return -1;
1813         if (!finite(a) || !finite(b)) {
1814                 a = finite(a) ? 0 : copysign(1.0, a);
1815                 b = finite(b) ? 0 : copysign(1.0, b);
1816         }
1817         if (a > b) return 1;
1818         if (a == b) return 0;
1819         return -1;
1820 }
1821
1822
1823 s4 builtin_dcmpg(double a, double b)
1824 {
1825         if (isnan(a)) return 1;
1826         if (isnan(b)) return 1;
1827         if (!finite(a) || !finite(b)) {
1828                 a = finite(a) ? 0 : copysign(1.0, a);
1829                 b = finite(b) ? 0 : copysign(1.0, b);
1830         }
1831         if (a > b) return 1;
1832         if (a == b) return 0;
1833         return -1;
1834 }
1835
1836
1837 /*********************** Conversion operations ****************************/
1838
1839 s8 builtin_i2l(s4 i)
1840 {
1841 #if U8_AVAILABLE
1842         return i;
1843 #else
1844         s8 v;
1845         v.high = 0;
1846         v.low = i;
1847         return v;
1848 #endif
1849 }
1850
1851
1852 float builtin_i2f(s4 a)
1853 {
1854         float f = (float) a;
1855         return f;
1856 }
1857
1858
1859 double builtin_i2d(s4 a)
1860 {
1861         double d = (double) a;
1862         return d;
1863 }
1864
1865
1866 s4 builtin_l2i(s8 l)
1867 {
1868 #if U8_AVAILABLE
1869         return (s4) l;
1870 #else
1871         return l.low;
1872 #endif
1873 }
1874
1875
1876 float builtin_l2f(s8 a)
1877 {
1878 #if U8_AVAILABLE
1879         float f = (float) a;
1880         return f;
1881 #else
1882         return 0.0;
1883 #endif
1884 }
1885
1886
1887 double builtin_l2d(s8 a)
1888 {
1889 #if U8_AVAILABLE
1890         double d = (double) a;
1891         return d;
1892 #else
1893         return 0.0;
1894 #endif
1895 }
1896
1897
1898 s4 builtin_f2i(float a) 
1899 {
1900
1901         return builtin_d2i((double) a);
1902
1903         /*      float f;
1904         
1905                 if (isnanf(a))
1906                 return 0;
1907                 if (finitef(a)) {
1908                 if (a > 2147483647)
1909                 return 2147483647;
1910                 if (a < (-2147483648))
1911                 return (-2147483648);
1912                 return (s4) a;
1913                 }
1914                 f = copysignf((float) 1.0, a);
1915                 if (f > 0)
1916                 return 2147483647;
1917                 return (-2147483648); */
1918 }
1919
1920
1921 s8 builtin_f2l(float a)
1922 {
1923
1924         return builtin_d2l((double) a);
1925
1926         /*      float f;
1927         
1928                 if (finitef(a)) {
1929                 if (a > 9223372036854775807L)
1930                 return 9223372036854775807L;
1931                 if (a < (-9223372036854775808L))
1932                 return (-9223372036854775808L);
1933                 return (s8) a;
1934                 }
1935                 if (isnanf(a))
1936                 return 0;
1937                 f = copysignf((float) 1.0, a);
1938                 if (f > 0)
1939                 return 9223372036854775807L;
1940                 return (-9223372036854775808L); */
1941 }
1942
1943
1944 double builtin_f2d(float a)
1945 {
1946         if (finitef(a)) return (double) a;
1947         else {
1948                 if (isnanf(a))
1949                         return longBitsToDouble(DBL_NAN);
1950                 else
1951                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1952         }
1953 }
1954
1955
1956 s4 builtin_d2i(double a) 
1957
1958         double d;
1959         
1960         if (finite(a)) {
1961                 if (a >= 2147483647)
1962                         return 2147483647;
1963                 if (a <= (-2147483647-1))
1964                         return (-2147483647-1);
1965                 return (s4) a;
1966         }
1967         if (isnan(a))
1968                 return 0;
1969         d = copysign(1.0, a);
1970         if (d > 0)
1971                 return 2147483647;
1972         return (-2147483647-1);
1973 }
1974
1975
1976 s8 builtin_d2l(double a)
1977 {
1978         double d;
1979         
1980         if (finite(a)) {
1981                 if (a >= 9223372036854775807LL)
1982                         return 9223372036854775807LL;
1983                 if (a <= (-9223372036854775807LL-1))
1984                         return (-9223372036854775807LL-1);
1985                 return (s8) a;
1986         }
1987         if (isnan(a))
1988                 return 0;
1989         d = copysign(1.0, a);
1990         if (d > 0)
1991                 return 9223372036854775807LL;
1992         return (-9223372036854775807LL-1);
1993 }
1994
1995
1996 float builtin_d2f(double a)
1997 {
1998         if (finite(a))
1999                 return (float) a;
2000         else {
2001                 if (isnan(a))
2002                         return intBitsToFloat(FLT_NAN);
2003                 else
2004                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2005         }
2006 }
2007
2008
2009 /* used to convert FLT_xxx defines into float values */
2010
2011 inline float intBitsToFloat(s4 i)
2012 {
2013         imm_union imb;
2014
2015         imb.i = i;
2016         return imb.f;
2017 }
2018
2019
2020 /* used to convert DBL_xxx defines into double values */
2021
2022 inline float longBitsToDouble(s8 l)
2023 {
2024         imm_union imb;
2025
2026         imb.l = l;
2027         return imb.d;
2028 }
2029
2030
2031 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2032 {
2033         return (java_arrayheader *)
2034                 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2035 }
2036
2037
2038 s4 builtin_dummy()
2039 {
2040         panic("Internal error: builtin_dummy called (native function is missing)");
2041         return 0; /* for the compiler */
2042 }
2043
2044
2045 /* builtin_asm_get_exceptionptrptr *********************************************
2046
2047    this is a wrapper for calls from asmpart
2048
2049 *******************************************************************************/
2050
2051 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2052 java_objectheader **builtin_asm_get_exceptionptrptr()
2053 {
2054         return builtin_get_exceptionptrptr();
2055 }
2056 #endif
2057
2058
2059 methodinfo *builtin_asm_get_threadrootmethod()
2060 {
2061         return *threadrootmethod;
2062 }
2063
2064
2065 inline void* builtin_asm_get_stackframeinfo()
2066 {
2067 /*log_text("builtin_asm_get_stackframeinfo()");*/
2068 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2069         return &THREADINFO->_stackframeinfo;
2070 #else
2071 #if defined(__GNUC__)
2072 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2073 #endif
2074                 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2075 #endif
2076 }
2077
2078 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2079 /*      stacktraceelement *el;*/
2080         size_t s;
2081         s=(end-begin);
2082         /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2083         *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2084 #if 0
2085         *el=MNEW(stacktraceelement,s+1); /*GC*/
2086 #endif
2087         memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2088         (*el)[s].method=0;
2089 #if defined(__GNUC__)
2090 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2091 #endif
2092         (*el)[s].linenumber=-1; /* -1 can never be reched otherwise, since line numbers are only u2, so it is save to use that as flag */
2093         return *el;
2094 }
2095
2096 /*
2097  * These are local overrides for various environment variables in Emacs.
2098  * Please do not remove this and leave it at the end of the file, where
2099  * Emacs will automagically detect them.
2100  * ---------------------------------------------------------------------
2101  * Local variables:
2102  * mode: c
2103  * indent-tabs-mode: t
2104  * c-basic-offset: 4
2105  * tab-width: 4
2106  * End:
2107  */