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