renamed vftbl type to vftbl_t
[cacao.git] / src / vm / 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 1296 2004-07-10 17:02:15Z stefan $
38
39 */
40
41
42 #include "global.h"
43 #include <assert.h>
44 #include <string.h>
45 #include <math.h>
46 #include "options.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/logging.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         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 *local_exceptionptr)
266 {
267         if (verbose) {
268                 char logtext[MAXLOGTEXT];
269                 sprintf(logtext, "Builtin exception thrown: ");
270                 if (local_exceptionptr) {
271                         java_lang_Throwable *t = (java_lang_Throwable *) local_exceptionptr;
272
273                         utf_sprint_classname(logtext + strlen(logtext),
274                                                                  local_exceptionptr->vftbl->class->name);
275
276                         if (t->detailMessage) {
277                                 sprintf(logtext + strlen(logtext), ": %s",
278                                                 javastring_tochar(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 = local_exceptionptr;
288
289         return local_exceptionptr;
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
485         return o;
486 }
487
488
489 /********************** Function: builtin_newarray **************************
490
491         Creates an array with the given vftbl on the heap.
492
493         Return value:  pointer to the array or NULL if no memory is available
494
495     CAUTION: The given vftbl must be the vftbl of the *array* class,
496     not of the element class.
497
498 *****************************************************************************/
499
500 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
501 {
502         java_arrayheader *a;
503         arraydescriptor *desc;
504         s4 dataoffset;
505         s4 componentsize;
506         s4 actualsize;
507
508         desc = arrayvftbl->arraydesc;
509         dataoffset = desc->dataoffset;
510         componentsize = desc->componentsize;
511
512         if (size < 0) {
513                 *exceptionptr =
514                         new_exception(string_java_lang_NegativeArraySizeException);
515                 return NULL;
516         }
517
518 #ifdef SIZE_FROM_CLASSINFO
519         actualsize = align_size(dataoffset + size * componentsize);
520         actualsize = dataoffset + size * componentsize;
521 #endif
522
523         if (((u4) actualsize) < ((u4) size)) { /* overflow */
524                 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
525                 return NULL;
526         }
527
528         a = heap_allocate(actualsize,
529                                           (desc->arraytype == ARRAYTYPE_OBJECT),
530                                           NULL);
531
532         if (!a)
533                 return NULL;
534
535         memset(a, 0, actualsize);
536
537         a->objheader.vftbl = arrayvftbl;
538         a->size = size;
539 #ifdef SIZE_FROM_CLASSINFO
540         a->alignedsize = actualsize;
541 #endif
542
543         return a;
544 }
545
546
547 /********************** Function: builtin_anewarray *************************
548
549         Creates an array of references to the given class type on the heap.
550
551         Return value: pointer to the array or NULL if no memory is available
552
553     XXX This function does not do The Right Thing, because it uses a
554     classinfo pointer at runtime. builtin_newarray should be used
555     instead.
556
557 *****************************************************************************/
558
559 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
560 {
561         /* is class loaded */
562         if (!component->loaded)
563                 if (!class_load(component))
564                         return NULL;
565
566         /* is class linked */
567         if (!component->linked)
568                 if (!class_link(component))
569                         return NULL;
570
571         return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
572 }
573
574
575 /******************** Function: builtin_newarray_int ***********************
576
577         Creates an array of 32 bit Integers on the heap.
578
579         Return value:  pointer to the array or NULL if no memory is available
580
581 *****************************************************************************/
582
583 java_intarray *builtin_newarray_int(s4 size)
584 {
585         return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
586 }
587
588
589 /******************** Function: builtin_newarray_long ***********************
590
591         Creates an array of 64 bit Integers on the heap.
592
593         Return value:  pointer to the array or NULL if no memory is available
594
595 *****************************************************************************/
596
597 java_longarray *builtin_newarray_long(s4 size)
598 {
599         return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
600 }
601
602
603 /******************** function: builtin_newarray_float ***********************
604
605         Creates an array of 32 bit IEEE floats on the heap.
606
607         Return value:  pointer to the array or NULL if no memory is available
608
609 *****************************************************************************/
610
611 java_floatarray *builtin_newarray_float(s4 size)
612 {
613         return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
614 }
615
616
617 /******************** function: builtin_newarray_double ***********************
618
619         Creates an array of 64 bit IEEE floats on the heap.
620
621         Return value:  pointer to the array or NULL if no memory is available
622
623 *****************************************************************************/
624
625 java_doublearray *builtin_newarray_double(s4 size)
626 {
627         return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
628 }
629
630
631 /******************** function: builtin_newarray_byte ***********************
632
633         Creates an array of 8 bit Integers on the heap.
634
635         Return value:  pointer to the array or NULL if no memory is available
636
637 *****************************************************************************/
638
639 java_bytearray *builtin_newarray_byte(s4 size)
640 {
641         return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
642 }
643
644
645 /******************** function: builtin_newarray_char ************************
646
647         Creates an array of characters on the heap.
648
649         Return value:  pointer to the array or NULL if no memory is available
650
651 *****************************************************************************/
652
653 java_chararray *builtin_newarray_char(s4 size)
654 {
655         return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
656 }
657
658
659 /******************** function: builtin_newarray_short ***********************
660
661         Creates an array of 16 bit Integers on the heap.
662
663         Return value:  pointer to the array or NULL if no memory is available
664
665 *****************************************************************************/
666
667 java_shortarray *builtin_newarray_short(s4 size)
668 {
669         return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
670 }
671
672
673 /******************** function: builtin_newarray_boolean ************************
674
675         Creates an array of bytes on the heap. The array is designated as an array
676         of booleans (important for casts)
677         
678         Return value:  pointer to the array or NULL if no memory is available
679
680 *****************************************************************************/
681
682 java_booleanarray *builtin_newarray_boolean(s4 size)
683 {
684         return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
685 }
686
687
688 /**************** function: builtin_nmultianewarray ***************************
689
690         Creates a multi-dimensional array on the heap. The dimensions are passed in
691         an array of longs.
692
693     Arguments:
694         n............number of dimensions to create
695         arrayvftbl...vftbl of the array class
696         dims.........array containing the size of each dimension to create
697
698         Return value:  pointer to the array or NULL if no memory is available
699
700 ******************************************************************************/
701
702 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
703 /*  java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
704 {
705         s4 size, i;
706         java_arrayheader *a;
707         vftbl_t *componentvftbl;
708
709 /*      utf_display(arrayclass->name); */
710
711 /*      class_load(arrayclass); */
712 /*      class_link(arrayclass); */
713         
714         /* create this dimension */
715         size = (s4) dims[0];
716         a = builtin_newarray(size, arrayvftbl);
717 /*      a = builtin_newarray(size, arrayclass->vftbl); */
718
719         if (!a)
720                 return NULL;
721
722         /* if this is the last dimension return */
723         if (!--n)
724                 return a;
725
726         /* get the vftbl of the components to create */
727         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
728 /*      component = arrayclass->vftbl->arraydesc; */
729
730         /* The verifier guarantees this. */
731         /* if (!componentvftbl) */
732         /*      panic ("multianewarray with too many dimensions"); */
733
734         /* create the component arrays */
735         for (i = 0; i < size; i++) {
736                 java_arrayheader *ea = 
737                         builtin_nmultianewarray(n, componentvftbl, dims + 1);
738
739                 if (!ea)
740                         return NULL;
741                 
742                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
743         }
744
745         return a;
746 }
747
748
749 /*****************************************************************************
750                                           METHOD LOGGING
751
752         Various functions for printing a message at method entry or exit (for
753         debugging)
754         
755 *****************************************************************************/
756
757 u4 methodindent = 0;
758
759 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
760                                                                                    methodinfo *method,
761                                                                                    int *pos,
762                                                                                    int line,
763                                                                                    int noindent)
764 {
765         if (!noindent) {
766                 if (methodindent)
767                         methodindent--;
768                 else
769                         log_text("WARNING: unmatched methodindent--");
770         }
771         if (verbose || runverbose || verboseexception) {
772                 if (_exceptionptr) {
773                         printf("Exception ");
774                         utf_display_classname(_exceptionptr->vftbl->class->name);
775
776                 } else {
777                         printf("Some Throwable");
778                 }
779                 printf(" thrown in ");
780
781                 if (method) {
782                         utf_display_classname(method->class->name);
783                         printf(".");
784                         utf_display(method->name);
785                         if (method->flags & ACC_SYNCHRONIZED)
786                                 printf("(SYNC");
787                         else
788                                 printf("(NOSYNC");
789                         if (method->flags & ACC_NATIVE) {
790                                 printf(",NATIVE");
791                                 printf(")(%p) at position %p\n", method->entrypoint, pos);
792                         } else {
793                                 printf(")(%p) at position %p (",method->entrypoint,pos);
794                                 if (method->class->sourcefile==NULL)
795                                         printf("<NO CLASSFILE INFORMATION>");
796                                 else
797                                         utf_display(method->class->sourcefile);
798                                 printf(":%d)\n",line);
799                         }
800
801                 } else
802                         printf("call_java_method\n");
803                 fflush (stdout);
804         }
805
806         return _exceptionptr;
807 }
808
809
810 #ifdef TRACE_ARGS_NUM
811 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
812 #if TRACE_ARGS_NUM > 6
813                                                 s8 a6, s8 a7,
814 #endif
815                                                 methodinfo *method)
816 {
817         int i;
818         char logtext[MAXLOGTEXT];
819         for (i = 0; i < methodindent; i++)
820                 logtext[i] = '\t';
821
822         sprintf(logtext + methodindent, "called: ");
823         utf_sprint_classname(logtext + strlen(logtext), method->class->name);
824         sprintf(logtext + strlen(logtext), ".");
825         utf_sprint(logtext + strlen(logtext), method->name);
826         utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
827
828         if ( method->flags & ACC_PUBLIC )       sprintf (logtext + strlen(logtext)," PUBLIC");
829         if ( method->flags & ACC_PRIVATE )      sprintf (logtext + strlen(logtext)," PRIVATE");
830         if ( method->flags & ACC_PROTECTED )    sprintf (logtext + strlen(logtext)," PROTECTED");
831         if ( method->flags & ACC_STATIC )       sprintf (logtext + strlen(logtext)," STATIC");
832         if ( method->flags & ACC_FINAL )        sprintf (logtext + strlen(logtext)," FINAL");
833         if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
834         if ( method->flags & ACC_VOLATILE )     sprintf (logtext + strlen(logtext)," VOLATILE");
835         if ( method->flags & ACC_TRANSIENT )    sprintf (logtext + strlen(logtext)," TRANSIENT");
836         if ( method->flags & ACC_NATIVE )       sprintf (logtext + strlen(logtext)," NATIVE");
837         if ( method->flags & ACC_INTERFACE )    sprintf (logtext + strlen(logtext)," INTERFACE");
838         if ( method->flags & ACC_ABSTRACT )     sprintf (logtext + strlen(logtext)," ABSTRACT");
839         
840
841         sprintf(logtext + strlen(logtext), "(");
842
843         switch (method->paramcount) {
844         case 0:
845                 break;
846
847 #if defined(__I386__) || defined(__POWERPC__)
848         case 1:
849                 sprintf(logtext+strlen(logtext), "%llx", a0);
850                 break;
851
852         case 2:
853                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
854                 break;
855
856         case 3:
857                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
858                 break;
859
860         case 4:
861                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
862                                 a0,   a1,   a2,   a3);
863                 break;
864
865         case 5:
866                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
867                                 a0,   a1,   a2,   a3,   a4);
868                 break;
869
870         case 6:
871                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
872                                 a0,   a1,   a2,   a3,   a4,   a5);
873                 break;
874
875 #if TRACE_ARGS_NUM > 6
876         case 7:
877                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
878                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
879                 break;
880
881         case 8:
882                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
883                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
884                 break;
885
886         default:
887                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
888                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   method->paramcount - 8);
889                 break;
890 #else
891         default:
892                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
893                                 a0,   a1,   a2,   a3,   a4,   a5,   method->paramcount - 6);
894                 break;
895 #endif
896 #else
897         case 1:
898                 sprintf(logtext+strlen(logtext), "%lx", a0);
899                 break;
900
901         case 2:
902                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
903                 break;
904
905         case 3:
906                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
907                 break;
908
909         case 4:
910                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
911                                 a0,  a1,  a2,  a3);
912                 break;
913
914         case 5:
915                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
916                                 a0,  a1,  a2,  a3,  a4);
917                 break;
918
919         case 6:
920                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
921                                 a0,  a1,  a2,  a3,  a4,  a5);
922                 break;
923
924 #if TRACE_ARGS_NUM > 6
925         case 7:
926                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
927                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
928                 break;
929
930         case 8:
931                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
932                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
933                 break;
934
935         default:
936                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
937                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  method->paramcount - 8);
938                 break;
939 #else
940         default:
941                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
942                                 a0,  a1,  a2,  a3,  a4,  a5,   method->paramcount - 6);
943                 break;
944 #endif
945 #endif
946         }
947
948         sprintf(logtext + strlen(logtext), ")");
949         log_text(logtext);
950
951         methodindent++;
952 }
953 #endif
954
955
956 void builtin_displaymethodstart(methodinfo *method)
957 {
958         char logtext[MAXLOGTEXT];
959         sprintf(logtext, "                                                                                              ");
960         sprintf(logtext + methodindent, "called: ");
961         utf_sprint(logtext + strlen(logtext), method->class->name);
962         sprintf(logtext + strlen(logtext), ".");
963         utf_sprint(logtext + strlen(logtext), method->name);
964         utf_sprint(logtext + strlen(logtext), method->descriptor);
965
966         if ( method->flags & ACC_PUBLIC )       sprintf (logtext + strlen(logtext)," PUBLIC");
967         if ( method->flags & ACC_PRIVATE )      sprintf (logtext + strlen(logtext)," PRIVATE");
968         if ( method->flags & ACC_PROTECTED )    sprintf (logtext + strlen(logtext)," PROTECTED");
969         if ( method->flags & ACC_STATIC )       sprintf (logtext + strlen(logtext)," STATIC");
970         if ( method->flags & ACC_FINAL )        sprintf (logtext + strlen(logtext)," FINAL");
971         if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
972         if ( method->flags & ACC_VOLATILE )     sprintf (logtext + strlen(logtext)," VOLATILE");
973         if ( method->flags & ACC_TRANSIENT )    sprintf (logtext + strlen(logtext)," TRANSIENT");
974         if ( method->flags & ACC_NATIVE )       sprintf (logtext + strlen(logtext)," NATIVE");
975         if ( method->flags & ACC_INTERFACE )    sprintf (logtext + strlen(logtext)," INTERFACE");
976         if ( method->flags & ACC_ABSTRACT )     sprintf (logtext + strlen(logtext)," ABSTRACT");
977
978         log_text(logtext);
979         methodindent++;
980 }
981
982
983 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
984 {
985         int i;
986         char logtext[MAXLOGTEXT];
987         for (i = 0; i < methodindent; i++)
988                 logtext[i] = '\t';
989         if (methodindent)
990                 methodindent--;
991         else
992                 log_text("WARNING: unmatched methodindent--");
993
994         sprintf(logtext + methodindent, "finished: ");
995         utf_sprint_classname(logtext + strlen(logtext), method->class->name);
996         sprintf(logtext + strlen(logtext), ".");
997         utf_sprint(logtext + strlen(logtext), method->name);
998         utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
999
1000         switch (method->returntype) {
1001         case TYPE_INT:
1002                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1003                 break;
1004
1005         case TYPE_LONG:
1006 #if defined(__I386__) || defined(__POWERPC__)
1007                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1008 #else
1009                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1010 #endif
1011                 break;
1012
1013         case TYPE_ADDRESS:
1014 #if defined(__I386__) || defined(__POWERPC__)
1015                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1016 #else
1017                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1018 #endif
1019                 break;
1020
1021         case TYPE_FLOAT:
1022                 sprintf(logtext + strlen(logtext), "->%g", f);
1023                 break;
1024
1025         case TYPE_DOUBLE:
1026                 sprintf(logtext + strlen(logtext), "->%g", d);
1027                 break;
1028         }
1029         log_text(logtext);
1030 }
1031
1032
1033 /****************************************************************************
1034                          SYNCHRONIZATION FUNCTIONS
1035 *****************************************************************************/
1036
1037 /*
1038  * Lock the mutex of an object.
1039  */
1040 void internal_lock_mutex_for_object(java_objectheader *object)
1041 {
1042 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1043         mutexHashEntry *entry;
1044         int hashValue;
1045
1046         assert(object != 0);
1047
1048         hashValue = MUTEX_HASH_VALUE(object);
1049         entry = &mutexHashTable[hashValue];
1050
1051         if (entry->object != 0) {
1052                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1053                         entry->object = 0;
1054                         entry->mutex.holder = 0;
1055                         entry->mutex.count = 0;
1056                         entry->mutex.muxWaiters = 0;
1057
1058                 } else {
1059                         while (entry->next != 0 && entry->object != object)
1060                                 entry = entry->next;
1061
1062                         if (entry->object != object) {
1063                                 entry->next = firstFreeOverflowEntry;
1064                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1065
1066                                 entry = entry->next;
1067                                 entry->object = 0;
1068                                 entry->next = 0;
1069                                 assert(entry->conditionCount == 0);
1070                         }
1071                 }
1072
1073         } else {
1074                 entry->mutex.holder = 0;
1075                 entry->mutex.count = 0;
1076                 entry->mutex.muxWaiters = 0;
1077         }
1078
1079         if (entry->object == 0)
1080                 entry->object = object;
1081         
1082         internal_lock_mutex(&entry->mutex);
1083 #endif
1084 }
1085
1086
1087 /*
1088  * Unlocks the mutex of an object.
1089  */
1090 void internal_unlock_mutex_for_object (java_objectheader *object)
1091 {
1092 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1093         int hashValue;
1094         mutexHashEntry *entry;
1095
1096         hashValue = MUTEX_HASH_VALUE(object);
1097         entry = &mutexHashTable[hashValue];
1098
1099         if (entry->object == object) {
1100                 internal_unlock_mutex(&entry->mutex);
1101
1102         } else {
1103                 while (entry->next != 0 && entry->next->object != object)
1104                         entry = entry->next;
1105
1106                 assert(entry->next != 0);
1107
1108                 internal_unlock_mutex(&entry->next->mutex);
1109
1110                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1111                         mutexHashEntry *unlinked = entry->next;
1112
1113                         entry->next = unlinked->next;
1114                         unlinked->next = firstFreeOverflowEntry;
1115                         firstFreeOverflowEntry = unlinked;
1116                 }
1117         }
1118 #endif
1119 }
1120
1121
1122 void builtin_monitorenter(java_objectheader *o)
1123 {
1124 #if defined(USE_THREADS)
1125 #if !defined(NATIVE_THREADS)
1126         int hashValue;
1127
1128         ++blockInts;
1129
1130         hashValue = MUTEX_HASH_VALUE(o);
1131         if (mutexHashTable[hashValue].object == o 
1132                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1133                 ++mutexHashTable[hashValue].mutex.count;
1134         else
1135                 internal_lock_mutex_for_object(o);
1136
1137         --blockInts;
1138 #else
1139         monitorEnter((threadobject *) THREADOBJECT, o);
1140 #endif
1141 #endif
1142 }
1143
1144 /*
1145  * Locks the class object - needed for static synchronized methods.
1146  * The use_class_as_object call is needed in order to circumvent a
1147  * possible deadlock with builtin_monitorenter called by another
1148  * thread calling use_class_as_object.
1149  */
1150 void builtin_staticmonitorenter(classinfo *c)
1151 {
1152         use_class_as_object(c);
1153         builtin_monitorenter(&c->header);
1154 }
1155
1156
1157 void builtin_monitorexit(java_objectheader *o)
1158 {
1159 #if defined(USE_THREADS)
1160 #if !defined(NATIVE_THREADS)
1161         int hashValue;
1162
1163         ++blockInts;
1164
1165         hashValue = MUTEX_HASH_VALUE(o);
1166         if (mutexHashTable[hashValue].object == o) {
1167                 if (mutexHashTable[hashValue].mutex.count == 1
1168                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1169                         internal_unlock_mutex_for_object(o);
1170                 else
1171                         --mutexHashTable[hashValue].mutex.count;
1172
1173         } else
1174                 internal_unlock_mutex_for_object(o);
1175
1176         --blockInts;
1177 #else
1178         monitorExit((threadobject *) THREADOBJECT, o);
1179 #endif
1180 #endif
1181 }
1182
1183
1184 /*****************************************************************************
1185                           MISCELLANEOUS HELPER FUNCTIONS
1186 *****************************************************************************/
1187
1188
1189
1190 /*********** Functions for integer divisions *****************************
1191  
1192         On some systems (eg. DEC ALPHA), integer division is not supported by the
1193         CPU. These helper functions implement the missing functionality.
1194
1195 ******************************************************************************/
1196
1197 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1198 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1199
1200
1201 /************** Functions for long arithmetics *******************************
1202
1203         On systems where 64 bit Integers are not supported by the CPU, these
1204         functions are needed.
1205
1206 ******************************************************************************/
1207
1208
1209 s8 builtin_ladd(s8 a, s8 b)
1210
1211 #if U8_AVAILABLE
1212         return a + b; 
1213 #else
1214         return builtin_i2l(0);
1215 #endif
1216 }
1217
1218 s8 builtin_lsub(s8 a, s8 b) 
1219
1220 #if U8_AVAILABLE
1221         return a - b; 
1222 #else
1223         return builtin_i2l(0);
1224 #endif
1225 }
1226
1227 s8 builtin_lmul(s8 a, s8 b) 
1228
1229 #if U8_AVAILABLE
1230         return a * b; 
1231 #else
1232         return builtin_i2l(0);
1233 #endif
1234 }
1235
1236 s8 builtin_ldiv(s8 a, s8 b) 
1237
1238 #if U8_AVAILABLE
1239         return a / b; 
1240 #else
1241         return builtin_i2l(0);
1242 #endif
1243 }
1244
1245 s8 builtin_lrem(s8 a, s8 b) 
1246
1247 #if U8_AVAILABLE
1248         return a % b; 
1249 #else
1250         return builtin_i2l(0);
1251 #endif
1252 }
1253
1254 s8 builtin_lshl(s8 a, s4 b) 
1255
1256 #if U8_AVAILABLE
1257         return a << (b & 63);
1258 #else
1259         return builtin_i2l(0);
1260 #endif
1261 }
1262
1263 s8 builtin_lshr(s8 a, s4 b) 
1264
1265 #if U8_AVAILABLE
1266         return a >> (b & 63);
1267 #else
1268         return builtin_i2l(0);
1269 #endif
1270 }
1271
1272 s8 builtin_lushr(s8 a, s4 b) 
1273
1274 #if U8_AVAILABLE
1275         return ((u8) a) >> (b & 63);
1276 #else
1277         return builtin_i2l(0);
1278 #endif
1279 }
1280
1281 s8 builtin_land(s8 a, s8 b) 
1282
1283 #if U8_AVAILABLE
1284         return a & b; 
1285 #else
1286         return builtin_i2l(0);
1287 #endif
1288 }
1289
1290 s8 builtin_lor(s8 a, s8 b) 
1291
1292 #if U8_AVAILABLE
1293         return a | b; 
1294 #else
1295         return builtin_i2l(0);
1296 #endif
1297 }
1298
1299 s8 builtin_lxor(s8 a, s8 b) 
1300
1301 #if U8_AVAILABLE
1302         return a ^ b; 
1303 #else
1304         return builtin_i2l(0);
1305 #endif
1306 }
1307
1308 s8 builtin_lneg(s8 a) 
1309
1310 #if U8_AVAILABLE
1311         return -a;
1312 #else
1313         return builtin_i2l(0);
1314 #endif
1315 }
1316
1317 s4 builtin_lcmp(s8 a, s8 b) 
1318
1319 #if U8_AVAILABLE
1320         if (a < b) return -1;
1321         if (a > b) return 1;
1322         return 0;
1323 #else
1324         return 0;
1325 #endif
1326 }
1327
1328
1329
1330
1331
1332 /*********** Functions for floating point operations *************************/
1333
1334 float builtin_fadd(float a, float b)
1335 {
1336         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1337         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1338         if (finitef(a)) {
1339                 if (finitef(b))
1340                         return a + b;
1341                 else
1342                         return b;
1343         }
1344         else {
1345                 if (finitef(b))
1346                         return a;
1347                 else {
1348                         if (copysignf(1.0, a) == copysignf(1.0, b))
1349                                 return a;
1350                         else
1351                                 return intBitsToFloat(FLT_NAN);
1352                 }
1353         }
1354 }
1355
1356
1357 float builtin_fsub(float a, float b)
1358 {
1359         return builtin_fadd(a, builtin_fneg(b));
1360 }
1361
1362
1363 float builtin_fmul(float a, float b)
1364 {
1365         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1366         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1367         if (finitef(a)) {
1368                 if (finitef(b)) return a * b;
1369                 else {
1370                         if (a == 0) return intBitsToFloat(FLT_NAN);
1371                         else return copysignf(b, copysignf(1.0, b)*a);
1372                 }
1373         }
1374         else {
1375                 if (finitef(b)) {
1376                         if (b == 0) return intBitsToFloat(FLT_NAN);
1377                         else return copysignf(a, copysignf(1.0, a)*b);
1378                 }
1379                 else {
1380                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1381                 }
1382         }
1383 }
1384
1385
1386 float builtin_fdiv(float a, float b)
1387 {
1388         if (finitef(a) && finitef(b)) {
1389                 if (b != 0)
1390                         return a / b;
1391                 else {
1392                         if (a > 0)
1393                                 return intBitsToFloat(FLT_POSINF);
1394                         else if (a < 0)
1395                                 return intBitsToFloat(FLT_NEGINF);
1396                 }
1397         }
1398         return intBitsToFloat(FLT_NAN);
1399 }
1400
1401
1402 float builtin_frem(float a, float b)
1403 {
1404         return fmodf(a, b);
1405 }
1406
1407
1408 float builtin_fneg(float a)
1409 {
1410         if (isnanf(a)) return a;
1411         else {
1412                 if (finitef(a)) return -a;
1413                 else return copysignf(a, -copysignf(1.0, a));
1414         }
1415 }
1416
1417
1418 s4 builtin_fcmpl(float a, float b)
1419 {
1420         if (isnanf(a)) return -1;
1421         if (isnanf(b)) return -1;
1422         if (!finitef(a) || !finitef(b)) {
1423                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1424                 b = finitef(b) ? 0 : copysignf(1.0, b);
1425         }
1426         if (a > b) return 1;
1427         if (a == b) return 0;
1428         return -1;
1429 }
1430
1431
1432 s4 builtin_fcmpg(float a, float b)
1433 {
1434         if (isnanf(a)) return 1;
1435         if (isnanf(b)) return 1;
1436         if (!finitef(a) || !finitef(b)) {
1437                 a = finitef(a) ? 0 : copysignf(1.0, a);
1438                 b = finitef(b) ? 0 : copysignf(1.0, b);
1439         }
1440         if (a > b) return 1;
1441         if (a == b) return 0;
1442         return -1;
1443 }
1444
1445
1446
1447 /************************* Functions for doubles ****************************/
1448
1449 double builtin_dadd(double a, double b)
1450 {
1451         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1452         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1453         if (finite(a)) {
1454                 if (finite(b)) return a + b;
1455                 else return b;
1456         }
1457         else {
1458                 if (finite(b)) return a;
1459                 else {
1460                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1461                         else return longBitsToDouble(DBL_NAN);
1462                 }
1463         }
1464 }
1465
1466
1467 double builtin_dsub(double a, double b)
1468 {
1469         return builtin_dadd(a, builtin_dneg(b));
1470 }
1471
1472
1473 double builtin_dmul(double a, double b)
1474 {
1475         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1476         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1477         if (finite(a)) {
1478                 if (finite(b)) return a * b;
1479                 else {
1480                         if (a == 0) return longBitsToDouble(DBL_NAN);
1481                         else return copysign(b, copysign(1.0, b) * a);
1482                 }
1483         }
1484         else {
1485                 if (finite(b)) {
1486                         if (b == 0) return longBitsToDouble(DBL_NAN);
1487                         else return copysign(a, copysign(1.0, a) * b);
1488                 }
1489                 else {
1490                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1491                 }
1492         }
1493 }
1494
1495
1496 double builtin_ddiv(double a, double b)
1497 {
1498         if (finite(a)) {
1499                 if (finite(b)) {
1500                         return a / b;
1501
1502                 } else {
1503                         if (isnan(b))
1504                                 return longBitsToDouble(DBL_NAN);
1505                         else
1506                                 return copysign(0.0, b);
1507                 }
1508
1509         } else {
1510                 if (finite(b)) {
1511                         if (a > 0)
1512                                 return longBitsToDouble(DBL_POSINF);
1513                         else if (a < 0)
1514                                 return longBitsToDouble(DBL_NEGINF);
1515
1516                 } else
1517                         return longBitsToDouble(DBL_NAN);
1518         }
1519
1520 /*      if (finite(a) && finite(b)) { */
1521 /*              if (b != 0) */
1522 /*                      return a / b; */
1523 /*              else { */
1524 /*                      if (a > 0) */
1525 /*                              return longBitsToDouble(DBL_POSINF); */
1526 /*                      else if (a < 0) */
1527 /*                              return longBitsToDouble(DBL_NEGINF); */
1528 /*              } */
1529 /*      } */
1530
1531         /* keep compiler happy */
1532         return 0;
1533 }
1534
1535
1536 double builtin_drem(double a, double b)
1537 {
1538         return fmod(a, b);
1539 }
1540
1541
1542 double builtin_dneg(double a)
1543 {
1544         if (isnan(a)) return a;
1545         else {
1546                 if (finite(a)) return -a;
1547                 else return copysign(a, -copysign(1.0, a));
1548         }
1549 }
1550
1551
1552 s4 builtin_dcmpl(double a, double b)
1553 {
1554         if (isnan(a)) return -1;
1555         if (isnan(b)) return -1;
1556         if (!finite(a) || !finite(b)) {
1557                 a = finite(a) ? 0 : copysign(1.0, a);
1558                 b = finite(b) ? 0 : copysign(1.0, b);
1559         }
1560         if (a > b) return 1;
1561         if (a == b) return 0;
1562         return -1;
1563 }
1564
1565
1566 s4 builtin_dcmpg(double a, double b)
1567 {
1568         if (isnan(a)) return 1;
1569         if (isnan(b)) return 1;
1570         if (!finite(a) || !finite(b)) {
1571                 a = finite(a) ? 0 : copysign(1.0, a);
1572                 b = finite(b) ? 0 : copysign(1.0, b);
1573         }
1574         if (a > b) return 1;
1575         if (a == b) return 0;
1576         return -1;
1577 }
1578
1579
1580 /*********************** Conversion operations ****************************/
1581
1582 s8 builtin_i2l(s4 i)
1583 {
1584 #if U8_AVAILABLE
1585         return i;
1586 #else
1587         s8 v;
1588         v.high = 0;
1589         v.low = i;
1590         return v;
1591 #endif
1592 }
1593
1594
1595 float builtin_i2f(s4 a)
1596 {
1597         float f = (float) a;
1598         return f;
1599 }
1600
1601
1602 double builtin_i2d(s4 a)
1603 {
1604         double d = (double) a;
1605         return d;
1606 }
1607
1608
1609 s4 builtin_l2i(s8 l)
1610 {
1611 #if U8_AVAILABLE
1612         return (s4) l;
1613 #else
1614         return l.low;
1615 #endif
1616 }
1617
1618
1619 float builtin_l2f(s8 a)
1620 {
1621 #if U8_AVAILABLE
1622         float f = (float) a;
1623         return f;
1624 #else
1625         return 0.0;
1626 #endif
1627 }
1628
1629
1630 double builtin_l2d(s8 a)
1631 {
1632 #if U8_AVAILABLE
1633         double d = (double) a;
1634         return d;
1635 #else
1636         return 0.0;
1637 #endif
1638 }
1639
1640
1641 s4 builtin_f2i(float a) 
1642 {
1643
1644         return builtin_d2i((double) a);
1645
1646         /*      float f;
1647         
1648                 if (isnanf(a))
1649                 return 0;
1650                 if (finitef(a)) {
1651                 if (a > 2147483647)
1652                 return 2147483647;
1653                 if (a < (-2147483648))
1654                 return (-2147483648);
1655                 return (s4) a;
1656                 }
1657                 f = copysignf((float) 1.0, a);
1658                 if (f > 0)
1659                 return 2147483647;
1660                 return (-2147483648); */
1661 }
1662
1663
1664 s8 builtin_f2l(float a)
1665 {
1666
1667         return builtin_d2l((double) a);
1668
1669         /*      float f;
1670         
1671                 if (finitef(a)) {
1672                 if (a > 9223372036854775807L)
1673                 return 9223372036854775807L;
1674                 if (a < (-9223372036854775808L))
1675                 return (-9223372036854775808L);
1676                 return (s8) a;
1677                 }
1678                 if (isnanf(a))
1679                 return 0;
1680                 f = copysignf((float) 1.0, a);
1681                 if (f > 0)
1682                 return 9223372036854775807L;
1683                 return (-9223372036854775808L); */
1684 }
1685
1686
1687 double builtin_f2d(float a)
1688 {
1689         if (finitef(a)) return (double) a;
1690         else {
1691                 if (isnanf(a))
1692                         return longBitsToDouble(DBL_NAN);
1693                 else
1694                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1695         }
1696 }
1697
1698
1699 s4 builtin_d2i(double a) 
1700
1701         double d;
1702         
1703         if (finite(a)) {
1704                 if (a >= 2147483647)
1705                         return 2147483647;
1706                 if (a <= (-2147483647-1))
1707                         return (-2147483647-1);
1708                 return (s4) a;
1709         }
1710         if (isnan(a))
1711                 return 0;
1712         d = copysign(1.0, a);
1713         if (d > 0)
1714                 return 2147483647;
1715         return (-2147483647-1);
1716 }
1717
1718
1719 s8 builtin_d2l(double a)
1720 {
1721         double d;
1722         
1723         if (finite(a)) {
1724                 if (a >= 9223372036854775807LL)
1725                         return 9223372036854775807LL;
1726                 if (a <= (-9223372036854775807LL-1))
1727                         return (-9223372036854775807LL-1);
1728                 return (s8) a;
1729         }
1730         if (isnan(a))
1731                 return 0;
1732         d = copysign(1.0, a);
1733         if (d > 0)
1734                 return 9223372036854775807LL;
1735         return (-9223372036854775807LL-1);
1736 }
1737
1738
1739 float builtin_d2f(double a)
1740 {
1741         if (finite(a))
1742                 return (float) a;
1743         else {
1744                 if (isnan(a))
1745                         return intBitsToFloat(FLT_NAN);
1746                 else
1747                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1748         }
1749 }
1750
1751
1752 /* used to convert FLT_xxx defines into float values */
1753
1754 inline float intBitsToFloat(s4 i)
1755 {
1756         imm_union imb;
1757
1758         imb.i = i;
1759         return imb.f;
1760 }
1761
1762
1763 /* used to convert DBL_xxx defines into double values */
1764
1765 inline float longBitsToDouble(s8 l)
1766 {
1767         imm_union imb;
1768
1769         imb.l = l;
1770         return imb.d;
1771 }
1772
1773
1774 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1775 {
1776         return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1777 }
1778
1779
1780 s4 builtin_dummy()
1781 {
1782         panic("Internal error: builtin_dummy called (native function is missing)");
1783         return 0; /* for the compiler */
1784 }
1785
1786
1787 /* builtin_asm_get_exceptionptrptr *********************************************
1788
1789    this is a wrapper for calls from asmpart
1790
1791 *******************************************************************************/
1792
1793 java_objectheader **builtin_asm_get_exceptionptrptr()
1794 {
1795         return builtin_get_exceptionptrptr();
1796 }
1797
1798
1799 methodinfo *builtin_asm_get_threadrootmethod()
1800 {
1801         return *threadrootmethod;
1802 }
1803
1804
1805 inline void* builtin_asm_get_stackframeinfo()
1806 {
1807 /*log_text("builtin_asm_get_stackframeinfo()");*/
1808 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1809         return &THREADINFO->_stackframeinfo;
1810 #else
1811 #if defined(__GNUC__)
1812 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1813 #endif
1814                 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1815 #endif
1816 }
1817
1818 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1819 /*      stacktraceelement *el;*/
1820         size_t s;
1821         s=(end-begin);
1822         /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1823         *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1824 #if 0
1825         *el=MNEW(stacktraceelement,s+1); /*GC*/
1826 #endif
1827         memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1828         (*el)[s].method=0;
1829 #if defined(__GNUC__)
1830 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1831 #endif
1832         (*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 */
1833         return *el;
1834 }
1835
1836 /*
1837  * These are local overrides for various environment variables in Emacs.
1838  * Please do not remove this and leave it at the end of the file, where
1839  * Emacs will automagically detect them.
1840  * ---------------------------------------------------------------------
1841  * Local variables:
1842  * mode: c
1843  * indent-tabs-mode: t
1844  * c-basic-offset: 4
1845  * tab-width: 4
1846  * End:
1847  */