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