6f003d3a0bb435934dd07207d2be1a3572313a93
[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 963 2004-03-15 07:37:49Z 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         assert(blockInts == 0);
1173
1174         ++blockInts;
1175
1176         hashValue = MUTEX_HASH_VALUE(o);
1177         if (mutexHashTable[hashValue].object == o 
1178                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1179                 ++mutexHashTable[hashValue].mutex.count;
1180         else
1181                 internal_lock_mutex_for_object(o);
1182
1183         --blockInts;
1184
1185         assert(blockInts == 0);
1186 #endif
1187 }
1188
1189
1190 void builtin_monitorexit (java_objectheader *o)
1191 {
1192 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1193         int hashValue;
1194
1195         assert(blockInts == 0);
1196
1197         ++blockInts;
1198
1199         hashValue = MUTEX_HASH_VALUE(o);
1200         if (mutexHashTable[hashValue].object == o) {
1201                 if (mutexHashTable[hashValue].mutex.count == 1
1202                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1203                         internal_unlock_mutex_for_object(o);
1204                 else
1205                         --mutexHashTable[hashValue].mutex.count;
1206
1207         } else
1208                 internal_unlock_mutex_for_object(o);
1209
1210         --blockInts;
1211
1212         assert(blockInts == 0);
1213 #endif
1214 }
1215
1216
1217 /*****************************************************************************
1218                           MISCELLANEOUS HELPER FUNCTIONS
1219 *****************************************************************************/
1220
1221
1222
1223 /*********** Functions for integer divisions *****************************
1224  
1225         On some systems (eg. DEC ALPHA), integer division is not supported by the
1226         CPU. These helper functions implement the missing functionality.
1227
1228 ******************************************************************************/
1229
1230 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1231 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1232
1233
1234 /************** Functions for long arithmetics *******************************
1235
1236         On systems where 64 bit Integers are not supported by the CPU, these
1237         functions are needed.
1238
1239 ******************************************************************************/
1240
1241
1242 s8 builtin_ladd(s8 a, s8 b)
1243
1244 #if U8_AVAILABLE
1245         return a + b; 
1246 #else
1247         return builtin_i2l(0);
1248 #endif
1249 }
1250
1251 s8 builtin_lsub(s8 a, s8 b) 
1252
1253 #if U8_AVAILABLE
1254         return a - b; 
1255 #else
1256         return builtin_i2l(0);
1257 #endif
1258 }
1259
1260 s8 builtin_lmul(s8 a, s8 b) 
1261
1262 #if U8_AVAILABLE
1263         return a * b; 
1264 #else
1265         return builtin_i2l(0);
1266 #endif
1267 }
1268
1269 s8 builtin_ldiv(s8 a, s8 b) 
1270
1271 #if U8_AVAILABLE
1272         return a / b; 
1273 #else
1274         return builtin_i2l(0);
1275 #endif
1276 }
1277
1278 s8 builtin_lrem(s8 a, s8 b) 
1279
1280 #if U8_AVAILABLE
1281         return a % b; 
1282 #else
1283         return builtin_i2l(0);
1284 #endif
1285 }
1286
1287 s8 builtin_lshl(s8 a, s4 b) 
1288
1289 #if U8_AVAILABLE
1290         return a << (b & 63);
1291 #else
1292         return builtin_i2l(0);
1293 #endif
1294 }
1295
1296 s8 builtin_lshr(s8 a, s4 b) 
1297
1298 #if U8_AVAILABLE
1299         return a >> (b & 63);
1300 #else
1301         return builtin_i2l(0);
1302 #endif
1303 }
1304
1305 s8 builtin_lushr(s8 a, s4 b) 
1306
1307 #if U8_AVAILABLE
1308         return ((u8) a) >> (b & 63);
1309 #else
1310         return builtin_i2l(0);
1311 #endif
1312 }
1313
1314 s8 builtin_land(s8 a, s8 b) 
1315
1316 #if U8_AVAILABLE
1317         return a & b; 
1318 #else
1319         return builtin_i2l(0);
1320 #endif
1321 }
1322
1323 s8 builtin_lor(s8 a, s8 b) 
1324
1325 #if U8_AVAILABLE
1326         return a | b; 
1327 #else
1328         return builtin_i2l(0);
1329 #endif
1330 }
1331
1332 s8 builtin_lxor(s8 a, s8 b) 
1333
1334 #if U8_AVAILABLE
1335         return a ^ b; 
1336 #else
1337         return builtin_i2l(0);
1338 #endif
1339 }
1340
1341 s8 builtin_lneg(s8 a) 
1342
1343 #if U8_AVAILABLE
1344         return -a;
1345 #else
1346         return builtin_i2l(0);
1347 #endif
1348 }
1349
1350 s4 builtin_lcmp(s8 a, s8 b) 
1351
1352 #if U8_AVAILABLE
1353         if (a < b) return -1;
1354         if (a > b) return 1;
1355         return 0;
1356 #else
1357         return 0;
1358 #endif
1359 }
1360
1361
1362
1363
1364
1365 /*********** Functions for floating point operations *************************/
1366
1367 float builtin_fadd(float a, float b)
1368 {
1369         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1370         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1371         if (finitef(a)) {
1372                 if (finitef(b))
1373                         return a + b;
1374                 else
1375                         return b;
1376         }
1377         else {
1378                 if (finitef(b))
1379                         return a;
1380                 else {
1381                         if (copysignf(1.0, a) == copysignf(1.0, b))
1382                                 return a;
1383                         else
1384                                 return intBitsToFloat(FLT_NAN);
1385                 }
1386         }
1387 }
1388
1389
1390 float builtin_fsub(float a, float b)
1391 {
1392         return builtin_fadd(a, builtin_fneg(b));
1393 }
1394
1395
1396 float builtin_fmul(float a, float b)
1397 {
1398         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1399         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1400         if (finitef(a)) {
1401                 if (finitef(b)) return a * b;
1402                 else {
1403                         if (a == 0) return intBitsToFloat(FLT_NAN);
1404                         else return copysignf(b, copysignf(1.0, b)*a);
1405                 }
1406         }
1407         else {
1408                 if (finitef(b)) {
1409                         if (b == 0) return intBitsToFloat(FLT_NAN);
1410                         else return copysignf(a, copysignf(1.0, a)*b);
1411                 }
1412                 else {
1413                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1414                 }
1415         }
1416 }
1417
1418
1419 float builtin_fdiv(float a, float b)
1420 {
1421         if (finitef(a) && finitef(b)) {
1422                 if (b != 0)
1423                         return a / b;
1424                 else {
1425                         if (a > 0)
1426                                 return intBitsToFloat(FLT_POSINF);
1427                         else if (a < 0)
1428                                 return intBitsToFloat(FLT_NEGINF);
1429                 }
1430         }
1431         return intBitsToFloat(FLT_NAN);
1432 }
1433
1434
1435 float builtin_frem(float a, float b)
1436 {
1437         return fmodf(a, b);
1438 }
1439
1440
1441 float builtin_fneg(float a)
1442 {
1443         if (isnanf(a)) return a;
1444         else {
1445                 if (finitef(a)) return -a;
1446                 else return copysignf(a, -copysignf(1.0, a));
1447         }
1448 }
1449
1450
1451 s4 builtin_fcmpl(float a, float b)
1452 {
1453         if (isnanf(a)) return -1;
1454         if (isnanf(b)) return -1;
1455         if (!finitef(a) || !finitef(b)) {
1456                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1457                 b = finitef(b) ? 0 : copysignf(1.0, b);
1458         }
1459         if (a > b) return 1;
1460         if (a == b) return 0;
1461         return -1;
1462 }
1463
1464
1465 s4 builtin_fcmpg(float a, float b)
1466 {
1467         if (isnanf(a)) return 1;
1468         if (isnanf(b)) return 1;
1469         if (!finitef(a) || !finitef(b)) {
1470                 a = finitef(a) ? 0 : copysignf(1.0, a);
1471                 b = finitef(b) ? 0 : copysignf(1.0, b);
1472         }
1473         if (a > b) return 1;
1474         if (a == b) return 0;
1475         return -1;
1476 }
1477
1478
1479
1480 /************************* Functions for doubles ****************************/
1481
1482 double builtin_dadd(double a, double b)
1483 {
1484         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1485         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1486         if (finite(a)) {
1487                 if (finite(b)) return a + b;
1488                 else return b;
1489         }
1490         else {
1491                 if (finite(b)) return a;
1492                 else {
1493                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1494                         else return longBitsToDouble(DBL_NAN);
1495                 }
1496         }
1497 }
1498
1499
1500 double builtin_dsub(double a, double b)
1501 {
1502         return builtin_dadd(a, builtin_dneg(b));
1503 }
1504
1505
1506 double builtin_dmul(double a, double b)
1507 {
1508         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1509         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1510         if (finite(a)) {
1511                 if (finite(b)) return a * b;
1512                 else {
1513                         if (a == 0) return longBitsToDouble(DBL_NAN);
1514                         else return copysign(b, copysign(1.0, b) * a);
1515                 }
1516         }
1517         else {
1518                 if (finite(b)) {
1519                         if (b == 0) return longBitsToDouble(DBL_NAN);
1520                         else return copysign(a, copysign(1.0, a) * b);
1521                 }
1522                 else {
1523                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1524                 }
1525         }
1526 }
1527
1528
1529 double builtin_ddiv(double a, double b)
1530 {
1531         if (finite(a)) {
1532                 if (finite(b)) {
1533                         return a / b;
1534
1535                 } else {
1536                         if (isnan(b))
1537                                 return longBitsToDouble(DBL_NAN);
1538                         else
1539                                 return copysign(0.0, b);
1540                 }
1541
1542         } else {
1543                 if (finite(b)) {
1544                         if (a > 0)
1545                                 return longBitsToDouble(DBL_POSINF);
1546                         else if (a < 0)
1547                                 return longBitsToDouble(DBL_NEGINF);
1548
1549                 } else
1550                         return longBitsToDouble(DBL_NAN);
1551         }
1552
1553 /*      if (finite(a) && finite(b)) { */
1554 /*              if (b != 0) */
1555 /*                      return a / b; */
1556 /*              else { */
1557 /*                      if (a > 0) */
1558 /*                              return longBitsToDouble(DBL_POSINF); */
1559 /*                      else if (a < 0) */
1560 /*                              return longBitsToDouble(DBL_NEGINF); */
1561 /*              } */
1562 /*      } */
1563
1564         /* keep compiler happy */
1565         return 0;
1566 }
1567
1568
1569 double builtin_drem(double a, double b)
1570 {
1571         return fmod(a, b);
1572 }
1573
1574
1575 double builtin_dneg(double a)
1576 {
1577         if (isnan(a)) return a;
1578         else {
1579                 if (finite(a)) return -a;
1580                 else return copysign(a, -copysign(1.0, a));
1581         }
1582 }
1583
1584
1585 s4 builtin_dcmpl(double a, double b)
1586 {
1587         if (isnan(a)) return -1;
1588         if (isnan(b)) return -1;
1589         if (!finite(a) || !finite(b)) {
1590                 a = finite(a) ? 0 : copysign(1.0, a);
1591                 b = finite(b) ? 0 : copysign(1.0, b);
1592         }
1593         if (a > b) return 1;
1594         if (a == b) return 0;
1595         return -1;
1596 }
1597
1598
1599 s4 builtin_dcmpg(double a, double b)
1600 {
1601         if (isnan(a)) return 1;
1602         if (isnan(b)) return 1;
1603         if (!finite(a) || !finite(b)) {
1604                 a = finite(a) ? 0 : copysign(1.0, a);
1605                 b = finite(b) ? 0 : copysign(1.0, b);
1606         }
1607         if (a > b) return 1;
1608         if (a == b) return 0;
1609         return -1;
1610 }
1611
1612
1613 /*********************** Conversion operations ****************************/
1614
1615 s8 builtin_i2l(s4 i)
1616 {
1617 #if U8_AVAILABLE
1618         return i;
1619 #else
1620         s8 v;
1621         v.high = 0;
1622         v.low = i;
1623         return v;
1624 #endif
1625 }
1626
1627
1628 float builtin_i2f(s4 a)
1629 {
1630         float f = (float) a;
1631         return f;
1632 }
1633
1634
1635 double builtin_i2d(s4 a)
1636 {
1637         double d = (double) a;
1638         return d;
1639 }
1640
1641
1642 s4 builtin_l2i(s8 l)
1643 {
1644 #if U8_AVAILABLE
1645         return (s4) l;
1646 #else
1647         return l.low;
1648 #endif
1649 }
1650
1651
1652 float builtin_l2f(s8 a)
1653 {
1654 #if U8_AVAILABLE
1655         float f = (float) a;
1656         return f;
1657 #else
1658         return 0.0;
1659 #endif
1660 }
1661
1662
1663 double builtin_l2d(s8 a)
1664 {
1665 #if U8_AVAILABLE
1666         double d = (double) a;
1667         return d;
1668 #else
1669         return 0.0;
1670 #endif
1671 }
1672
1673
1674 s4 builtin_f2i(float a) 
1675 {
1676
1677         return builtin_d2i((double) a);
1678
1679         /*      float f;
1680         
1681                 if (isnanf(a))
1682                 return 0;
1683                 if (finitef(a)) {
1684                 if (a > 2147483647)
1685                 return 2147483647;
1686                 if (a < (-2147483648))
1687                 return (-2147483648);
1688                 return (s4) a;
1689                 }
1690                 f = copysignf((float) 1.0, a);
1691                 if (f > 0)
1692                 return 2147483647;
1693                 return (-2147483648); */
1694 }
1695
1696
1697 s8 builtin_f2l(float a)
1698 {
1699
1700         return builtin_d2l((double) a);
1701
1702         /*      float f;
1703         
1704                 if (finitef(a)) {
1705                 if (a > 9223372036854775807L)
1706                 return 9223372036854775807L;
1707                 if (a < (-9223372036854775808L))
1708                 return (-9223372036854775808L);
1709                 return (s8) a;
1710                 }
1711                 if (isnanf(a))
1712                 return 0;
1713                 f = copysignf((float) 1.0, a);
1714                 if (f > 0)
1715                 return 9223372036854775807L;
1716                 return (-9223372036854775808L); */
1717 }
1718
1719
1720 double builtin_f2d(float a)
1721 {
1722         if (finitef(a)) return (double) a;
1723         else {
1724                 if (isnanf(a))
1725                         return longBitsToDouble(DBL_NAN);
1726                 else
1727                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1728         }
1729 }
1730
1731
1732 s4 builtin_d2i(double a) 
1733
1734         double d;
1735         
1736         if (finite(a)) {
1737                 if (a >= 2147483647)
1738                         return 2147483647;
1739                 if (a <= (-2147483647-1))
1740                         return (-2147483647-1);
1741                 return (s4) a;
1742         }
1743         if (isnan(a))
1744                 return 0;
1745         d = copysign(1.0, a);
1746         if (d > 0)
1747                 return 2147483647;
1748         return (-2147483647-1);
1749 }
1750
1751
1752 s8 builtin_d2l(double a)
1753 {
1754         double d;
1755         
1756         if (finite(a)) {
1757                 if (a >= 9223372036854775807LL)
1758                         return 9223372036854775807LL;
1759                 if (a <= (-9223372036854775807LL-1))
1760                         return (-9223372036854775807LL-1);
1761                 return (s8) a;
1762         }
1763         if (isnan(a))
1764                 return 0;
1765         d = copysign(1.0, a);
1766         if (d > 0)
1767                 return 9223372036854775807LL;
1768         return (-9223372036854775807LL-1);
1769 }
1770
1771
1772 float builtin_d2f(double a)
1773 {
1774         if (finite(a))
1775                 return (float) a;
1776         else {
1777                 if (isnan(a))
1778                         return intBitsToFloat(FLT_NAN);
1779                 else
1780                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1781         }
1782 }
1783
1784
1785 /* used to convert FLT_xxx defines into float values */
1786
1787 inline float intBitsToFloat(s4 i)
1788 {
1789         imm_union imb;
1790
1791         imb.i = i;
1792         return imb.f;
1793 }
1794
1795
1796 /* used to convert DBL_xxx defines into double values */
1797
1798 inline float longBitsToDouble(s8 l)
1799 {
1800         imm_union imb;
1801
1802         imb.l = l;
1803         return imb.d;
1804 }
1805
1806
1807 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1808 {
1809         return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1810 }
1811
1812 s4 builtin_dummy()
1813 {
1814         panic("Internal error: builtin_dummy called (native function is missing)");
1815         return 0; /* for the compiler */
1816 }
1817
1818
1819 inline methodinfo *builtin_asm_get_threadrootmethod() {
1820         return *threadrootmethod;
1821 }
1822
1823
1824 inline void* 
1825 builtin_asm_get_stackframeinfo(){
1826 /*log_text("builtin_asm_get_stackframeinfo()");*/
1827 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1828 #ifdef HAVE___THREAD
1829         return &_thread_nativestackframeinfo; /*support for __thread attribute*/
1830 #else
1831     return &((nativethread*) pthread_getspecific(tkey_stackframeinfo))->_stackframeinfo /*copied from exception handling, is that really */
1832         /*old pthread*/
1833 #endif
1834 #else
1835 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1836         return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1837 #endif
1838 }
1839
1840 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1841 /*      stacktraceelement *el;*/
1842         size_t s;
1843         s=(end-begin);
1844         /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1845         *el=GCNEW(stacktraceelement,s+1);
1846         memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1847         (*el)[s].method=0;
1848         (*el)[s].linenumber=0;
1849         return *el;
1850 }
1851
1852 /*
1853  * These are local overrides for various environment variables in Emacs.
1854  * Please do not remove this and leave it at the end of the file, where
1855  * Emacs will automagically detect them.
1856  * ---------------------------------------------------------------------
1857  * Local variables:
1858  * mode: c
1859  * indent-tabs-mode: t
1860  * c-basic-offset: 4
1861  * tab-width: 4
1862  * End:
1863  */