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