Native threads
[cacao.git] / src / vm / builtin.c
1 /* builtin.c - functions for unsupported operations
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
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    Contains C functions for JavaVM Instructions that cannot be
32    translated to machine language directly. Consequently, the
33    generated machine code for these instructions contains function
34    calls instead of machine instructions, using the C calling
35    convention.
36
37    $Id: builtin.c 851 2004-01-05 23:59:28Z stefan $
38
39 */
40
41
42 #include <assert.h>
43 #include <string.h>
44 #include <math.h>
45 #include "main.h"
46 #include "global.h"
47 #include "builtin.h"
48 #include "native.h"
49 #include "loader.h"
50 #include "tables.h"
51 #include "asmpart.h"
52 #include "mm/boehm.h"
53 #include "threads/thread.h"
54 #include "threads/locks.h"
55 #include "toolbox/loging.h"
56 #include "toolbox/memory.h"
57 #include "nat/java_lang_Cloneable.h"
58 #include "nat/java_lang_VMObject.h"
59
60
61 #undef DEBUG /*define DEBUG 1*/
62
63 /* XXX delete? */
64 #if 0
65 builtin_descriptor builtin_desc[] = {
66         {(functionptr) builtin_instanceof,                 "instanceof"},
67         {(functionptr) builtin_checkcast,                  "checkcast"},
68         {(functionptr) asm_builtin_checkcast,      "checkcast"},
69         {(functionptr) builtin_arrayinstanceof,    "arrayinstanceof"},
70 #if defined(__I386__)
71         {(functionptr) asm_builtin_arrayinstanceof,"arrayinstanceof"},
72 #endif
73         {(functionptr) builtin_checkarraycast,     "checkarraycast"},
74         {(functionptr) asm_builtin_checkarraycast, "checkarraycast"},
75         {(functionptr) asm_builtin_aastore,                "aastore"},
76         {(functionptr) builtin_new,                                "new"},
77         {(functionptr) builtin_newarray,       "newarray"},
78         {(functionptr) builtin_anewarray,          "anewarray"},
79 #if defined(__I386__)
80         /*
81          * have 2 parameters (needs stack manipulation)
82          */
83         {(functionptr) asm_builtin_newarray,       "newarray"},
84 #endif
85         {(functionptr) builtin_newarray_boolean,   "newarray_boolean"},
86         {(functionptr) builtin_newarray_char,      "newarray_char"},
87         {(functionptr) builtin_newarray_float,     "newarray_float"},
88         {(functionptr) builtin_newarray_double,    "newarray_double"},
89         {(functionptr) builtin_newarray_byte,      "newarray_byte"},
90         {(functionptr) builtin_newarray_short,     "newarray_short"},
91         {(functionptr) builtin_newarray_int,       "newarray_int"},
92         {(functionptr) builtin_newarray_long,      "newarray_long"},
93         {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
94         {(functionptr) builtin_displaymethodstop,  "displaymethodstop"},
95         {(functionptr) builtin_monitorenter,       "monitorenter"},
96         {(functionptr) asm_builtin_monitorenter,   "monitorenter"},
97         {(functionptr) builtin_monitorexit,                "monitorexit"},
98         {(functionptr) asm_builtin_monitorexit,    "monitorexit"},
99 #if !SUPPORT_DIVISION
100         {(functionptr) builtin_idiv,                       "idiv"},
101         {(functionptr) asm_builtin_idiv,                   "idiv"},
102         {(functionptr) builtin_irem,                       "irem"},
103         {(functionptr) asm_builtin_irem,                   "irem"},
104 #endif
105         {(functionptr) builtin_ladd,                       "ladd"},
106         {(functionptr) builtin_lsub,                       "lsub"},
107         {(functionptr) builtin_lmul,                       "lmul"},
108 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
109         {(functionptr) builtin_ldiv,                       "ldiv"},
110         {(functionptr) asm_builtin_ldiv,                   "ldiv"},
111         {(functionptr) builtin_lrem,                       "lrem"},
112         {(functionptr) asm_builtin_lrem,                   "lrem"},
113 #endif
114         {(functionptr) builtin_lshl,                       "lshl"},
115         {(functionptr) builtin_lshr,                       "lshr"},
116         {(functionptr) builtin_lushr,                      "lushr"},
117         {(functionptr) builtin_land,                       "land"},
118         {(functionptr) builtin_lor,                                "lor"},
119         {(functionptr) builtin_lxor,                       "lxor"},
120         {(functionptr) builtin_lneg,                       "lneg"},
121         {(functionptr) builtin_lcmp,                       "lcmp"},
122         {(functionptr) builtin_fadd,                       "fadd"},
123         {(functionptr) builtin_fsub,                       "fsub"},
124         {(functionptr) builtin_fmul,                       "fmul"},
125         {(functionptr) builtin_fdiv,                       "fdiv"},
126         {(functionptr) builtin_frem,                       "frem"},
127         {(functionptr) builtin_fneg,                       "fneg"},
128         {(functionptr) builtin_fcmpl,                      "fcmpl"},
129         {(functionptr) builtin_fcmpg,                      "fcmpg"},
130         {(functionptr) builtin_dadd,                       "dadd"},
131         {(functionptr) builtin_dsub,                       "dsub"},
132         {(functionptr) builtin_dmul,                       "dmul"},
133         {(functionptr) builtin_ddiv,                       "ddiv"},
134         {(functionptr) builtin_drem,                       "drem"},
135         {(functionptr) builtin_dneg,                       "dneg"},
136         {(functionptr) builtin_dcmpl,                      "dcmpl"},
137         {(functionptr) builtin_dcmpg,                      "dcmpg"},
138         {(functionptr) builtin_i2l,                                "i2l"},
139         {(functionptr) builtin_i2f,                                "i2f"},
140         {(functionptr) builtin_i2d,                                "i2d"},
141         {(functionptr) builtin_l2i,                                "l2i"},
142         {(functionptr) builtin_l2f,                                "l2f"},
143         {(functionptr) builtin_l2d,                                "l2d"},
144         {(functionptr) builtin_f2i,                                "f2i"},
145         {(functionptr) builtin_f2l,                                "f2l"},
146         {(functionptr) builtin_f2d,                                "f2d"},
147         {(functionptr) builtin_d2i,                                "d2i"},
148         {(functionptr) builtin_d2l,                                "d2l"},
149 #if defined(__I386__)
150         {(functionptr) asm_builtin_f2i,                    "f2i"},
151         {(functionptr) asm_builtin_f2l,                    "f2l"},
152         {(functionptr) asm_builtin_d2i,                    "d2i"},
153         {(functionptr) asm_builtin_d2l,                    "d2l"},
154 #endif
155         {(functionptr) builtin_d2f,                                "d2f"},
156         {(functionptr) NULL,                                       "unknown"}
157 };
158 #endif
159
160
161 /*****************************************************************************
162                                                                 TYPE CHECKS
163 *****************************************************************************/
164
165
166
167 /*************** internal function: builtin_isanysubclass *********************
168
169         Checks a subclass relation between two classes. Implemented interfaces
170         are interpreted as super classes.
171         Return value:  1 ... sub is subclass of super
172                                    0 ... otherwise
173                                         
174 *****************************************************************************/                                  
175 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
176
177         s4 res;
178
179         /*classinfo *tmp;*/
180         if (super->flags & ACC_INTERFACE)
181                 return (sub->vftbl->interfacetablelength > super->index) &&
182                         (sub->vftbl->interfacetable[-super->index] != NULL);
183
184         /*
185           while (sub != 0)
186           if (sub == super)
187           return 1;
188           else
189           sub = sub->super;
190
191           return 0;
192         */
193
194 /*
195         for (tmp=sub;tmp!=0;tmp=tmp->super) {
196                 printf("->");
197                 utf_display(tmp->name);
198         }
199                 printf("\n\n");
200         
201         for (tmp=super;tmp!=0;tmp=tmp->super) {
202                 printf("->");
203                 utf_display(tmp->name);
204         }
205                 printf("\n");
206         
207
208         printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
209                         sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
210                         super->vftbl->diffval); */
211
212 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
213         cast_lock();
214 #endif
215
216         res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
217                 (unsigned) (super->vftbl->diffval);
218
219 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
220         cast_unlock();
221 #endif
222
223         return res;
224 }
225
226 /* XXX inline this? */
227 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
228 {
229         int base;
230         s4 res;
231         
232 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
233         cast_lock();
234 #endif
235
236         if ((base = super->baseval) <= 0)
237                 /* super is an interface */
238                 res = (sub->interfacetablelength > -base) &&
239                         (sub->interfacetable[base] != NULL);
240         else
241             res = (unsigned) (sub->baseval - base)
242                         <= (unsigned) (super->diffval);
243
244 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
245         cast_unlock();
246 #endif
247
248         return res;
249 }
250
251
252 /****************** function: builtin_instanceof *****************************
253
254         Checks if an object is an instance of some given class (or subclass of
255         that class). If class is an interface, checks if the interface is
256         implemented.
257         Return value:  1 ... obj is an instance of class or implements the interface
258                                    0 ... otherwise or if obj == NULL
259                          
260 *****************************************************************************/
261
262 /* XXX should use vftbl */
263 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
264 {
265 #ifdef DEBUG
266         log_text ("builtin_instanceof called");
267 #endif  
268         if (!obj) return 0;
269         return builtin_isanysubclass (obj->vftbl->class, class);
270 }
271
272
273
274 /**************** function: builtin_checkcast *******************************
275
276         The same as builtin_instanceof except that 1 is returned when
277         obj == NULL
278                           
279 ****************************************************************************/
280
281 /* XXX should use vftbl */
282 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
283 {
284 #ifdef DEBUG
285         log_text("builtin_checkcast called");
286 #endif
287
288         if (obj == NULL)
289                 return 1;
290         if (builtin_isanysubclass(obj->vftbl->class, class))
291                 return 1;
292
293 #if DEBUG
294         printf("#### checkcast failed ");
295         utf_display(obj->vftbl->class->name);
296         printf(" -> ");
297         utf_display(class->name);
298         printf("\n");
299 #endif
300
301         return 0;
302 }
303
304
305 /*********** internal function: builtin_descriptorscompatible ******************
306
307         Checks if two array type descriptors are assignment compatible
308         Return value:  1 ... target = desc is possible
309                                    0 ... otherwise
310                         
311 ******************************************************************************/
312
313 /* XXX inline this? */
314 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
315 {
316         if (desc==target) return 1;
317         if (desc->arraytype != target->arraytype) return 0;
318         if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
319         
320         /* {both arrays are arrays of references} */
321         if (desc->dimension == target->dimension)
322                 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
323         if (desc->dimension < target->dimension) return 0;
324
325         /* {desc has higher dimension than target} */
326         return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
327 }
328
329
330 /******************** function: builtin_checkarraycast ***********************
331
332         Checks if an object is really a subtype of the requested array type.
333         The object has to be an array to begin with. For simple arrays (int, short,
334         double, etc.) the types have to match exactly.
335         For arrays of objects, the type of elements in the array has to be a
336         subtype (or the same type) of the requested element type. For arrays of
337         arrays (which in turn can again be arrays of arrays), the types at the
338         lowest level have to satisfy the corresponding sub class relation.
339         
340         Return value:  1 ... cast is possible
341                                    0 ... otherwise
342         
343         ATTENTION: a cast with a NULL pointer is always possible.
344                         
345 *****************************************************************************/
346
347 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
348 {
349         arraydescriptor *desc;
350         
351         if (!o) return 1;
352         if ((desc = o->vftbl->arraydesc) == NULL) return 0;
353
354         return builtin_descriptorscompatible(desc, target->arraydesc);
355 }
356
357
358 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
359 {
360         if (!obj) return 1;
361         return builtin_checkarraycast(obj, target);
362 }
363
364
365 /************************** exception functions *******************************
366
367 ******************************************************************************/
368
369 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
370 {
371         if (verbose) {
372                 char logtext[MAXLOGTEXT];
373                 sprintf(logtext, "Builtin exception thrown: ");
374                 if (local_exceptionptr)
375                         utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
376                 else {
377                         sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
378                         if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
379                         if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
380                         if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
381                         if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
382                         if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
383                         if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
384                         if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
385                         if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
386                         if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
387                         if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
388                         }
389                 log_text(logtext);
390         }
391         exceptionptr = local_exceptionptr;
392         return local_exceptionptr;
393 }
394
395 java_objectheader *builtin_get_exceptionptr()
396 {
397 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
398 #ifdef HAVE___THREAD
399         return exceptionptr;
400 #else
401         pthread_getspecific(tkey_exceptionptr);
402 #endif
403 #else
404         panic("builtin_get_exceptionptr should not be used in this configuration");
405         return NULL;
406 #endif
407 }
408
409 void builtin_set_exceptionptr(java_objectheader *e)
410 {
411 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
412 #ifdef HAVE___THREAD
413         exceptionptr = e;
414 #else
415         pthread_setspecific(tkey_exceptionptr, e);
416 #endif
417 #else
418         panic("builtin_set_exceptionptr should not be used in this configuration");
419 #endif
420 }
421
422
423 /******************* function: builtin_canstore *******************************
424
425         Checks, if an object can be stored in an array.
426         Return value:  1 ... possible
427                                    0 ... otherwise
428
429 ******************************************************************************/
430
431 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
432 {
433         arraydescriptor *desc;
434         arraydescriptor *valuedesc;
435         vftbl *componentvftbl;
436         vftbl *valuevftbl;
437     int dim_m1;
438         int base;
439         
440         if (!o) return 1;
441
442         /* The following is guaranteed (by verifier checks):
443          *
444          *     *) a->...vftbl->arraydesc != NULL
445          *     *) a->...vftbl->arraydesc->componentvftbl != NULL
446          *     *) o->vftbl is not an interface vftbl
447          */
448         
449         desc = a->header.objheader.vftbl->arraydesc;
450     componentvftbl = desc->componentvftbl;
451         valuevftbl = o->vftbl;
452
453     if ((dim_m1 = desc->dimension - 1) == 0) {
454                 s4 res;
455
456                 /* {a is a one-dimensional array} */
457                 /* {a is an array of references} */
458                 
459                 if (valuevftbl == componentvftbl)
460                         return 1;
461
462                 if ((base = componentvftbl->baseval) <= 0)
463                         /* an array of interface references */
464                         return (valuevftbl->interfacetablelength > -base &&
465                                         valuevftbl->interfacetable[base] != NULL);
466                 
467 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
468                 cast_lock();
469 #endif
470
471                 res = (unsigned)(valuevftbl->baseval - base)
472                         <= (unsigned)(componentvftbl->diffval);
473
474 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
475                 cast_unlock();
476 #endif
477
478                 return res;
479     }
480     /* {a has dimension > 1} */
481         /* {componentvftbl->arraydesc != NULL} */
482
483         /* check if o is an array */
484         if ((valuedesc = valuevftbl->arraydesc) == NULL)
485                 return 0;
486         /* {o is an array} */
487
488         return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
489 }
490
491
492 /* This is an optimized version where a is guaranteed to be one-dimensional */
493 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
494 {
495         arraydescriptor *desc;
496         vftbl *elementvftbl;
497         vftbl *valuevftbl;
498         int base;
499         s4 res;
500         
501         if (!o) return 1;
502
503         /* The following is guaranteed (by verifier checks):
504          *
505          *     *) a->...vftbl->arraydesc != NULL
506          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
507          *     *) a->...vftbl->arraydesc->dimension == 1
508          *     *) o->vftbl is not an interface vftbl
509          */
510
511         desc = a->header.objheader.vftbl->arraydesc;
512     elementvftbl = desc->elementvftbl;
513         valuevftbl = o->vftbl;
514
515         /* {a is a one-dimensional array} */
516         
517         if (valuevftbl == elementvftbl)
518                 return 1;
519
520         if ((base = elementvftbl->baseval) <= 0)
521                 /* an array of interface references */
522                 return (valuevftbl->interfacetablelength > -base &&
523                                 valuevftbl->interfacetable[base] != NULL);
524         
525 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
526         cast_lock();
527 #endif
528
529         res = (unsigned)(valuevftbl->baseval - base)
530                 <= (unsigned)(elementvftbl->diffval);
531
532 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
533         cast_unlock();
534 #endif
535
536         return res;
537 }
538
539
540 /* This is an optimized version where a is guaranteed to be a
541  * one-dimensional array of a class type */
542 /* XXX this could be inlined by the code generator */
543 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
544 {
545         vftbl *elementvftbl;
546         vftbl *valuevftbl;
547         s4 res;
548         
549         if (!o) return 1;
550
551         /* The following is guaranteed (by verifier checks):
552          *
553          *     *) a->...vftbl->arraydesc != NULL
554          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
555          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
556          *     *) a->...vftbl->arraydesc->dimension == 1
557          *     *) o->vftbl is not an interface vftbl
558          */
559
560     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
561         valuevftbl = o->vftbl;
562
563         /* {a is a one-dimensional array} */
564         
565         if (valuevftbl == elementvftbl)
566                 return 1;
567
568 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
569         cast_lock();
570 #endif
571
572         res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
573                 <= (unsigned)(elementvftbl->diffval);
574
575 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
576         cast_unlock();
577 #endif
578
579         return res;
580 }
581
582
583 /******************** Function: builtin_new **********************************
584
585         Creates a new instance of class c on the heap.
586         Return value:  pointer to the object or NULL if no memory is
587                                    available
588                         
589 *****************************************************************************/
590
591 #define ALIGNMENT 3
592 #define align_size(size)        ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
593
594 java_objectheader *builtin_new(classinfo *c)
595 {
596         java_objectheader *o;
597
598         class_init(c);
599
600 #ifdef SIZE_FROM_CLASSINFO
601         c->alignedsize = align_size(c->instancesize);
602         o = heap_allocate(c->alignedsize, true, c->finalizer);
603 #else
604         o = heap_allocate(c->instancesize, true, c->finalizer);
605 #endif
606         if (!o) return NULL;
607         
608         memset(o, 0, c->instancesize);
609
610         o->vftbl = c->vftbl;
611
612         return o;
613 }
614
615 /********************** Function: builtin_newarray **************************
616
617         Creates an array with the given vftbl on the heap.
618
619         Return value:  pointer to the array or NULL if no memory is available
620
621     CAUTION: The given vftbl must be the vftbl of the *array* class,
622     not of the element class.
623
624 *****************************************************************************/
625
626 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
627 {
628         java_arrayheader *a;
629         arraydescriptor *desc = arrayvftbl->arraydesc;
630         s4 dataoffset = desc->dataoffset;
631         s4 componentsize = desc->componentsize;
632         s4 actualsize;
633
634         if (size<0) {
635                 exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
636                 return NULL;
637         }
638 #ifdef SIZE_FROM_CLASSINFO
639         actualsize = align_size(dataoffset + size * componentsize);
640 #else
641         actualsize = dataoffset + size * componentsize;
642 #endif
643
644         if (((u4)actualsize)<((u4)size)) { /* overflow */
645                 exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
646                 return NULL;
647         }
648         a = heap_allocate(actualsize,
649                                           (desc->arraytype == ARRAYTYPE_OBJECT),
650                                           NULL);
651
652         if (!a) return NULL;
653         memset(a, 0, actualsize);
654
655
656         /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
657
658         a->objheader.vftbl = arrayvftbl;
659         a->size = size;
660 #ifdef SIZE_FROM_CLASSINFO
661         a->alignedsize = actualsize;
662 #endif
663
664         return a;
665 }
666
667
668 /********************** Function: builtin_anewarray *************************
669
670         Creates an array of references to the given class type on the heap.
671
672         Return value:  pointer to the array or NULL if no memory is available
673
674     XXX This function does not do The Right Thing, because it uses a
675     classinfo pointer at runtime. builtin_newarray should be used
676     instead.
677
678 *****************************************************************************/
679
680 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
681 {
682         return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
683 }
684
685
686 /******************** Function: builtin_newarray_int ***********************
687
688         Creates an array of 32 bit Integers on the heap.
689
690         Return value:  pointer to the array or NULL if no memory is available
691
692 *****************************************************************************/
693
694 java_intarray *builtin_newarray_int(s4 size)
695 {
696         return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
697 }
698
699
700 /******************** Function: builtin_newarray_long ***********************
701
702         Creates an array of 64 bit Integers on the heap.
703
704         Return value:  pointer to the array or NULL if no memory is available
705
706 *****************************************************************************/
707
708 java_longarray *builtin_newarray_long(s4 size)
709 {
710         return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
711 }
712
713
714 /******************** function: builtin_newarray_float ***********************
715
716         Creates an array of 32 bit IEEE floats on the heap.
717
718         Return value:  pointer to the array or NULL if no memory is available
719
720 *****************************************************************************/
721
722 java_floatarray *builtin_newarray_float(s4 size)
723 {
724         return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
725 }
726
727
728 /******************** function: builtin_newarray_double ***********************
729
730         Creates an array of 64 bit IEEE floats on the heap.
731
732         Return value:  pointer to the array or NULL if no memory is available
733
734 *****************************************************************************/
735
736 java_doublearray *builtin_newarray_double(s4 size)
737 {
738         return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
739 }
740
741
742 /******************** function: builtin_newarray_byte ***********************
743
744         Creates an array of 8 bit Integers on the heap.
745
746         Return value:  pointer to the array or NULL if no memory is available
747
748 *****************************************************************************/
749
750 java_bytearray *builtin_newarray_byte(s4 size)
751 {
752         return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
753 }
754
755
756 /******************** function: builtin_newarray_char ************************
757
758         Creates an array of characters on the heap.
759
760         Return value:  pointer to the array or NULL if no memory is available
761
762 *****************************************************************************/
763
764 java_chararray *builtin_newarray_char(s4 size)
765 {
766         return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
767 }
768
769
770 /******************** function: builtin_newarray_short ***********************
771
772         Creates an array of 16 bit Integers on the heap.
773
774         Return value:  pointer to the array or NULL if no memory is available
775
776 *****************************************************************************/
777
778 java_shortarray *builtin_newarray_short(s4 size)
779 {
780         return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
781 }
782
783
784 /******************** function: builtin_newarray_boolean ************************
785
786         Creates an array of bytes on the heap. The array is designated as an array
787         of booleans (important for casts)
788         
789         Return value:  pointer to the array or NULL if no memory is available
790
791 *****************************************************************************/
792
793 java_booleanarray *builtin_newarray_boolean(s4 size)
794 {
795         return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
796 }
797
798
799 /**************** function: builtin_nmultianewarray ***************************
800
801         Creates a multi-dimensional array on the heap. The dimensions are passed in
802         an array of longs.
803
804     Arguments:
805         n............number of dimensions to create
806         arrayvftbl...vftbl of the array class
807         dims.........array containing the size of each dimension to create
808
809         Return value:  pointer to the array or NULL if no memory is available
810
811 ******************************************************************************/
812
813         /* Helper functions */
814
815 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
816 {
817         int size, i;
818         java_arrayheader *a;
819         vftbl *componentvftbl;
820
821         /* create this dimension */
822         size = (int) dims[0];
823         a = builtin_newarray(size,arrayvftbl);
824         if (!a) return NULL;
825
826         /* if this is the last dimension return */
827         if (!--n) return a;
828
829         /* get the vftbl of the components to create */
830         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
831         if (!componentvftbl) /* XXX the verifier could check this */
832                 panic ("multianewarray with too many dimensions");
833
834         /* create the component arrays */
835         for (i = 0; i < size; i++) {
836                 java_arrayheader *ea = 
837                         builtin_nmultianewarray(n,componentvftbl,dims+1);
838                 if (!ea) return NULL;
839                 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
840         }
841
842         return a;
843 }
844
845
846 /*****************************************************************************
847                                           METHOD LOGGING
848
849         Various functions for printing a message at method entry or exit (for
850         debugging)
851         
852 *****************************************************************************/
853
854
855 u4 methodindent = 0;
856
857 java_objectheader *builtin_trace_exception(java_objectheader *exceptionptr,
858                                                                                    methodinfo *method, int *pos, 
859                                                                                    int noindent)
860 {
861         if (!noindent) {
862                 if (methodindent)
863                         methodindent--;
864                 else
865                         log_text("WARNING: unmatched methodindent--");
866         }
867         if (verbose || runverbose) {
868                 printf("Exception ");
869                 if (exceptionptr) {
870                         utf_display (exceptionptr->vftbl->class->name);
871                 }
872                 else {
873                         printf("Error: <Nullpointer instead of exception>");
874                         if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
875                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
876                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
877                         if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
878                         if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
879                         if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
880                         if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
881                         if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
882                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
883                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
884
885                 }
886                 printf(" thrown in ");
887                 if (method) {
888                         utf_display (method->class->name);
889                         printf(".");
890                         utf_display (method->name);
891                         if (method->flags & ACC_SYNCHRONIZED)
892                                 printf("(SYNC)");
893                         else
894                                 printf("(NOSYNC)");
895                         printf("(%p) at position %p\n", method->entrypoint, pos);
896                 }
897                 else
898                         printf("call_java_method\n");
899                 fflush (stdout);
900         }
901         return exceptionptr;
902 }
903
904
905 #ifdef TRACE_ARGS_NUM
906 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
907 #if TRACE_ARGS_NUM > 6
908                                                 s8 a6, s8 a7,
909 #endif
910                                                 methodinfo *method)
911 {
912         int i;
913         char logtext[MAXLOGTEXT];
914         for (i = 0; i < methodindent; i++)
915                 logtext[i] = '\t';
916         sprintf(logtext + methodindent, "called: ");
917         utf_sprint(logtext + strlen(logtext), method->class->name);
918         sprintf(logtext + strlen(logtext), ".");
919         utf_sprint(logtext + strlen(logtext), method->name);
920         utf_sprint(logtext + strlen(logtext), method->descriptor);
921         sprintf(logtext + strlen(logtext), "(");
922
923         switch (method->paramcount) {
924         case 0:
925                 break;
926
927 #if defined(__I386__)
928         case 1:
929                 sprintf(logtext+strlen(logtext), "%llx", a0);
930                 break;
931
932         case 2:
933                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
934                 break;
935
936         case 3:
937                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
938                 break;
939
940         case 4:
941                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
942                                 a0,   a1,   a2,   a3);
943                 break;
944
945         case 5:
946                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
947                                 a0,   a1,   a2,   a3,   a4);
948                 break;
949
950         case 6:
951                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
952                                 a0,   a1,   a2,   a3,   a4,   a5);
953                 break;
954
955 #if TRACE_ARGS_NUM > 6
956         case 7:
957                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
958                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
959                 break;
960
961         case 8:
962                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
963                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
964                 break;
965
966         default:
967                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
968                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   method->paramcount - 8);
969                 break;
970 #else
971         default:
972                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
973                                 a0,   a1,   a2,   a3,   a4,   a5,   method->paramcount - 6);
974                 break;
975 #endif
976 #else
977         case 1:
978                 sprintf(logtext+strlen(logtext), "%lx", a0);
979                 break;
980
981         case 2:
982                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
983                 break;
984
985         case 3:
986                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
987                 break;
988
989         case 4:
990                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
991                                 a0,  a1,  a2,  a3);
992                 break;
993
994         case 5:
995                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
996                                 a0,  a1,  a2,  a3,  a4);
997                 break;
998
999         case 6:
1000                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1001                                 a0,  a1,  a2,  a3,  a4,  a5);
1002                 break;
1003
1004 #if TRACE_ARGS_NUM > 6
1005         case 7:
1006                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1007                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
1008                 break;
1009
1010         case 8:
1011                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1012                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
1013                 break;
1014
1015         default:
1016                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1017                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  method->paramcount - 8);
1018                 break;
1019 #else
1020         default:
1021                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1022                                 a0,  a1,  a2,  a3,  a4,  a5,   method->paramcount - 6);
1023                 break;
1024 #endif
1025 #endif
1026         }
1027         sprintf (logtext+strlen(logtext), ")");
1028         log_text(logtext);
1029
1030         methodindent++;
1031 }
1032 #endif
1033
1034
1035 void builtin_displaymethodstart(methodinfo *method)
1036 {
1037         char logtext[MAXLOGTEXT];
1038         sprintf(logtext, "                                                                                              ");
1039         sprintf(logtext + methodindent, "called: ");
1040         utf_sprint(logtext + strlen(logtext), method->class->name);
1041         sprintf(logtext + strlen(logtext), ".");
1042         utf_sprint(logtext + strlen(logtext), method->name);
1043         utf_sprint(logtext + strlen(logtext), method->descriptor);
1044         log_text(logtext);
1045         methodindent++;
1046 }
1047
1048
1049 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1050 {
1051         int i;
1052         char logtext[MAXLOGTEXT];
1053         for (i = 0; i < methodindent; i++)
1054                 logtext[i] = '\t';
1055         if (methodindent)
1056                 methodindent--;
1057         else
1058                 log_text("WARNING: unmatched methodindent--");
1059         sprintf(logtext + methodindent, "finished: ");
1060         utf_sprint(logtext + strlen(logtext), method->class->name);
1061         sprintf(logtext + strlen(logtext), ".");
1062         utf_sprint(logtext + strlen(logtext), method->name);
1063         utf_sprint(logtext + strlen(logtext), method->descriptor);
1064
1065         switch (method->returntype) {
1066         case TYPE_INT:
1067                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1068                 break;
1069         case TYPE_LONG:
1070 #if defined(__I386__)
1071                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1072 #else
1073                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1074 #endif
1075                 break;
1076         case TYPE_ADDRESS:
1077 #if defined(__I386__)
1078                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1079 #else
1080                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1081 #endif
1082                 break;
1083         case TYPE_FLOAT:
1084                 sprintf(logtext + strlen(logtext), "->%g", f);
1085                 break;
1086         case TYPE_DOUBLE:
1087                 sprintf(logtext + strlen(logtext), "->%g", d);
1088                 break;
1089         }
1090         log_text(logtext);
1091 }
1092
1093
1094 void builtin_displaymethodexception(methodinfo *method)
1095 {
1096         int i;
1097         char logtext[MAXLOGTEXT];
1098         for (i = 0; i < methodindent; i++)
1099                 logtext[i] = '\t';
1100         sprintf(logtext + methodindent, "exception abort: ");
1101         utf_sprint(logtext + strlen(logtext), method->class->name);
1102         sprintf(logtext + strlen(logtext), ".");
1103         utf_sprint(logtext + strlen(logtext), method->name);
1104         utf_sprint(logtext + strlen(logtext), method->descriptor);
1105         log_text(logtext);
1106 }
1107
1108
1109 /****************************************************************************
1110                          SYNCHRONIZATION FUNCTIONS
1111 *****************************************************************************/
1112
1113 /*
1114  * Lock the mutex of an object.
1115  */
1116 void internal_lock_mutex_for_object(java_objectheader *object)
1117 {
1118 #ifdef USE_THREADS
1119         mutexHashEntry *entry;
1120         int hashValue;
1121
1122         assert(object != 0);
1123
1124         hashValue = MUTEX_HASH_VALUE(object);
1125         entry = &mutexHashTable[hashValue];
1126
1127         if (entry->object != 0) {
1128                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1129                         entry->object = 0;
1130                         entry->mutex.holder = 0;
1131                         entry->mutex.count = 0;
1132                         entry->mutex.muxWaiters = 0;
1133
1134                 } else {
1135                         while (entry->next != 0 && entry->object != object)
1136                                 entry = entry->next;
1137
1138                         if (entry->object != object) {
1139                                 entry->next = firstFreeOverflowEntry;
1140                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1141
1142                                 entry = entry->next;
1143                                 entry->object = 0;
1144                                 entry->next = 0;
1145                                 assert(entry->conditionCount == 0);
1146                         }
1147                 }
1148
1149         } else {
1150                 entry->mutex.holder = 0;
1151                 entry->mutex.count = 0;
1152                 entry->mutex.muxWaiters = 0;
1153         }
1154
1155         if (entry->object == 0)
1156                 entry->object = object;
1157         
1158         internal_lock_mutex(&entry->mutex);
1159 #endif
1160 }
1161
1162
1163 /*
1164  * Unlocks the mutex of an object.
1165  */
1166 void internal_unlock_mutex_for_object (java_objectheader *object)
1167 {
1168 #ifdef USE_THREADS
1169         int hashValue;
1170         mutexHashEntry *entry;
1171
1172         hashValue = MUTEX_HASH_VALUE(object);
1173         entry = &mutexHashTable[hashValue];
1174
1175         if (entry->object == object) {
1176                 internal_unlock_mutex(&entry->mutex);
1177
1178         } else {
1179                 while (entry->next != 0 && entry->next->object != object)
1180                         entry = entry->next;
1181
1182                 assert(entry->next != 0);
1183
1184                 internal_unlock_mutex(&entry->next->mutex);
1185
1186                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1187                         mutexHashEntry *unlinked = entry->next;
1188
1189                         entry->next = unlinked->next;
1190                         unlinked->next = firstFreeOverflowEntry;
1191                         firstFreeOverflowEntry = unlinked;
1192                 }
1193         }
1194 #endif
1195 }
1196
1197
1198 void builtin_monitorenter(java_objectheader *o)
1199 {
1200 #ifdef USE_THREADS
1201         int hashValue;
1202
1203         assert(blockInts == 0);
1204
1205         ++blockInts;
1206
1207         hashValue = MUTEX_HASH_VALUE(o);
1208         if (mutexHashTable[hashValue].object == o 
1209                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1210                 ++mutexHashTable[hashValue].mutex.count;
1211         else
1212                 internal_lock_mutex_for_object(o);
1213
1214         --blockInts;
1215
1216         assert(blockInts == 0);
1217 #endif
1218 }
1219
1220
1221 void builtin_monitorexit (java_objectheader *o)
1222 {
1223 #ifdef USE_THREADS
1224         int hashValue;
1225
1226         assert(blockInts == 0);
1227
1228         ++blockInts;
1229
1230         hashValue = MUTEX_HASH_VALUE(o);
1231         if (mutexHashTable[hashValue].object == o) {
1232                 if (mutexHashTable[hashValue].mutex.count == 1
1233                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1234                         internal_unlock_mutex_for_object(o);
1235                 else
1236                         --mutexHashTable[hashValue].mutex.count;
1237
1238         } else
1239                 internal_unlock_mutex_for_object(o);
1240
1241         --blockInts;
1242
1243         assert(blockInts == 0);
1244 #endif
1245 }
1246
1247
1248 /*****************************************************************************
1249                           MISCELLANEOUS HELPER FUNCTIONS
1250 *****************************************************************************/
1251
1252
1253
1254 /*********** Functions for integer divisions *****************************
1255  
1256         On some systems (eg. DEC ALPHA), integer division is not supported by the
1257         CPU. These helper functions implement the missing functionality.
1258
1259 ******************************************************************************/
1260
1261 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1262 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1263
1264
1265 /************** Functions for long arithmetics *******************************
1266
1267         On systems where 64 bit Integers are not supported by the CPU, these
1268         functions are needed.
1269
1270 ******************************************************************************/
1271
1272
1273 s8 builtin_ladd(s8 a, s8 b)
1274
1275 #if U8_AVAILABLE
1276         return a + b; 
1277 #else
1278         return builtin_i2l(0);
1279 #endif
1280 }
1281
1282 s8 builtin_lsub(s8 a, s8 b) 
1283
1284 #if U8_AVAILABLE
1285         return a - b; 
1286 #else
1287         return builtin_i2l(0);
1288 #endif
1289 }
1290
1291 s8 builtin_lmul(s8 a, s8 b) 
1292
1293 #if U8_AVAILABLE
1294         return a * b; 
1295 #else
1296         return builtin_i2l(0);
1297 #endif
1298 }
1299
1300 s8 builtin_ldiv(s8 a, s8 b) 
1301
1302 #if U8_AVAILABLE
1303         return a / b; 
1304 #else
1305         return builtin_i2l(0);
1306 #endif
1307 }
1308
1309 s8 builtin_lrem(s8 a, s8 b) 
1310
1311 #if U8_AVAILABLE
1312         return a % b; 
1313 #else
1314         return builtin_i2l(0);
1315 #endif
1316 }
1317
1318 s8 builtin_lshl(s8 a, s4 b) 
1319
1320 #if U8_AVAILABLE
1321         return a << (b & 63);
1322 #else
1323         return builtin_i2l(0);
1324 #endif
1325 }
1326
1327 s8 builtin_lshr(s8 a, s4 b) 
1328
1329 #if U8_AVAILABLE
1330         return a >> (b & 63);
1331 #else
1332         return builtin_i2l(0);
1333 #endif
1334 }
1335
1336 s8 builtin_lushr(s8 a, s4 b) 
1337
1338 #if U8_AVAILABLE
1339         return ((u8) a) >> (b & 63);
1340 #else
1341         return builtin_i2l(0);
1342 #endif
1343 }
1344
1345 s8 builtin_land(s8 a, s8 b) 
1346
1347 #if U8_AVAILABLE
1348         return a & b; 
1349 #else
1350         return builtin_i2l(0);
1351 #endif
1352 }
1353
1354 s8 builtin_lor(s8 a, s8 b) 
1355
1356 #if U8_AVAILABLE
1357         return a | b; 
1358 #else
1359         return builtin_i2l(0);
1360 #endif
1361 }
1362
1363 s8 builtin_lxor(s8 a, s8 b) 
1364
1365 #if U8_AVAILABLE
1366         return a ^ b; 
1367 #else
1368         return builtin_i2l(0);
1369 #endif
1370 }
1371
1372 s8 builtin_lneg(s8 a) 
1373
1374 #if U8_AVAILABLE
1375         return -a;
1376 #else
1377         return builtin_i2l(0);
1378 #endif
1379 }
1380
1381 s4 builtin_lcmp(s8 a, s8 b) 
1382
1383 #if U8_AVAILABLE
1384         if (a < b) return -1;
1385         if (a > b) return 1;
1386         return 0;
1387 #else
1388         return 0;
1389 #endif
1390 }
1391
1392
1393
1394
1395
1396 /*********** Functions for floating point operations *************************/
1397
1398 float builtin_fadd(float a, float b)
1399 {
1400         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1401         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1402         if (finitef(a)) {
1403                 if (finitef(b))
1404                         return a + b;
1405                 else
1406                         return b;
1407         }
1408         else {
1409                 if (finitef(b))
1410                         return a;
1411                 else {
1412                         if (copysignf(1.0, a) == copysignf(1.0, b))
1413                                 return a;
1414                         else
1415                                 return intBitsToFloat(FLT_NAN);
1416                 }
1417         }
1418 }
1419
1420
1421 float builtin_fsub(float a, float b)
1422 {
1423         return builtin_fadd(a, builtin_fneg(b));
1424 }
1425
1426
1427 float builtin_fmul(float a, float b)
1428 {
1429         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1430         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1431         if (finitef(a)) {
1432                 if (finitef(b)) return a * b;
1433                 else {
1434                         if (a == 0) return intBitsToFloat(FLT_NAN);
1435                         else return copysignf(b, copysignf(1.0, b)*a);
1436                 }
1437         }
1438         else {
1439                 if (finitef(b)) {
1440                         if (b == 0) return intBitsToFloat(FLT_NAN);
1441                         else return copysignf(a, copysignf(1.0, a)*b);
1442                 }
1443                 else {
1444                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1445                 }
1446         }
1447 }
1448
1449
1450 float builtin_fdiv(float a, float b)
1451 {
1452         if (finitef(a) && finitef(b)) {
1453                 if (b != 0)
1454                         return a / b;
1455                 else {
1456                         if (a > 0)
1457                                 return intBitsToFloat(FLT_POSINF);
1458                         else if (a < 0)
1459                                 return intBitsToFloat(FLT_NEGINF);
1460                 }
1461         }
1462         return intBitsToFloat(FLT_NAN);
1463 }
1464
1465
1466 float builtin_frem(float a, float b)
1467 {
1468         return fmodf(a, b);
1469 }
1470
1471
1472 float builtin_fneg(float a)
1473 {
1474         if (isnanf(a)) return a;
1475         else {
1476                 if (finitef(a)) return -a;
1477                 else return copysignf(a, -copysignf(1.0, a));
1478         }
1479 }
1480
1481
1482 s4 builtin_fcmpl(float a, float b)
1483 {
1484         if (isnanf(a)) return -1;
1485         if (isnanf(b)) return -1;
1486         if (!finitef(a) || !finitef(b)) {
1487                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1488                 b = finitef(b) ? 0 : copysignf(1.0, b);
1489         }
1490         if (a > b) return 1;
1491         if (a == b) return 0;
1492         return -1;
1493 }
1494
1495
1496 s4 builtin_fcmpg(float a, float b)
1497 {
1498         if (isnanf(a)) return 1;
1499         if (isnanf(b)) return 1;
1500         if (!finitef(a) || !finitef(b)) {
1501                 a = finitef(a) ? 0 : copysignf(1.0, a);
1502                 b = finitef(b) ? 0 : copysignf(1.0, b);
1503         }
1504         if (a > b) return 1;
1505         if (a == b) return 0;
1506         return -1;
1507 }
1508
1509
1510
1511 /************************* Functions for doubles ****************************/
1512
1513 double builtin_dadd(double a, double b)
1514 {
1515         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1516         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1517         if (finite(a)) {
1518                 if (finite(b)) return a + b;
1519                 else return b;
1520         }
1521         else {
1522                 if (finite(b)) return a;
1523                 else {
1524                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1525                         else return longBitsToDouble(DBL_NAN);
1526                 }
1527         }
1528 }
1529
1530
1531 double builtin_dsub(double a, double b)
1532 {
1533         return builtin_dadd(a, builtin_dneg(b));
1534 }
1535
1536
1537 double builtin_dmul(double a, double b)
1538 {
1539         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1540         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1541         if (finite(a)) {
1542                 if (finite(b)) return a * b;
1543                 else {
1544                         if (a == 0) return longBitsToDouble(DBL_NAN);
1545                         else return copysign(b, copysign(1.0, b) * a);
1546                 }
1547         }
1548         else {
1549                 if (finite(b)) {
1550                         if (b == 0) return longBitsToDouble(DBL_NAN);
1551                         else return copysign(a, copysign(1.0, a) * b);
1552                 }
1553                 else {
1554                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1555                 }
1556         }
1557 }
1558
1559
1560 double builtin_ddiv(double a, double b)
1561 {
1562         if (finite(a)) {
1563                 if (finite(b)) {
1564                         return a / b;
1565
1566                 } else {
1567                         if (isnan(b))
1568                                 return longBitsToDouble(DBL_NAN);
1569                         else
1570                                 return copysign(0.0, b);
1571                 }
1572
1573         } else {
1574                 if (finite(b)) {
1575                         if (a > 0)
1576                                 return longBitsToDouble(DBL_POSINF);
1577                         else if (a < 0)
1578                                 return longBitsToDouble(DBL_NEGINF);
1579
1580                 } else
1581                         return longBitsToDouble(DBL_NAN);
1582         }
1583
1584 /*      if (finite(a) && finite(b)) { */
1585 /*              if (b != 0) */
1586 /*                      return a / b; */
1587 /*              else { */
1588 /*                      if (a > 0) */
1589 /*                              return longBitsToDouble(DBL_POSINF); */
1590 /*                      else if (a < 0) */
1591 /*                              return longBitsToDouble(DBL_NEGINF); */
1592 /*              } */
1593 /*      } */
1594
1595         /* keep compiler happy */
1596         return 0;
1597 }
1598
1599
1600 double builtin_drem(double a, double b)
1601 {
1602         return fmod(a, b);
1603 }
1604
1605
1606 double builtin_dneg(double a)
1607 {
1608         if (isnan(a)) return a;
1609         else {
1610                 if (finite(a)) return -a;
1611                 else return copysign(a, -copysign(1.0, a));
1612         }
1613 }
1614
1615
1616 s4 builtin_dcmpl(double a, double b)
1617 {
1618         if (isnan(a)) return -1;
1619         if (isnan(b)) return -1;
1620         if (!finite(a) || !finite(b)) {
1621                 a = finite(a) ? 0 : copysign(1.0, a);
1622                 b = finite(b) ? 0 : copysign(1.0, b);
1623         }
1624         if (a > b) return 1;
1625         if (a == b) return 0;
1626         return -1;
1627 }
1628
1629
1630 s4 builtin_dcmpg(double a, double b)
1631 {
1632         if (isnan(a)) return 1;
1633         if (isnan(b)) return 1;
1634         if (!finite(a) || !finite(b)) {
1635                 a = finite(a) ? 0 : copysign(1.0, a);
1636                 b = finite(b) ? 0 : copysign(1.0, b);
1637         }
1638         if (a > b) return 1;
1639         if (a == b) return 0;
1640         return -1;
1641 }
1642
1643
1644 /*********************** Conversion operations ****************************/
1645
1646 s8 builtin_i2l(s4 i)
1647 {
1648 #if U8_AVAILABLE
1649         return i;
1650 #else
1651         s8 v;
1652         v.high = 0;
1653         v.low = i;
1654         return v;
1655 #endif
1656 }
1657
1658
1659 float builtin_i2f(s4 a)
1660 {
1661         float f = (float) a;
1662         return f;
1663 }
1664
1665
1666 double builtin_i2d(s4 a)
1667 {
1668         double d = (double) a;
1669         return d;
1670 }
1671
1672
1673 s4 builtin_l2i(s8 l)
1674 {
1675 #if U8_AVAILABLE
1676         return (s4) l;
1677 #else
1678         return l.low;
1679 #endif
1680 }
1681
1682
1683 float builtin_l2f(s8 a)
1684 {
1685 #if U8_AVAILABLE
1686         float f = (float) a;
1687         return f;
1688 #else
1689         return 0.0;
1690 #endif
1691 }
1692
1693
1694 double builtin_l2d(s8 a)
1695 {
1696 #if U8_AVAILABLE
1697         double d = (double) a;
1698         return d;
1699 #else
1700         return 0.0;
1701 #endif
1702 }
1703
1704
1705 s4 builtin_f2i(float a) 
1706 {
1707
1708         return builtin_d2i((double) a);
1709
1710         /*      float f;
1711         
1712                 if (isnanf(a))
1713                 return 0;
1714                 if (finitef(a)) {
1715                 if (a > 2147483647)
1716                 return 2147483647;
1717                 if (a < (-2147483648))
1718                 return (-2147483648);
1719                 return (s4) a;
1720                 }
1721                 f = copysignf((float) 1.0, a);
1722                 if (f > 0)
1723                 return 2147483647;
1724                 return (-2147483648); */
1725 }
1726
1727
1728 s8 builtin_f2l(float a)
1729 {
1730
1731         return builtin_d2l((double) a);
1732
1733         /*      float f;
1734         
1735                 if (finitef(a)) {
1736                 if (a > 9223372036854775807L)
1737                 return 9223372036854775807L;
1738                 if (a < (-9223372036854775808L))
1739                 return (-9223372036854775808L);
1740                 return (s8) a;
1741                 }
1742                 if (isnanf(a))
1743                 return 0;
1744                 f = copysignf((float) 1.0, a);
1745                 if (f > 0)
1746                 return 9223372036854775807L;
1747                 return (-9223372036854775808L); */
1748 }
1749
1750
1751 double builtin_f2d(float a)
1752 {
1753         if (finitef(a)) return (double) a;
1754         else {
1755                 if (isnanf(a))
1756                         return longBitsToDouble(DBL_NAN);
1757                 else
1758                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1759         }
1760 }
1761
1762
1763 s4 builtin_d2i(double a) 
1764
1765         double d;
1766         
1767         if (finite(a)) {
1768                 if (a >= 2147483647)
1769                         return 2147483647;
1770                 if (a <= (-2147483647-1))
1771                         return (-2147483647-1);
1772                 return (s4) a;
1773         }
1774         if (isnan(a))
1775                 return 0;
1776         d = copysign(1.0, a);
1777         if (d > 0)
1778                 return 2147483647;
1779         return (-2147483647-1);
1780 }
1781
1782
1783 s8 builtin_d2l(double a)
1784 {
1785         double d;
1786         
1787         if (finite(a)) {
1788                 if (a >= 9223372036854775807LL)
1789                         return 9223372036854775807LL;
1790                 if (a <= (-9223372036854775807LL-1))
1791                         return (-9223372036854775807LL-1);
1792                 return (s8) a;
1793         }
1794         if (isnan(a))
1795                 return 0;
1796         d = copysign(1.0, a);
1797         if (d > 0)
1798                 return 9223372036854775807LL;
1799         return (-9223372036854775807LL-1);
1800 }
1801
1802
1803 float builtin_d2f(double a)
1804 {
1805         if (finite(a))
1806                 return (float) a;
1807         else {
1808                 if (isnan(a))
1809                         return intBitsToFloat(FLT_NAN);
1810                 else
1811                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1812         }
1813 }
1814
1815
1816 /* used to convert FLT_xxx defines into float values */
1817
1818 inline float intBitsToFloat(s4 i)
1819 {
1820         imm_union imb;
1821
1822         imb.i = i;
1823         return imb.f;
1824 }
1825
1826
1827 /* used to convert DBL_xxx defines into double values */
1828
1829 inline float longBitsToDouble(s8 l)
1830 {
1831         imm_union imb;
1832
1833         imb.l = l;
1834         return imb.d;
1835 }
1836
1837
1838 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1839 {
1840         return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1841 }
1842
1843
1844 /*
1845  * These are local overrides for various environment variables in Emacs.
1846  * Please do not remove this and leave it at the end of the file, where
1847  * Emacs will automagically detect them.
1848  * ---------------------------------------------------------------------
1849  * Local variables:
1850  * mode: c
1851  * indent-tabs-mode: t
1852  * c-basic-offset: 4
1853  * tab-width: 4
1854  * End:
1855  */