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