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