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