removed the class hash and all functions identifying classes by name only
[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 2195 2005-04-03 16:53:16Z edwin $
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         /*utf_fprint(stderr,c->name);fprintf(stderr,"\n");*/
683         assert(c->loaded);
684
685         /* is the class linked */
686         if (!c->linked)
687                 if (!link_class(c))
688                         return NULL;
689
690         if (!c->initialized) {
691                 if (initverbose)
692                         log_message_class("Initialize class (from builtin_new): ", c);
693
694                 if (!class_init(c))
695                         return NULL;
696         }
697
698         o = heap_allocate(c->instancesize, true, c->finalizer);
699
700         if (!o)
701                 return NULL;
702
703         MSET(o, 0, u1, c->instancesize);
704
705         o->vftbl = c->vftbl;
706
707 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
708         initObjectLock(o);
709 #endif
710
711         return o;
712 }
713
714
715 /* builtin_newarray ************************************************************
716
717    Creates an array with the given vftbl on the heap.
718
719    Return value:  pointer to the array or NULL if no memory is available
720
721    CAUTION: The given vftbl must be the vftbl of the *array* class,
722    not of the element class.
723
724 *******************************************************************************/
725
726 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
727 {
728         java_arrayheader *a;
729         arraydescriptor *desc;
730         s4 dataoffset;
731         s4 componentsize;
732         s4 actualsize;
733
734         desc = arrayvftbl->arraydesc;
735         dataoffset = desc->dataoffset;
736         componentsize = desc->componentsize;
737
738         if (size < 0) {
739                 *exceptionptr = new_negativearraysizeexception();
740                 return NULL;
741         }
742
743         actualsize = dataoffset + size * componentsize;
744
745         if (((u4) actualsize) < ((u4) size)) { /* overflow */
746                 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
747                 return NULL;
748         }
749
750         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
751
752         if (!a)
753                 return NULL;
754
755         MSET(a, 0, u1, actualsize);
756
757         a->objheader.vftbl = arrayvftbl;
758
759 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
760         initObjectLock(&a->objheader);
761 #endif
762
763         a->size = size;
764
765         return a;
766 }
767
768
769 /********************** Function: builtin_anewarray *************************
770
771         Creates an array of references to the given class type on the heap.
772
773         Return value: pointer to the array or NULL if no memory is available
774
775     XXX This function does not do The Right Thing, because it uses a
776     classinfo pointer at runtime. builtin_newarray should be used
777     instead.
778
779 *****************************************************************************/
780
781 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
782 {
783         classinfo *c;
784         
785         /* is class loaded */
786         assert(component->loaded);
787
788         /* is class linked */
789         if (!component->linked)
790                 if (!link_class(component))
791                         return NULL;
792
793         c = class_array_of(component,true);
794         if (!c)
795                 return NULL;
796         return (java_objectarray *) builtin_newarray(size, c->vftbl);
797 }
798
799
800 /******************** Function: builtin_newarray_int ***********************
801
802         Creates an array of 32 bit Integers on the heap.
803
804         Return value:  pointer to the array or NULL if no memory is available
805
806 *****************************************************************************/
807
808 java_intarray *builtin_newarray_int(s4 size)
809 {
810         return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
811 }
812
813
814 /******************** Function: builtin_newarray_long ***********************
815
816         Creates an array of 64 bit Integers on the heap.
817
818         Return value:  pointer to the array or NULL if no memory is available
819
820 *****************************************************************************/
821
822 java_longarray *builtin_newarray_long(s4 size)
823 {
824         return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
825 }
826
827
828 /******************** function: builtin_newarray_float ***********************
829
830         Creates an array of 32 bit IEEE floats on the heap.
831
832         Return value:  pointer to the array or NULL if no memory is available
833
834 *****************************************************************************/
835
836 java_floatarray *builtin_newarray_float(s4 size)
837 {
838         return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
839 }
840
841
842 /******************** function: builtin_newarray_double ***********************
843
844         Creates an array of 64 bit IEEE floats on the heap.
845
846         Return value:  pointer to the array or NULL if no memory is available
847
848 *****************************************************************************/
849
850 java_doublearray *builtin_newarray_double(s4 size)
851 {
852         return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
853 }
854
855
856 /******************** function: builtin_newarray_byte ***********************
857
858         Creates an array of 8 bit Integers on the heap.
859
860         Return value:  pointer to the array or NULL if no memory is available
861
862 *****************************************************************************/
863
864 java_bytearray *builtin_newarray_byte(s4 size)
865 {
866         return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
867 }
868
869
870 /******************** function: builtin_newarray_char ************************
871
872         Creates an array of characters on the heap.
873
874         Return value:  pointer to the array or NULL if no memory is available
875
876 *****************************************************************************/
877
878 java_chararray *builtin_newarray_char(s4 size)
879 {
880         return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
881 }
882
883
884 /******************** function: builtin_newarray_short ***********************
885
886         Creates an array of 16 bit Integers on the heap.
887
888         Return value:  pointer to the array or NULL if no memory is available
889
890 *****************************************************************************/
891
892 java_shortarray *builtin_newarray_short(s4 size)
893 {
894         return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
895 }
896
897
898 /******************** function: builtin_newarray_boolean ************************
899
900         Creates an array of bytes on the heap. The array is designated as an array
901         of booleans (important for casts)
902         
903         Return value:  pointer to the array or NULL if no memory is available
904
905 *****************************************************************************/
906
907 java_booleanarray *builtin_newarray_boolean(s4 size)
908 {
909         return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
910 }
911
912
913 /**************** function: builtin_nmultianewarray ***************************
914
915         Creates a multi-dimensional array on the heap. The dimensions are passed in
916         an array of longs.
917
918     Arguments:
919         n............number of dimensions to create
920         arrayvftbl...vftbl of the array class
921         dims.........array containing the size of each dimension to create
922
923         Return value:  pointer to the array or NULL if no memory is available
924
925 ******************************************************************************/
926
927 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
928 /*  java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
929 {
930         s4 size, i;
931         java_arrayheader *a;
932         vftbl_t *componentvftbl;
933
934 /*      utf_display(arrayclass->name); */
935
936 /*      class_load(arrayclass); */
937 /*      class_link(arrayclass); */
938         
939         /* create this dimension */
940         size = (s4) dims[0];
941         a = builtin_newarray(size, arrayvftbl);
942 /*      a = builtin_newarray(size, arrayclass->vftbl); */
943
944         if (!a)
945                 return NULL;
946
947         /* if this is the last dimension return */
948         if (!--n)
949                 return a;
950
951         /* get the vftbl of the components to create */
952         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
953 /*      component = arrayclass->vftbl->arraydesc; */
954
955         /* The verifier guarantees this. */
956         /* if (!componentvftbl) */
957         /*      panic ("multianewarray with too many dimensions"); */
958
959         /* create the component arrays */
960         for (i = 0; i < size; i++) {
961                 java_arrayheader *ea = 
962                         builtin_nmultianewarray(n, componentvftbl, dims + 1);
963
964                 if (!ea)
965                         return NULL;
966                 
967                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
968         }
969
970         return a;
971 }
972
973
974 /*****************************************************************************
975                                           METHOD LOGGING
976
977         Various functions for printing a message at method entry or exit (for
978         debugging)
979         
980 *****************************************************************************/
981
982 u4 methodindent = 0;
983
984 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
985                                                                                    methodinfo *m,
986                                                                                    void *pos,
987                                                                                    s4 line,
988                                                                                    s4 noindent)
989 {
990         if (!noindent) {
991                 if (methodindent)
992                         methodindent--;
993                 else
994                         log_text("WARNING: unmatched methodindent--");
995         }
996         if (opt_verbose || runverbose || verboseexception) {
997                 if (xptr) {
998                         printf("Exception ");
999                         utf_display_classname(xptr->vftbl->class->name);
1000
1001                 } else {
1002                         printf("Some Throwable");
1003                 }
1004                 printf(" thrown in ");
1005
1006                 if (m) {
1007                         utf_display_classname(m->class->name);
1008                         printf(".");
1009                         utf_display(m->name);
1010                         if (m->flags & ACC_SYNCHRONIZED) {
1011                                 printf("(SYNC");
1012
1013                         } else{
1014                                 printf("(NOSYNC");
1015                         }
1016
1017                         if (m->flags & ACC_NATIVE) {
1018                                 printf(",NATIVE");
1019 #if POINTERSIZE == 8
1020                                 printf(")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1021 #else
1022                                 printf(")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1023 #endif
1024
1025                         } else {
1026 #if POINTERSIZE == 8
1027                                 printf(")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1028 #else
1029                                 printf(")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1030 #endif
1031                                 if (m->class->sourcefile == NULL) {
1032                                         printf("<NO CLASSFILE INFORMATION>");
1033
1034                                 } else {
1035                                         utf_display(m->class->sourcefile);
1036                                 }
1037                                 printf(":%d)\n", line);
1038                         }
1039
1040                 } else
1041                         printf("call_java_method\n");
1042                 fflush(stdout);
1043         }
1044
1045         return xptr;
1046 }
1047
1048
1049 #ifdef TRACE_ARGS_NUM
1050 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1051 #if TRACE_ARGS_NUM >= 6
1052                                                 s8 a4, s8 a5,
1053 #endif
1054 #if TRACE_ARGS_NUM == 8
1055                                                 s8 a6, s8 a7,
1056 #endif
1057                                                 methodinfo *m)
1058 {
1059         s4 i;
1060         char logtext[MAXLOGTEXT];
1061         for (i = 0; i < methodindent; i++)
1062                 logtext[i] = '\t';
1063         if (methodindent == 0) 
1064                         sprintf(logtext + methodindent, "1st_call: ");
1065         else
1066                 sprintf(logtext + methodindent, "called: ");
1067
1068         utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1069         sprintf(logtext + strlen(logtext), ".");
1070         utf_sprint(logtext + strlen(logtext), m->name);
1071         utf_sprint(logtext + strlen(logtext), m->descriptor);
1072
1073         if (m->flags & ACC_PUBLIC)       sprintf(logtext + strlen(logtext), " PUBLIC");
1074         if (m->flags & ACC_PRIVATE)      sprintf(logtext + strlen(logtext), " PRIVATE");
1075         if (m->flags & ACC_PROTECTED)    sprintf(logtext + strlen(logtext), " PROTECTED");
1076         if (m->flags & ACC_STATIC)       sprintf(logtext + strlen(logtext), " STATIC");
1077         if (m->flags & ACC_FINAL)        sprintf(logtext + strlen(logtext), " FINAL");
1078         if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1079         if (m->flags & ACC_VOLATILE)     sprintf(logtext + strlen(logtext), " VOLATILE");
1080         if (m->flags & ACC_TRANSIENT)    sprintf(logtext + strlen(logtext), " TRANSIENT");
1081         if (m->flags & ACC_NATIVE)       sprintf(logtext + strlen(logtext), " NATIVE");
1082         if (m->flags & ACC_INTERFACE)    sprintf(logtext + strlen(logtext), " INTERFACE");
1083         if (m->flags & ACC_ABSTRACT)     sprintf(logtext + strlen(logtext), " ABSTRACT");
1084         
1085
1086         sprintf(logtext + strlen(logtext), "(");
1087
1088         switch (m->paramcount) {
1089         case 0:
1090                 break;
1091
1092 #if defined(__I386__) || defined(__POWERPC__)
1093         case 1:
1094                 sprintf(logtext+strlen(logtext), "%llx", a0);
1095                 break;
1096
1097         case 2:
1098                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1099                 break;
1100
1101         case 3:
1102                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1103                 break;
1104
1105         case 4:
1106                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1107                                 a0,   a1,   a2,   a3);
1108                 break;
1109
1110 #if TRACE_ARGS_NUM >= 6
1111         case 5:
1112                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1113                                 a0,   a1,   a2,   a3,   a4);
1114                 break;
1115
1116         case 6:
1117                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1118                                 a0,   a1,   a2,   a3,   a4,   a5);
1119                 break;
1120 #endif /* TRACE_ARGS_NUM >= 6 */
1121
1122 #if TRACE_ARGS_NUM == 8
1123         case 7:
1124                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1125                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
1126                 break;
1127
1128         case 8:
1129                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1130                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
1131                 break;
1132
1133         default:
1134                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1135                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   m->paramcount - 8);
1136                 break;
1137 #else /* TRACE_ARGS_NUM == 8 */
1138         default:
1139                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1140                                 a0,   a1,   a2,   a3,   a4,   a5,   m->paramcount - 6);
1141                 break;
1142 #endif /* TRACE_ARGS_NUM == 8 */
1143 #else /* defined(__I386__) || defined(__POWERPC__) */
1144         case 1:
1145                 sprintf(logtext+strlen(logtext), "%lx", a0);
1146                 break;
1147
1148         case 2:
1149                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1150                 break;
1151
1152         case 3:
1153                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1154                 break;
1155
1156         case 4:
1157                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1158                                 a0,  a1,  a2,  a3);
1159                 break;
1160
1161 #if TRACE_ARGS_NUM >= 6
1162         case 5:
1163                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1164                                 a0,  a1,  a2,  a3,  a4);
1165                 break;
1166
1167         case 6:
1168                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1169                                 a0,  a1,  a2,  a3,  a4,  a5);
1170                 break;
1171 #endif /* TRACE_ARGS_NUM >= 6 */
1172
1173 #if TRACE_ARGS_NUM == 8
1174         case 7:
1175                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1176                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
1177                 break;
1178
1179         case 8:
1180                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1181                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
1182                 break;
1183 #endif /* TRACE_ARGS_NUM == 8 */
1184
1185         default:
1186 #if TRACE_ARGS_NUM == 4
1187                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1188                                 a0,  a1,  a2,  a3,   m->paramcount - 4);
1189
1190 #elif TRACE_ARGS_NUM == 6
1191                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1192                                 a0,  a1,  a2,  a3,  a4,  a5,  m->paramcount - 6);
1193
1194 #elif TRACE_ARGS_NUM == 8
1195                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1196                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  m->paramcount - 8);
1197 #endif
1198                 break;
1199 #endif /* defined(__I386__) || defined(__POWERPC__) */
1200         }
1201
1202         sprintf(logtext + strlen(logtext), ")");
1203         log_text(logtext);
1204
1205         methodindent++;
1206 }
1207 #endif
1208
1209
1210 void builtin_displaymethodstart(methodinfo *m)
1211 {
1212         char logtext[MAXLOGTEXT];
1213         sprintf(logtext, "                                                                                              ");
1214         sprintf(logtext + methodindent, "called: ");
1215         utf_sprint(logtext + strlen(logtext), m->class->name);
1216         sprintf(logtext + strlen(logtext), ".");
1217         utf_sprint(logtext + strlen(logtext), m->name);
1218         utf_sprint(logtext + strlen(logtext), m->descriptor);
1219
1220         if (m->flags & ACC_PUBLIC)       sprintf(logtext + strlen(logtext), " PUBLIC");
1221         if (m->flags & ACC_PRIVATE)      sprintf(logtext + strlen(logtext), " PRIVATE");
1222         if (m->flags & ACC_PROTECTED)    sprintf(logtext + strlen(logtext), " PROTECTED");
1223         if (m->flags & ACC_STATIC)       sprintf(logtext + strlen(logtext), " STATIC");
1224         if (m->flags & ACC_FINAL)        sprintf(logtext + strlen(logtext), " FINAL");
1225         if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1226         if (m->flags & ACC_VOLATILE)     sprintf(logtext + strlen(logtext), " VOLATILE");
1227         if (m->flags & ACC_TRANSIENT)    sprintf(logtext + strlen(logtext), " TRANSIENT");
1228         if (m->flags & ACC_NATIVE)       sprintf(logtext + strlen(logtext), " NATIVE");
1229         if (m->flags & ACC_INTERFACE)    sprintf(logtext + strlen(logtext), " INTERFACE");
1230         if (m->flags & ACC_ABSTRACT)     sprintf(logtext + strlen(logtext), " ABSTRACT");
1231
1232         log_text(logtext);
1233         methodindent++;
1234 }
1235
1236
1237 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1238 {
1239         int i;
1240         char logtext[MAXLOGTEXT];
1241         for (i = 0; i < methodindent; i++)
1242                 logtext[i] = '\t';
1243         if (methodindent)
1244                 methodindent--;
1245         else
1246                 log_text("WARNING: unmatched methodindent--");
1247
1248         sprintf(logtext + methodindent, "finished: ");
1249         utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1250         sprintf(logtext + strlen(logtext), ".");
1251         utf_sprint(logtext + strlen(logtext), m->name);
1252         utf_sprint(logtext + strlen(logtext), m->descriptor);
1253
1254         switch (m->returntype) {
1255         case TYPE_INT:
1256                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1257                 break;
1258
1259         case TYPE_LONG:
1260 #if defined(__I386__) || defined(__POWERPC__)
1261                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1262 #else
1263                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1264 #endif
1265                 break;
1266
1267         case TYPE_ADDRESS:
1268 #if defined(__I386__) || defined(__POWERPC__)
1269                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1270 #else
1271                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1272 #endif
1273                 break;
1274
1275         case TYPE_FLOAT:
1276                 sprintf(logtext + strlen(logtext), "->%g", f);
1277                 break;
1278
1279         case TYPE_DOUBLE:
1280                 sprintf(logtext + strlen(logtext), "->%g", d);
1281                 break;
1282         }
1283         log_text(logtext);
1284 }
1285
1286
1287 /****************************************************************************
1288                          SYNCHRONIZATION FUNCTIONS
1289 *****************************************************************************/
1290
1291 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1292 /*
1293  * Lock the mutex of an object.
1294  */
1295 void internal_lock_mutex_for_object(java_objectheader *object)
1296 {
1297         mutexHashEntry *entry;
1298         int hashValue;
1299
1300         assert(object != 0);
1301
1302         hashValue = MUTEX_HASH_VALUE(object);
1303         entry = &mutexHashTable[hashValue];
1304
1305         if (entry->object != 0) {
1306                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1307                         entry->object = 0;
1308                         entry->mutex.holder = 0;
1309                         entry->mutex.count = 0;
1310                         entry->mutex.muxWaiters = 0;
1311
1312                 } else {
1313                         while (entry->next != 0 && entry->object != object)
1314                                 entry = entry->next;
1315
1316                         if (entry->object != object) {
1317                                 entry->next = firstFreeOverflowEntry;
1318                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1319
1320                                 entry = entry->next;
1321                                 entry->object = 0;
1322                                 entry->next = 0;
1323                                 assert(entry->conditionCount == 0);
1324                         }
1325                 }
1326
1327         } else {
1328                 entry->mutex.holder = 0;
1329                 entry->mutex.count = 0;
1330                 entry->mutex.muxWaiters = 0;
1331         }
1332
1333         if (entry->object == 0)
1334                 entry->object = object;
1335         
1336         internal_lock_mutex(&entry->mutex);
1337 }
1338 #endif
1339
1340
1341 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1342 /*
1343  * Unlocks the mutex of an object.
1344  */
1345 void internal_unlock_mutex_for_object (java_objectheader *object)
1346 {
1347         int hashValue;
1348         mutexHashEntry *entry;
1349
1350         hashValue = MUTEX_HASH_VALUE(object);
1351         entry = &mutexHashTable[hashValue];
1352
1353         if (entry->object == object) {
1354                 internal_unlock_mutex(&entry->mutex);
1355
1356         } else {
1357                 while (entry->next != 0 && entry->next->object != object)
1358                         entry = entry->next;
1359
1360                 assert(entry->next != 0);
1361
1362                 internal_unlock_mutex(&entry->next->mutex);
1363
1364                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1365                         mutexHashEntry *unlinked = entry->next;
1366
1367                         entry->next = unlinked->next;
1368                         unlinked->next = firstFreeOverflowEntry;
1369                         firstFreeOverflowEntry = unlinked;
1370                 }
1371         }
1372 }
1373 #endif
1374
1375
1376 #if defined(USE_THREADS)
1377 void builtin_monitorenter(java_objectheader *o)
1378 {
1379 #if !defined(NATIVE_THREADS)
1380         int hashValue;
1381
1382         ++blockInts;
1383
1384         hashValue = MUTEX_HASH_VALUE(o);
1385         if (mutexHashTable[hashValue].object == o 
1386                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1387                 ++mutexHashTable[hashValue].mutex.count;
1388         else
1389                 internal_lock_mutex_for_object(o);
1390
1391         --blockInts;
1392 #else
1393         monitorEnter((threadobject *) THREADOBJECT, o);
1394 #endif
1395 }
1396 #endif
1397
1398
1399 #if defined(USE_THREADS)
1400 /*
1401  * Locks the class object - needed for static synchronized methods.
1402  * The use_class_as_object call is needed in order to circumvent a
1403  * possible deadlock with builtin_monitorenter called by another
1404  * thread calling use_class_as_object.
1405  */
1406 void builtin_staticmonitorenter(classinfo *c)
1407 {
1408         use_class_as_object(c);
1409         builtin_monitorenter(&c->header);
1410 }
1411 #endif
1412
1413
1414 #if defined(USE_THREADS)
1415 void *builtin_monitorexit(java_objectheader *o)
1416 {
1417 #if !defined(NATIVE_THREADS)
1418         int hashValue;
1419
1420         ++blockInts;
1421
1422         hashValue = MUTEX_HASH_VALUE(o);
1423         if (mutexHashTable[hashValue].object == o) {
1424                 if (mutexHashTable[hashValue].mutex.count == 1
1425                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1426                         internal_unlock_mutex_for_object(o);
1427                 else
1428                         --mutexHashTable[hashValue].mutex.count;
1429
1430         } else
1431                 internal_unlock_mutex_for_object(o);
1432
1433         --blockInts;
1434         return o;
1435 #else
1436         monitorExit((threadobject *) THREADOBJECT, o);
1437         return o;
1438 #endif
1439 }
1440 #endif
1441
1442
1443 /*****************************************************************************
1444                           MISCELLANEOUS HELPER FUNCTIONS
1445 *****************************************************************************/
1446
1447
1448
1449 /*********** Functions for integer divisions *****************************
1450  
1451         On some systems (eg. DEC ALPHA), integer division is not supported by the
1452         CPU. These helper functions implement the missing functionality.
1453
1454 ******************************************************************************/
1455
1456 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1457 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1458
1459
1460 /************** Functions for long arithmetics *******************************
1461
1462         On systems where 64 bit Integers are not supported by the CPU, these
1463         functions are needed.
1464
1465 ******************************************************************************/
1466
1467
1468 s8 builtin_ladd(s8 a, s8 b)
1469
1470 #if U8_AVAILABLE
1471         return a + b; 
1472 #else
1473         return builtin_i2l(0);
1474 #endif
1475 }
1476
1477 s8 builtin_lsub(s8 a, s8 b) 
1478
1479 #if U8_AVAILABLE
1480         return a - b; 
1481 #else
1482         return builtin_i2l(0);
1483 #endif
1484 }
1485
1486 s8 builtin_lmul(s8 a, s8 b) 
1487
1488 #if U8_AVAILABLE
1489         return a * b; 
1490 #else
1491         return builtin_i2l(0);
1492 #endif
1493 }
1494
1495 s8 builtin_ldiv(s8 a, s8 b) 
1496
1497 #if U8_AVAILABLE
1498         return a / b; 
1499 #else
1500         return builtin_i2l(0);
1501 #endif
1502 }
1503
1504 s8 builtin_lrem(s8 a, s8 b) 
1505
1506 #if U8_AVAILABLE
1507         return a % b; 
1508 #else
1509         return builtin_i2l(0);
1510 #endif
1511 }
1512
1513 s8 builtin_lshl(s8 a, s4 b) 
1514
1515 #if U8_AVAILABLE
1516         return a << (b & 63);
1517 #else
1518         return builtin_i2l(0);
1519 #endif
1520 }
1521
1522 s8 builtin_lshr(s8 a, s4 b) 
1523
1524 #if U8_AVAILABLE
1525         return a >> (b & 63);
1526 #else
1527         return builtin_i2l(0);
1528 #endif
1529 }
1530
1531 s8 builtin_lushr(s8 a, s4 b) 
1532
1533 #if U8_AVAILABLE
1534         return ((u8) a) >> (b & 63);
1535 #else
1536         return builtin_i2l(0);
1537 #endif
1538 }
1539
1540 s8 builtin_land(s8 a, s8 b) 
1541
1542 #if U8_AVAILABLE
1543         return a & b; 
1544 #else
1545         return builtin_i2l(0);
1546 #endif
1547 }
1548
1549 s8 builtin_lor(s8 a, s8 b) 
1550
1551 #if U8_AVAILABLE
1552         return a | b; 
1553 #else
1554         return builtin_i2l(0);
1555 #endif
1556 }
1557
1558 s8 builtin_lxor(s8 a, s8 b) 
1559
1560 #if U8_AVAILABLE
1561         return a ^ b; 
1562 #else
1563         return builtin_i2l(0);
1564 #endif
1565 }
1566
1567 s8 builtin_lneg(s8 a) 
1568
1569 #if U8_AVAILABLE
1570         return -a;
1571 #else
1572         return builtin_i2l(0);
1573 #endif
1574 }
1575
1576 s4 builtin_lcmp(s8 a, s8 b) 
1577
1578 #if U8_AVAILABLE
1579         if (a < b) return -1;
1580         if (a > b) return 1;
1581         return 0;
1582 #else
1583         return 0;
1584 #endif
1585 }
1586
1587
1588
1589
1590
1591 /*********** Functions for floating point operations *************************/
1592
1593 float builtin_fadd(float a, float b)
1594 {
1595         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1596         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1597         if (finitef(a)) {
1598                 if (finitef(b))
1599                         return a + b;
1600                 else
1601                         return b;
1602         }
1603         else {
1604                 if (finitef(b))
1605                         return a;
1606                 else {
1607                         if (copysignf(1.0, a) == copysignf(1.0, b))
1608                                 return a;
1609                         else
1610                                 return intBitsToFloat(FLT_NAN);
1611                 }
1612         }
1613 }
1614
1615
1616 float builtin_fsub(float a, float b)
1617 {
1618         return builtin_fadd(a, builtin_fneg(b));
1619 }
1620
1621
1622 float builtin_fmul(float a, float b)
1623 {
1624         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1625         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1626         if (finitef(a)) {
1627                 if (finitef(b)) return a * b;
1628                 else {
1629                         if (a == 0) return intBitsToFloat(FLT_NAN);
1630                         else return copysignf(b, copysignf(1.0, b)*a);
1631                 }
1632         }
1633         else {
1634                 if (finitef(b)) {
1635                         if (b == 0) return intBitsToFloat(FLT_NAN);
1636                         else return copysignf(a, copysignf(1.0, a)*b);
1637                 }
1638                 else {
1639                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1640                 }
1641         }
1642 }
1643
1644
1645 float builtin_fdiv(float a, float b)
1646 {
1647         if (finitef(a) && finitef(b)) {
1648                 if (b != 0)
1649                         return a / b;
1650                 else {
1651                         if (a > 0)
1652                                 return intBitsToFloat(FLT_POSINF);
1653                         else if (a < 0)
1654                                 return intBitsToFloat(FLT_NEGINF);
1655                 }
1656         }
1657         return intBitsToFloat(FLT_NAN);
1658 }
1659
1660
1661 float builtin_frem(float a, float b)
1662 {
1663         return fmodf(a, b);
1664 }
1665
1666
1667 float builtin_fneg(float a)
1668 {
1669         if (isnanf(a)) return a;
1670         else {
1671                 if (finitef(a)) return -a;
1672                 else return copysignf(a, -copysignf(1.0, a));
1673         }
1674 }
1675
1676
1677 s4 builtin_fcmpl(float a, float b)
1678 {
1679         if (isnanf(a)) return -1;
1680         if (isnanf(b)) return -1;
1681         if (!finitef(a) || !finitef(b)) {
1682                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1683                 b = finitef(b) ? 0 : copysignf(1.0, b);
1684         }
1685         if (a > b) return 1;
1686         if (a == b) return 0;
1687         return -1;
1688 }
1689
1690
1691 s4 builtin_fcmpg(float a, float b)
1692 {
1693         if (isnanf(a)) return 1;
1694         if (isnanf(b)) return 1;
1695         if (!finitef(a) || !finitef(b)) {
1696                 a = finitef(a) ? 0 : copysignf(1.0, a);
1697                 b = finitef(b) ? 0 : copysignf(1.0, b);
1698         }
1699         if (a > b) return 1;
1700         if (a == b) return 0;
1701         return -1;
1702 }
1703
1704
1705
1706 /************************* Functions for doubles ****************************/
1707
1708 double builtin_dadd(double a, double b)
1709 {
1710         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1711         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1712         if (finite(a)) {
1713                 if (finite(b)) return a + b;
1714                 else return b;
1715         }
1716         else {
1717                 if (finite(b)) return a;
1718                 else {
1719                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1720                         else return longBitsToDouble(DBL_NAN);
1721                 }
1722         }
1723 }
1724
1725
1726 double builtin_dsub(double a, double b)
1727 {
1728         return builtin_dadd(a, builtin_dneg(b));
1729 }
1730
1731
1732 double builtin_dmul(double a, double b)
1733 {
1734         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1735         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1736         if (finite(a)) {
1737                 if (finite(b)) return a * b;
1738                 else {
1739                         if (a == 0) return longBitsToDouble(DBL_NAN);
1740                         else return copysign(b, copysign(1.0, b) * a);
1741                 }
1742         }
1743         else {
1744                 if (finite(b)) {
1745                         if (b == 0) return longBitsToDouble(DBL_NAN);
1746                         else return copysign(a, copysign(1.0, a) * b);
1747                 }
1748                 else {
1749                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1750                 }
1751         }
1752 }
1753
1754
1755 double builtin_ddiv(double a, double b)
1756 {
1757         if (finite(a)) {
1758                 if (finite(b)) {
1759                         return a / b;
1760
1761                 } else {
1762                         if (isnan(b))
1763                                 return longBitsToDouble(DBL_NAN);
1764                         else
1765                                 return copysign(0.0, b);
1766                 }
1767
1768         } else {
1769                 if (finite(b)) {
1770                         if (a > 0)
1771                                 return longBitsToDouble(DBL_POSINF);
1772                         else if (a < 0)
1773                                 return longBitsToDouble(DBL_NEGINF);
1774
1775                 } else
1776                         return longBitsToDouble(DBL_NAN);
1777         }
1778
1779 /*      if (finite(a) && finite(b)) { */
1780 /*              if (b != 0) */
1781 /*                      return a / b; */
1782 /*              else { */
1783 /*                      if (a > 0) */
1784 /*                              return longBitsToDouble(DBL_POSINF); */
1785 /*                      else if (a < 0) */
1786 /*                              return longBitsToDouble(DBL_NEGINF); */
1787 /*              } */
1788 /*      } */
1789
1790         /* keep compiler happy */
1791         return 0;
1792 }
1793
1794
1795 double builtin_drem(double a, double b)
1796 {
1797         return fmod(a, b);
1798 }
1799
1800
1801 double builtin_dneg(double a)
1802 {
1803         if (isnan(a)) return a;
1804         else {
1805                 if (finite(a)) return -a;
1806                 else return copysign(a, -copysign(1.0, a));
1807         }
1808 }
1809
1810
1811 s4 builtin_dcmpl(double a, double b)
1812 {
1813         if (isnan(a)) return -1;
1814         if (isnan(b)) return -1;
1815         if (!finite(a) || !finite(b)) {
1816                 a = finite(a) ? 0 : copysign(1.0, a);
1817                 b = finite(b) ? 0 : copysign(1.0, b);
1818         }
1819         if (a > b) return 1;
1820         if (a == b) return 0;
1821         return -1;
1822 }
1823
1824
1825 s4 builtin_dcmpg(double a, double b)
1826 {
1827         if (isnan(a)) return 1;
1828         if (isnan(b)) return 1;
1829         if (!finite(a) || !finite(b)) {
1830                 a = finite(a) ? 0 : copysign(1.0, a);
1831                 b = finite(b) ? 0 : copysign(1.0, b);
1832         }
1833         if (a > b) return 1;
1834         if (a == b) return 0;
1835         return -1;
1836 }
1837
1838
1839 /*********************** Conversion operations ****************************/
1840
1841 s8 builtin_i2l(s4 i)
1842 {
1843 #if U8_AVAILABLE
1844         return i;
1845 #else
1846         s8 v;
1847         v.high = 0;
1848         v.low = i;
1849         return v;
1850 #endif
1851 }
1852
1853
1854 float builtin_i2f(s4 a)
1855 {
1856         float f = (float) a;
1857         return f;
1858 }
1859
1860
1861 double builtin_i2d(s4 a)
1862 {
1863         double d = (double) a;
1864         return d;
1865 }
1866
1867
1868 s4 builtin_l2i(s8 l)
1869 {
1870 #if U8_AVAILABLE
1871         return (s4) l;
1872 #else
1873         return l.low;
1874 #endif
1875 }
1876
1877
1878 float builtin_l2f(s8 a)
1879 {
1880 #if U8_AVAILABLE
1881         float f = (float) a;
1882         return f;
1883 #else
1884         return 0.0;
1885 #endif
1886 }
1887
1888
1889 double builtin_l2d(s8 a)
1890 {
1891 #if U8_AVAILABLE
1892         double d = (double) a;
1893         return d;
1894 #else
1895         return 0.0;
1896 #endif
1897 }
1898
1899
1900 s4 builtin_f2i(float a) 
1901 {
1902
1903         return builtin_d2i((double) a);
1904
1905         /*      float f;
1906         
1907                 if (isnanf(a))
1908                 return 0;
1909                 if (finitef(a)) {
1910                 if (a > 2147483647)
1911                 return 2147483647;
1912                 if (a < (-2147483648))
1913                 return (-2147483648);
1914                 return (s4) a;
1915                 }
1916                 f = copysignf((float) 1.0, a);
1917                 if (f > 0)
1918                 return 2147483647;
1919                 return (-2147483648); */
1920 }
1921
1922
1923 s8 builtin_f2l(float a)
1924 {
1925
1926         return builtin_d2l((double) a);
1927
1928         /*      float f;
1929         
1930                 if (finitef(a)) {
1931                 if (a > 9223372036854775807L)
1932                 return 9223372036854775807L;
1933                 if (a < (-9223372036854775808L))
1934                 return (-9223372036854775808L);
1935                 return (s8) a;
1936                 }
1937                 if (isnanf(a))
1938                 return 0;
1939                 f = copysignf((float) 1.0, a);
1940                 if (f > 0)
1941                 return 9223372036854775807L;
1942                 return (-9223372036854775808L); */
1943 }
1944
1945
1946 double builtin_f2d(float a)
1947 {
1948         if (finitef(a)) return (double) a;
1949         else {
1950                 if (isnanf(a))
1951                         return longBitsToDouble(DBL_NAN);
1952                 else
1953                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1954         }
1955 }
1956
1957
1958 s4 builtin_d2i(double a) 
1959
1960         double d;
1961         
1962         if (finite(a)) {
1963                 if (a >= 2147483647)
1964                         return 2147483647;
1965                 if (a <= (-2147483647-1))
1966                         return (-2147483647-1);
1967                 return (s4) a;
1968         }
1969         if (isnan(a))
1970                 return 0;
1971         d = copysign(1.0, a);
1972         if (d > 0)
1973                 return 2147483647;
1974         return (-2147483647-1);
1975 }
1976
1977
1978 s8 builtin_d2l(double a)
1979 {
1980         double d;
1981         
1982         if (finite(a)) {
1983                 if (a >= 9223372036854775807LL)
1984                         return 9223372036854775807LL;
1985                 if (a <= (-9223372036854775807LL-1))
1986                         return (-9223372036854775807LL-1);
1987                 return (s8) a;
1988         }
1989         if (isnan(a))
1990                 return 0;
1991         d = copysign(1.0, a);
1992         if (d > 0)
1993                 return 9223372036854775807LL;
1994         return (-9223372036854775807LL-1);
1995 }
1996
1997
1998 float builtin_d2f(double a)
1999 {
2000         if (finite(a))
2001                 return (float) a;
2002         else {
2003                 if (isnan(a))
2004                         return intBitsToFloat(FLT_NAN);
2005                 else
2006                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2007         }
2008 }
2009
2010
2011 /* used to convert FLT_xxx defines into float values */
2012
2013 inline float intBitsToFloat(s4 i)
2014 {
2015         imm_union imb;
2016
2017         imb.i = i;
2018         return imb.f;
2019 }
2020
2021
2022 /* used to convert DBL_xxx defines into double values */
2023
2024 inline float longBitsToDouble(s8 l)
2025 {
2026         imm_union imb;
2027
2028         imb.l = l;
2029         return imb.d;
2030 }
2031
2032
2033 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2034 {
2035         return (java_arrayheader *)
2036                 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2037 }
2038
2039
2040 s4 builtin_dummy()
2041 {
2042         panic("Internal error: builtin_dummy called (native function is missing)");
2043         return 0; /* for the compiler */
2044 }
2045
2046
2047 /* builtin_asm_get_exceptionptrptr *********************************************
2048
2049    this is a wrapper for calls from asmpart
2050
2051 *******************************************************************************/
2052
2053 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2054 java_objectheader **builtin_asm_get_exceptionptrptr()
2055 {
2056         return builtin_get_exceptionptrptr();
2057 }
2058 #endif
2059
2060
2061 methodinfo *builtin_asm_get_threadrootmethod()
2062 {
2063         return *threadrootmethod;
2064 }
2065
2066
2067 inline void* builtin_asm_get_stackframeinfo()
2068 {
2069 /*log_text("builtin_asm_get_stackframeinfo()");*/
2070 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2071         return &THREADINFO->_stackframeinfo;
2072 #else
2073 #if defined(__GNUC__)
2074 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2075 #endif
2076                 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2077 #endif
2078 }
2079
2080 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2081 /*      stacktraceelement *el;*/
2082         size_t s;
2083         s=(end-begin);
2084         /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2085         *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2086 #if 0
2087         *el=MNEW(stacktraceelement,s+1); /*GC*/
2088 #endif
2089         memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2090         (*el)[s].method=0;
2091 #if defined(__GNUC__)
2092 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2093 #endif
2094         (*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 */
2095         return *el;
2096 }
2097
2098 /*
2099  * These are local overrides for various environment variables in Emacs.
2100  * Please do not remove this and leave it at the end of the file, where
2101  * Emacs will automagically detect them.
2102  * ---------------------------------------------------------------------
2103  * Local variables:
2104  * mode: c
2105  * indent-tabs-mode: t
2106  * c-basic-offset: 4
2107  * tab-width: 4
2108  * End:
2109  */