- -verbosecall fixes
[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 964 2004-03-15 14:52:43Z 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 u4 methodindent = 0;
776
777 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
778                                                                                    methodinfo *method, int *pos, 
779                                                                                    int line,
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 || verboseexception) {
789                 if (_exceptionptr) {
790                         printf("Exception ");
791                         utf_display(_exceptionptr->vftbl->class->name);
792
793                 } else {
794                         printf("Some Throwable");
795 /*
796                         printf("Error: <Nullpointer instead of exception>");
797                         if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
798                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
799                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
800                         if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
801                         if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
802                         if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
803                         if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
804                         if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
805                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
806                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
807                         */
808                 }
809                 printf(" thrown in ");
810
811                 if (method) {
812                         utf_display_classname(method->class->name);
813                         printf(".");
814                         utf_display(method->name);
815                         if (method->flags & ACC_SYNCHRONIZED)
816                                 printf("(SYNC");
817                         else
818                                 printf("(NOSYNC");
819                         if (method->flags & ACC_NATIVE) {
820                                 printf(",NATIVE");
821                                 printf(")(%p) at position %p\n", method->entrypoint, pos);
822                         } else {
823                                 printf(")(%p) at position %p (",method->entrypoint,pos);
824                                 if (method->class->sourcefile==NULL)
825                                         printf("<NO CLASSFILE INFORMATION>");
826                                 else
827                                         utf_display(method->class->sourcefile);
828                                 printf(":%d)\n",line);
829                         }
830
831                 } else
832                         printf("call_java_method\n");
833                 fflush (stdout);
834         }
835
836         return _exceptionptr;
837 }
838
839
840 #ifdef TRACE_ARGS_NUM
841 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
842 #if TRACE_ARGS_NUM > 6
843                                                 s8 a6, s8 a7,
844 #endif
845                                                 methodinfo *method)
846 {
847         int i;
848         char logtext[MAXLOGTEXT];
849         for (i = 0; i < methodindent; i++)
850                 logtext[i] = '\t';
851
852         sprintf(logtext + methodindent, "called: ");
853         utf_sprint(logtext + strlen(logtext), method->class->name);
854         sprintf(logtext + strlen(logtext), ".");
855         utf_sprint(logtext + strlen(logtext), method->name);
856         utf_sprint(logtext + strlen(logtext), method->descriptor);
857
858         if ( method->flags & ACC_PUBLIC )       sprintf (logtext + strlen(logtext)," PUBLIC");
859         if ( method->flags & ACC_PRIVATE )      sprintf (logtext + strlen(logtext)," PRIVATE");
860         if ( method->flags & ACC_PROTECTED )    sprintf (logtext + strlen(logtext)," PROTECTED");
861         if ( method->flags & ACC_STATIC )       sprintf (logtext + strlen(logtext)," STATIC");
862         if ( method->flags & ACC_FINAL )        sprintf (logtext + strlen(logtext)," FINAL");
863         if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
864         if ( method->flags & ACC_VOLATILE )     sprintf (logtext + strlen(logtext)," VOLATILE");
865         if ( method->flags & ACC_TRANSIENT )    sprintf (logtext + strlen(logtext)," TRANSIENT");
866         if ( method->flags & ACC_NATIVE )       sprintf (logtext + strlen(logtext)," NATIVE");
867         if ( method->flags & ACC_INTERFACE )    sprintf (logtext + strlen(logtext)," INTERFACE");
868         if ( method->flags & ACC_ABSTRACT )     sprintf (logtext + strlen(logtext)," ABSTRACT");
869         
870
871         sprintf(logtext + strlen(logtext), "(");
872
873         switch (method->paramcount) {
874         case 0:
875                 break;
876
877 #if defined(__I386__) || defined(__POWERPC__)
878         case 1:
879                 sprintf(logtext+strlen(logtext), "%llx", a0);
880                 break;
881
882         case 2:
883                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
884                 break;
885
886         case 3:
887                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
888                 break;
889
890         case 4:
891                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
892                                 a0,   a1,   a2,   a3);
893                 break;
894
895         case 5:
896                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
897                                 a0,   a1,   a2,   a3,   a4);
898                 break;
899
900         case 6:
901                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
902                                 a0,   a1,   a2,   a3,   a4,   a5);
903                 break;
904
905 #if TRACE_ARGS_NUM > 6
906         case 7:
907                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
908                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
909                 break;
910
911         case 8:
912                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
913                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
914                 break;
915
916         default:
917                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
918                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   method->paramcount - 8);
919                 break;
920 #else
921         default:
922                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
923                                 a0,   a1,   a2,   a3,   a4,   a5,   method->paramcount - 6);
924                 break;
925 #endif
926 #else
927         case 1:
928                 sprintf(logtext+strlen(logtext), "%lx", a0);
929                 break;
930
931         case 2:
932                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
933                 break;
934
935         case 3:
936                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
937                 break;
938
939         case 4:
940                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
941                                 a0,  a1,  a2,  a3);
942                 break;
943
944         case 5:
945                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
946                                 a0,  a1,  a2,  a3,  a4);
947                 break;
948
949         case 6:
950                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
951                                 a0,  a1,  a2,  a3,  a4,  a5);
952                 break;
953
954 #if TRACE_ARGS_NUM > 6
955         case 7:
956                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
957                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
958                 break;
959
960         case 8:
961                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
962                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
963                 break;
964
965         default:
966                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
967                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  method->paramcount - 8);
968                 break;
969 #else
970         default:
971                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
972                                 a0,  a1,  a2,  a3,  a4,  a5,   method->paramcount - 6);
973                 break;
974 #endif
975 #endif
976         }
977
978         sprintf(logtext + strlen(logtext), ")");
979         log_text(logtext);
980
981         methodindent++;
982 }
983 #endif
984
985
986 void builtin_displaymethodstart(methodinfo *method)
987 {
988         char logtext[MAXLOGTEXT];
989         sprintf(logtext, "                                                                                              ");
990         sprintf(logtext + methodindent, "called: ");
991         utf_sprint(logtext + strlen(logtext), method->class->name);
992         sprintf(logtext + strlen(logtext), ".");
993         utf_sprint(logtext + strlen(logtext), method->name);
994         utf_sprint(logtext + strlen(logtext), method->descriptor);
995
996         if ( method->flags & ACC_PUBLIC )       sprintf (logtext + strlen(logtext)," PUBLIC");
997         if ( method->flags & ACC_PRIVATE )      sprintf (logtext + strlen(logtext)," PRIVATE");
998         if ( method->flags & ACC_PROTECTED )    sprintf (logtext + strlen(logtext)," PROTECTED");
999         if ( method->flags & ACC_STATIC )       sprintf (logtext + strlen(logtext)," STATIC");
1000         if ( method->flags & ACC_FINAL )        sprintf (logtext + strlen(logtext)," FINAL");
1001         if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
1002         if ( method->flags & ACC_VOLATILE )     sprintf (logtext + strlen(logtext)," VOLATILE");
1003         if ( method->flags & ACC_TRANSIENT )    sprintf (logtext + strlen(logtext)," TRANSIENT");
1004         if ( method->flags & ACC_NATIVE )       sprintf (logtext + strlen(logtext)," NATIVE");
1005         if ( method->flags & ACC_INTERFACE )    sprintf (logtext + strlen(logtext)," INTERFACE");
1006         if ( method->flags & ACC_ABSTRACT )     sprintf (logtext + strlen(logtext)," ABSTRACT");
1007
1008         log_text(logtext);
1009         methodindent++;
1010 }
1011
1012
1013 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1014 {
1015         int i;
1016         char logtext[MAXLOGTEXT];
1017         for (i = 0; i < methodindent; i++)
1018                 logtext[i] = '\t';
1019         if (methodindent)
1020                 methodindent--;
1021         else
1022                 log_text("WARNING: unmatched methodindent--");
1023
1024         sprintf(logtext + methodindent, "finished: ");
1025         utf_sprint(logtext + strlen(logtext), method->class->name);
1026         sprintf(logtext + strlen(logtext), ".");
1027         utf_sprint(logtext + strlen(logtext), method->name);
1028         utf_sprint(logtext + strlen(logtext), method->descriptor);
1029
1030         switch (method->returntype) {
1031         case TYPE_INT:
1032                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1033                 break;
1034
1035         case TYPE_LONG:
1036 #if defined(__I386__) || defined(__POWERPC__)
1037                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1038 #else
1039                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1040 #endif
1041                 break;
1042
1043         case TYPE_ADDRESS:
1044 #if defined(__I386__) || defined(__POWERPC__)
1045                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1046 #else
1047                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1048 #endif
1049                 break;
1050
1051         case TYPE_FLOAT:
1052                 sprintf(logtext + strlen(logtext), "->%g", f);
1053                 break;
1054
1055         case TYPE_DOUBLE:
1056                 sprintf(logtext + strlen(logtext), "->%g", d);
1057                 break;
1058         }
1059         log_text(logtext);
1060 }
1061
1062
1063 void builtin_displaymethodexception(methodinfo *method)
1064 {
1065         int i;
1066         char logtext[MAXLOGTEXT];
1067         for (i = 0; i < methodindent; i++)
1068                 logtext[i] = '\t';
1069         sprintf(logtext + methodindent, "exception abort: ");
1070         utf_sprint(logtext + strlen(logtext), method->class->name);
1071         sprintf(logtext + strlen(logtext), ".");
1072         utf_sprint(logtext + strlen(logtext), method->name);
1073         utf_sprint(logtext + strlen(logtext), method->descriptor);
1074         log_text(logtext);
1075 }
1076
1077
1078 /****************************************************************************
1079                          SYNCHRONIZATION FUNCTIONS
1080 *****************************************************************************/
1081
1082 /*
1083  * Lock the mutex of an object.
1084  */
1085 void internal_lock_mutex_for_object(java_objectheader *object)
1086 {
1087 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1088         mutexHashEntry *entry;
1089         int hashValue;
1090
1091         assert(object != 0);
1092
1093         hashValue = MUTEX_HASH_VALUE(object);
1094         entry = &mutexHashTable[hashValue];
1095
1096         if (entry->object != 0) {
1097                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1098                         entry->object = 0;
1099                         entry->mutex.holder = 0;
1100                         entry->mutex.count = 0;
1101                         entry->mutex.muxWaiters = 0;
1102
1103                 } else {
1104                         while (entry->next != 0 && entry->object != object)
1105                                 entry = entry->next;
1106
1107                         if (entry->object != object) {
1108                                 entry->next = firstFreeOverflowEntry;
1109                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1110
1111                                 entry = entry->next;
1112                                 entry->object = 0;
1113                                 entry->next = 0;
1114                                 assert(entry->conditionCount == 0);
1115                         }
1116                 }
1117
1118         } else {
1119                 entry->mutex.holder = 0;
1120                 entry->mutex.count = 0;
1121                 entry->mutex.muxWaiters = 0;
1122         }
1123
1124         if (entry->object == 0)
1125                 entry->object = object;
1126         
1127         internal_lock_mutex(&entry->mutex);
1128 #endif
1129 }
1130
1131
1132 /*
1133  * Unlocks the mutex of an object.
1134  */
1135 void internal_unlock_mutex_for_object (java_objectheader *object)
1136 {
1137 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1138         int hashValue;
1139         mutexHashEntry *entry;
1140
1141         hashValue = MUTEX_HASH_VALUE(object);
1142         entry = &mutexHashTable[hashValue];
1143
1144         if (entry->object == object) {
1145                 internal_unlock_mutex(&entry->mutex);
1146
1147         } else {
1148                 while (entry->next != 0 && entry->next->object != object)
1149                         entry = entry->next;
1150
1151                 assert(entry->next != 0);
1152
1153                 internal_unlock_mutex(&entry->next->mutex);
1154
1155                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1156                         mutexHashEntry *unlinked = entry->next;
1157
1158                         entry->next = unlinked->next;
1159                         unlinked->next = firstFreeOverflowEntry;
1160                         firstFreeOverflowEntry = unlinked;
1161                 }
1162         }
1163 #endif
1164 }
1165
1166
1167 void builtin_monitorenter(java_objectheader *o)
1168 {
1169 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1170         int hashValue;
1171
1172         log_text("Monitor enter");
1173
1174         assert(blockInts == 0);
1175
1176         ++blockInts;
1177
1178         hashValue = MUTEX_HASH_VALUE(o);
1179         if (mutexHashTable[hashValue].object == o 
1180                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1181                 ++mutexHashTable[hashValue].mutex.count;
1182         else
1183                 internal_lock_mutex_for_object(o);
1184
1185         --blockInts;
1186
1187         assert(blockInts == 0);
1188 #endif
1189 }
1190
1191
1192 void builtin_monitorexit (java_objectheader *o)
1193 {
1194
1195 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1196         int hashValue;
1197
1198         log_text("Monitor leave");
1199
1200         assert(blockInts == 0);
1201
1202         ++blockInts;
1203
1204         hashValue = MUTEX_HASH_VALUE(o);
1205         if (mutexHashTable[hashValue].object == o) {
1206                 if (mutexHashTable[hashValue].mutex.count == 1
1207                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1208                         internal_unlock_mutex_for_object(o);
1209                 else
1210                         --mutexHashTable[hashValue].mutex.count;
1211
1212         } else
1213                 internal_unlock_mutex_for_object(o);
1214
1215         --blockInts;
1216
1217         assert(blockInts == 0);
1218 #endif
1219 }
1220
1221
1222 /*****************************************************************************
1223                           MISCELLANEOUS HELPER FUNCTIONS
1224 *****************************************************************************/
1225
1226
1227
1228 /*********** Functions for integer divisions *****************************
1229  
1230         On some systems (eg. DEC ALPHA), integer division is not supported by the
1231         CPU. These helper functions implement the missing functionality.
1232
1233 ******************************************************************************/
1234
1235 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1236 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1237
1238
1239 /************** Functions for long arithmetics *******************************
1240
1241         On systems where 64 bit Integers are not supported by the CPU, these
1242         functions are needed.
1243
1244 ******************************************************************************/
1245
1246
1247 s8 builtin_ladd(s8 a, s8 b)
1248
1249 #if U8_AVAILABLE
1250         return a + b; 
1251 #else
1252         return builtin_i2l(0);
1253 #endif
1254 }
1255
1256 s8 builtin_lsub(s8 a, s8 b) 
1257
1258 #if U8_AVAILABLE
1259         return a - b; 
1260 #else
1261         return builtin_i2l(0);
1262 #endif
1263 }
1264
1265 s8 builtin_lmul(s8 a, s8 b) 
1266
1267 #if U8_AVAILABLE
1268         return a * b; 
1269 #else
1270         return builtin_i2l(0);
1271 #endif
1272 }
1273
1274 s8 builtin_ldiv(s8 a, s8 b) 
1275
1276 #if U8_AVAILABLE
1277         return a / b; 
1278 #else
1279         return builtin_i2l(0);
1280 #endif
1281 }
1282
1283 s8 builtin_lrem(s8 a, s8 b) 
1284
1285 #if U8_AVAILABLE
1286         return a % b; 
1287 #else
1288         return builtin_i2l(0);
1289 #endif
1290 }
1291
1292 s8 builtin_lshl(s8 a, s4 b) 
1293
1294 #if U8_AVAILABLE
1295         return a << (b & 63);
1296 #else
1297         return builtin_i2l(0);
1298 #endif
1299 }
1300
1301 s8 builtin_lshr(s8 a, s4 b) 
1302
1303 #if U8_AVAILABLE
1304         return a >> (b & 63);
1305 #else
1306         return builtin_i2l(0);
1307 #endif
1308 }
1309
1310 s8 builtin_lushr(s8 a, s4 b) 
1311
1312 #if U8_AVAILABLE
1313         return ((u8) a) >> (b & 63);
1314 #else
1315         return builtin_i2l(0);
1316 #endif
1317 }
1318
1319 s8 builtin_land(s8 a, s8 b) 
1320
1321 #if U8_AVAILABLE
1322         return a & b; 
1323 #else
1324         return builtin_i2l(0);
1325 #endif
1326 }
1327
1328 s8 builtin_lor(s8 a, s8 b) 
1329
1330 #if U8_AVAILABLE
1331         return a | b; 
1332 #else
1333         return builtin_i2l(0);
1334 #endif
1335 }
1336
1337 s8 builtin_lxor(s8 a, s8 b) 
1338
1339 #if U8_AVAILABLE
1340         return a ^ b; 
1341 #else
1342         return builtin_i2l(0);
1343 #endif
1344 }
1345
1346 s8 builtin_lneg(s8 a) 
1347
1348 #if U8_AVAILABLE
1349         return -a;
1350 #else
1351         return builtin_i2l(0);
1352 #endif
1353 }
1354
1355 s4 builtin_lcmp(s8 a, s8 b) 
1356
1357 #if U8_AVAILABLE
1358         if (a < b) return -1;
1359         if (a > b) return 1;
1360         return 0;
1361 #else
1362         return 0;
1363 #endif
1364 }
1365
1366
1367
1368
1369
1370 /*********** Functions for floating point operations *************************/
1371
1372 float builtin_fadd(float a, float b)
1373 {
1374         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1375         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1376         if (finitef(a)) {
1377                 if (finitef(b))
1378                         return a + b;
1379                 else
1380                         return b;
1381         }
1382         else {
1383                 if (finitef(b))
1384                         return a;
1385                 else {
1386                         if (copysignf(1.0, a) == copysignf(1.0, b))
1387                                 return a;
1388                         else
1389                                 return intBitsToFloat(FLT_NAN);
1390                 }
1391         }
1392 }
1393
1394
1395 float builtin_fsub(float a, float b)
1396 {
1397         return builtin_fadd(a, builtin_fneg(b));
1398 }
1399
1400
1401 float builtin_fmul(float a, float b)
1402 {
1403         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1404         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1405         if (finitef(a)) {
1406                 if (finitef(b)) return a * b;
1407                 else {
1408                         if (a == 0) return intBitsToFloat(FLT_NAN);
1409                         else return copysignf(b, copysignf(1.0, b)*a);
1410                 }
1411         }
1412         else {
1413                 if (finitef(b)) {
1414                         if (b == 0) return intBitsToFloat(FLT_NAN);
1415                         else return copysignf(a, copysignf(1.0, a)*b);
1416                 }
1417                 else {
1418                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1419                 }
1420         }
1421 }
1422
1423
1424 float builtin_fdiv(float a, float b)
1425 {
1426         if (finitef(a) && finitef(b)) {
1427                 if (b != 0)
1428                         return a / b;
1429                 else {
1430                         if (a > 0)
1431                                 return intBitsToFloat(FLT_POSINF);
1432                         else if (a < 0)
1433                                 return intBitsToFloat(FLT_NEGINF);
1434                 }
1435         }
1436         return intBitsToFloat(FLT_NAN);
1437 }
1438
1439
1440 float builtin_frem(float a, float b)
1441 {
1442         return fmodf(a, b);
1443 }
1444
1445
1446 float builtin_fneg(float a)
1447 {
1448         if (isnanf(a)) return a;
1449         else {
1450                 if (finitef(a)) return -a;
1451                 else return copysignf(a, -copysignf(1.0, a));
1452         }
1453 }
1454
1455
1456 s4 builtin_fcmpl(float a, float b)
1457 {
1458         if (isnanf(a)) return -1;
1459         if (isnanf(b)) return -1;
1460         if (!finitef(a) || !finitef(b)) {
1461                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1462                 b = finitef(b) ? 0 : copysignf(1.0, b);
1463         }
1464         if (a > b) return 1;
1465         if (a == b) return 0;
1466         return -1;
1467 }
1468
1469
1470 s4 builtin_fcmpg(float a, float b)
1471 {
1472         if (isnanf(a)) return 1;
1473         if (isnanf(b)) return 1;
1474         if (!finitef(a) || !finitef(b)) {
1475                 a = finitef(a) ? 0 : copysignf(1.0, a);
1476                 b = finitef(b) ? 0 : copysignf(1.0, b);
1477         }
1478         if (a > b) return 1;
1479         if (a == b) return 0;
1480         return -1;
1481 }
1482
1483
1484
1485 /************************* Functions for doubles ****************************/
1486
1487 double builtin_dadd(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 return b;
1494         }
1495         else {
1496                 if (finite(b)) return a;
1497                 else {
1498                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1499                         else return longBitsToDouble(DBL_NAN);
1500                 }
1501         }
1502 }
1503
1504
1505 double builtin_dsub(double a, double b)
1506 {
1507         return builtin_dadd(a, builtin_dneg(b));
1508 }
1509
1510
1511 double builtin_dmul(double a, double b)
1512 {
1513         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1514         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1515         if (finite(a)) {
1516                 if (finite(b)) return a * b;
1517                 else {
1518                         if (a == 0) return longBitsToDouble(DBL_NAN);
1519                         else return copysign(b, copysign(1.0, b) * a);
1520                 }
1521         }
1522         else {
1523                 if (finite(b)) {
1524                         if (b == 0) return longBitsToDouble(DBL_NAN);
1525                         else return copysign(a, copysign(1.0, a) * b);
1526                 }
1527                 else {
1528                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1529                 }
1530         }
1531 }
1532
1533
1534 double builtin_ddiv(double a, double b)
1535 {
1536         if (finite(a)) {
1537                 if (finite(b)) {
1538                         return a / b;
1539
1540                 } else {
1541                         if (isnan(b))
1542                                 return longBitsToDouble(DBL_NAN);
1543                         else
1544                                 return copysign(0.0, b);
1545                 }
1546
1547         } else {
1548                 if (finite(b)) {
1549                         if (a > 0)
1550                                 return longBitsToDouble(DBL_POSINF);
1551                         else if (a < 0)
1552                                 return longBitsToDouble(DBL_NEGINF);
1553
1554                 } else
1555                         return longBitsToDouble(DBL_NAN);
1556         }
1557
1558 /*      if (finite(a) && finite(b)) { */
1559 /*              if (b != 0) */
1560 /*                      return a / b; */
1561 /*              else { */
1562 /*                      if (a > 0) */
1563 /*                              return longBitsToDouble(DBL_POSINF); */
1564 /*                      else if (a < 0) */
1565 /*                              return longBitsToDouble(DBL_NEGINF); */
1566 /*              } */
1567 /*      } */
1568
1569         /* keep compiler happy */
1570         return 0;
1571 }
1572
1573
1574 double builtin_drem(double a, double b)
1575 {
1576         return fmod(a, b);
1577 }
1578
1579
1580 double builtin_dneg(double a)
1581 {
1582         if (isnan(a)) return a;
1583         else {
1584                 if (finite(a)) return -a;
1585                 else return copysign(a, -copysign(1.0, a));
1586         }
1587 }
1588
1589
1590 s4 builtin_dcmpl(double a, double b)
1591 {
1592         if (isnan(a)) return -1;
1593         if (isnan(b)) return -1;
1594         if (!finite(a) || !finite(b)) {
1595                 a = finite(a) ? 0 : copysign(1.0, a);
1596                 b = finite(b) ? 0 : copysign(1.0, b);
1597         }
1598         if (a > b) return 1;
1599         if (a == b) return 0;
1600         return -1;
1601 }
1602
1603
1604 s4 builtin_dcmpg(double a, double b)
1605 {
1606         if (isnan(a)) return 1;
1607         if (isnan(b)) return 1;
1608         if (!finite(a) || !finite(b)) {
1609                 a = finite(a) ? 0 : copysign(1.0, a);
1610                 b = finite(b) ? 0 : copysign(1.0, b);
1611         }
1612         if (a > b) return 1;
1613         if (a == b) return 0;
1614         return -1;
1615 }
1616
1617
1618 /*********************** Conversion operations ****************************/
1619
1620 s8 builtin_i2l(s4 i)
1621 {
1622 #if U8_AVAILABLE
1623         return i;
1624 #else
1625         s8 v;
1626         v.high = 0;
1627         v.low = i;
1628         return v;
1629 #endif
1630 }
1631
1632
1633 float builtin_i2f(s4 a)
1634 {
1635         float f = (float) a;
1636         return f;
1637 }
1638
1639
1640 double builtin_i2d(s4 a)
1641 {
1642         double d = (double) a;
1643         return d;
1644 }
1645
1646
1647 s4 builtin_l2i(s8 l)
1648 {
1649 #if U8_AVAILABLE
1650         return (s4) l;
1651 #else
1652         return l.low;
1653 #endif
1654 }
1655
1656
1657 float builtin_l2f(s8 a)
1658 {
1659 #if U8_AVAILABLE
1660         float f = (float) a;
1661         return f;
1662 #else
1663         return 0.0;
1664 #endif
1665 }
1666
1667
1668 double builtin_l2d(s8 a)
1669 {
1670 #if U8_AVAILABLE
1671         double d = (double) a;
1672         return d;
1673 #else
1674         return 0.0;
1675 #endif
1676 }
1677
1678
1679 s4 builtin_f2i(float a) 
1680 {
1681
1682         return builtin_d2i((double) a);
1683
1684         /*      float f;
1685         
1686                 if (isnanf(a))
1687                 return 0;
1688                 if (finitef(a)) {
1689                 if (a > 2147483647)
1690                 return 2147483647;
1691                 if (a < (-2147483648))
1692                 return (-2147483648);
1693                 return (s4) a;
1694                 }
1695                 f = copysignf((float) 1.0, a);
1696                 if (f > 0)
1697                 return 2147483647;
1698                 return (-2147483648); */
1699 }
1700
1701
1702 s8 builtin_f2l(float a)
1703 {
1704
1705         return builtin_d2l((double) a);
1706
1707         /*      float f;
1708         
1709                 if (finitef(a)) {
1710                 if (a > 9223372036854775807L)
1711                 return 9223372036854775807L;
1712                 if (a < (-9223372036854775808L))
1713                 return (-9223372036854775808L);
1714                 return (s8) a;
1715                 }
1716                 if (isnanf(a))
1717                 return 0;
1718                 f = copysignf((float) 1.0, a);
1719                 if (f > 0)
1720                 return 9223372036854775807L;
1721                 return (-9223372036854775808L); */
1722 }
1723
1724
1725 double builtin_f2d(float a)
1726 {
1727         if (finitef(a)) return (double) a;
1728         else {
1729                 if (isnanf(a))
1730                         return longBitsToDouble(DBL_NAN);
1731                 else
1732                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1733         }
1734 }
1735
1736
1737 s4 builtin_d2i(double a) 
1738
1739         double d;
1740         
1741         if (finite(a)) {
1742                 if (a >= 2147483647)
1743                         return 2147483647;
1744                 if (a <= (-2147483647-1))
1745                         return (-2147483647-1);
1746                 return (s4) a;
1747         }
1748         if (isnan(a))
1749                 return 0;
1750         d = copysign(1.0, a);
1751         if (d > 0)
1752                 return 2147483647;
1753         return (-2147483647-1);
1754 }
1755
1756
1757 s8 builtin_d2l(double a)
1758 {
1759         double d;
1760         
1761         if (finite(a)) {
1762                 if (a >= 9223372036854775807LL)
1763                         return 9223372036854775807LL;
1764                 if (a <= (-9223372036854775807LL-1))
1765                         return (-9223372036854775807LL-1);
1766                 return (s8) a;
1767         }
1768         if (isnan(a))
1769                 return 0;
1770         d = copysign(1.0, a);
1771         if (d > 0)
1772                 return 9223372036854775807LL;
1773         return (-9223372036854775807LL-1);
1774 }
1775
1776
1777 float builtin_d2f(double a)
1778 {
1779         if (finite(a))
1780                 return (float) a;
1781         else {
1782                 if (isnan(a))
1783                         return intBitsToFloat(FLT_NAN);
1784                 else
1785                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1786         }
1787 }
1788
1789
1790 /* used to convert FLT_xxx defines into float values */
1791
1792 inline float intBitsToFloat(s4 i)
1793 {
1794         imm_union imb;
1795
1796         imb.i = i;
1797         return imb.f;
1798 }
1799
1800
1801 /* used to convert DBL_xxx defines into double values */
1802
1803 inline float longBitsToDouble(s8 l)
1804 {
1805         imm_union imb;
1806
1807         imb.l = l;
1808         return imb.d;
1809 }
1810
1811
1812 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1813 {
1814         return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1815 }
1816
1817 s4 builtin_dummy()
1818 {
1819         panic("Internal error: builtin_dummy called (native function is missing)");
1820         return 0; /* for the compiler */
1821 }
1822
1823
1824 inline methodinfo *builtin_asm_get_threadrootmethod() {
1825         return *threadrootmethod;
1826 }
1827
1828
1829 inline void* 
1830 builtin_asm_get_stackframeinfo(){
1831 /*log_text("builtin_asm_get_stackframeinfo()");*/
1832 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1833 #ifdef HAVE___THREAD
1834         return &_thread_nativestackframeinfo; /*support for __thread attribute*/
1835 #else
1836     return &((nativethread*) pthread_getspecific(tkey_stackframeinfo))->_stackframeinfo /*copied from exception handling, is that really */
1837         /*old pthread*/
1838 #endif
1839 #else
1840 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1841         return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1842 #endif
1843 }
1844
1845 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1846 /*      stacktraceelement *el;*/
1847         size_t s;
1848         s=(end-begin);
1849         /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1850         *el=GCNEW(stacktraceelement,s+1);
1851         memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1852         (*el)[s].method=0;
1853         (*el)[s].linenumber=0;
1854         return *el;
1855 }
1856
1857 /*
1858  * These are local overrides for various environment variables in Emacs.
1859  * Please do not remove this and leave it at the end of the file, where
1860  * Emacs will automagically detect them.
1861  * ---------------------------------------------------------------------
1862  * Local variables:
1863  * mode: c
1864  * indent-tabs-mode: t
1865  * c-basic-offset: 4
1866  * tab-width: 4
1867  * End:
1868  */