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