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