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