- #include "nat/java_lang_VMObject.h"
[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 1542 2004-11-18 12:19:49Z twisti $
38
39 */
40
41
42 #include <assert.h>
43 #include <string.h>
44 #include <math.h>
45 #include "exceptions.h"
46 #include "global.h"
47 #include "options.h"
48 #include "builtin.h"
49 #include "native.h"
50 #include "loader.h"
51 #include "tables.h"
52 #include "asmpart.h"
53 #include "mm/boehm.h"
54 #include "threads/thread.h"
55 #include "threads/locks.h"
56 #include "toolbox/logging.h"
57 #include "toolbox/memory.h"
58 #include "nat/java_lang_Cloneable.h"
59 #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 (opt_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 (opt_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
797                         } else{
798                                 printf("(NOSYNC");
799                         }
800
801                         if (m->flags & ACC_NATIVE) {
802                                 printf(",NATIVE");
803 #if POINTERSIZE == 8
804                                 printf(")(0x%016lx) at position %p\n", (s8) m->entrypoint, pos);
805 #else
806                                 printf(")(0x%08lx) at position %p\n", (s4) m->entrypoint, pos);
807 #endif
808
809                         } else {
810 #if POINTERSIZE == 8
811                                 printf(")(0x%016lx) at position %p (", (s8) m->entrypoint, pos);
812 #else
813                                 printf(")(0x%08lx) at position %p (", (s4) m->entrypoint, pos);
814 #endif
815                                 if (m->class->sourcefile == NULL) {
816                                         printf("<NO CLASSFILE INFORMATION>");
817
818                                 } else {
819                                         utf_display(m->class->sourcefile);
820                                 }
821                                 printf(":%d)\n", line);
822                         }
823
824                 } else
825                         printf("call_java_method\n");
826                 fflush(stdout);
827         }
828
829         return xptr;
830 }
831
832
833 #ifdef TRACE_ARGS_NUM
834 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
835 #if TRACE_ARGS_NUM > 6
836                                                 s8 a6, s8 a7,
837 #endif
838                                                 methodinfo *m)
839 {
840         s4 i;
841         char logtext[MAXLOGTEXT];
842         for (i = 0; i < methodindent; i++)
843                 logtext[i] = '\t';
844
845         sprintf(logtext + methodindent, "called: ");
846         utf_sprint_classname(logtext + strlen(logtext), m->class->name);
847         sprintf(logtext + strlen(logtext), ".");
848         utf_sprint(logtext + strlen(logtext), m->name);
849         utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
850
851         if (m->flags & ACC_PUBLIC)       sprintf(logtext + strlen(logtext), " PUBLIC");
852         if (m->flags & ACC_PRIVATE)      sprintf(logtext + strlen(logtext), " PRIVATE");
853         if (m->flags & ACC_PROTECTED)    sprintf(logtext + strlen(logtext), " PROTECTED");
854         if (m->flags & ACC_STATIC)       sprintf(logtext + strlen(logtext), " STATIC");
855         if (m->flags & ACC_FINAL)        sprintf(logtext + strlen(logtext), " FINAL");
856         if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
857         if (m->flags & ACC_VOLATILE)     sprintf(logtext + strlen(logtext), " VOLATILE");
858         if (m->flags & ACC_TRANSIENT)    sprintf(logtext + strlen(logtext), " TRANSIENT");
859         if (m->flags & ACC_NATIVE)       sprintf(logtext + strlen(logtext), " NATIVE");
860         if (m->flags & ACC_INTERFACE)    sprintf(logtext + strlen(logtext), " INTERFACE");
861         if (m->flags & ACC_ABSTRACT)     sprintf(logtext + strlen(logtext), " ABSTRACT");
862         
863
864         sprintf(logtext + strlen(logtext), "(");
865
866         switch (m->paramcount) {
867         case 0:
868                 break;
869
870 #if defined(__I386__) || defined(__POWERPC__)
871         case 1:
872                 sprintf(logtext+strlen(logtext), "%llx", a0);
873                 break;
874
875         case 2:
876                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
877                 break;
878
879         case 3:
880                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
881                 break;
882
883         case 4:
884                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
885                                 a0,   a1,   a2,   a3);
886                 break;
887
888         case 5:
889                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
890                                 a0,   a1,   a2,   a3,   a4);
891                 break;
892
893         case 6:
894                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
895                                 a0,   a1,   a2,   a3,   a4,   a5);
896                 break;
897
898 #if TRACE_ARGS_NUM > 6
899         case 7:
900                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
901                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
902                 break;
903
904         case 8:
905                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
906                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
907                 break;
908
909         default:
910                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
911                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   m->paramcount - 8);
912                 break;
913 #else
914         default:
915                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
916                                 a0,   a1,   a2,   a3,   a4,   a5,   m->paramcount - 6);
917                 break;
918 #endif
919 #else
920         case 1:
921                 sprintf(logtext+strlen(logtext), "%lx", a0);
922                 break;
923
924         case 2:
925                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
926                 break;
927
928         case 3:
929                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
930                 break;
931
932         case 4:
933                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
934                                 a0,  a1,  a2,  a3);
935                 break;
936
937         case 5:
938                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
939                                 a0,  a1,  a2,  a3,  a4);
940                 break;
941
942         case 6:
943                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
944                                 a0,  a1,  a2,  a3,  a4,  a5);
945                 break;
946
947 #if TRACE_ARGS_NUM > 6
948         case 7:
949                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
950                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
951                 break;
952
953         case 8:
954                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
955                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
956                 break;
957
958         default:
959                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
960                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  m->paramcount - 8);
961                 break;
962 #else
963         default:
964                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
965                                 a0,  a1,  a2,  a3,  a4,  a5,   m->paramcount - 6);
966                 break;
967 #endif
968 #endif
969         }
970
971         sprintf(logtext + strlen(logtext), ")");
972         log_text(logtext);
973
974         methodindent++;
975 }
976 #endif
977
978
979 void builtin_displaymethodstart(methodinfo *m)
980 {
981         char logtext[MAXLOGTEXT];
982         sprintf(logtext, "                                                                                              ");
983         sprintf(logtext + methodindent, "called: ");
984         utf_sprint(logtext + strlen(logtext), m->class->name);
985         sprintf(logtext + strlen(logtext), ".");
986         utf_sprint(logtext + strlen(logtext), m->name);
987         utf_sprint(logtext + strlen(logtext), m->descriptor);
988
989         if (m->flags & ACC_PUBLIC)       sprintf(logtext + strlen(logtext), " PUBLIC");
990         if (m->flags & ACC_PRIVATE)      sprintf(logtext + strlen(logtext), " PRIVATE");
991         if (m->flags & ACC_PROTECTED)    sprintf(logtext + strlen(logtext), " PROTECTED");
992         if (m->flags & ACC_STATIC)       sprintf(logtext + strlen(logtext), " STATIC");
993         if (m->flags & ACC_FINAL)        sprintf(logtext + strlen(logtext), " FINAL");
994         if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
995         if (m->flags & ACC_VOLATILE)     sprintf(logtext + strlen(logtext), " VOLATILE");
996         if (m->flags & ACC_TRANSIENT)    sprintf(logtext + strlen(logtext), " TRANSIENT");
997         if (m->flags & ACC_NATIVE)       sprintf(logtext + strlen(logtext), " NATIVE");
998         if (m->flags & ACC_INTERFACE)    sprintf(logtext + strlen(logtext), " INTERFACE");
999         if (m->flags & ACC_ABSTRACT)     sprintf(logtext + strlen(logtext), " ABSTRACT");
1000
1001         log_text(logtext);
1002         methodindent++;
1003 }
1004
1005
1006 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1007 {
1008         int i;
1009         char logtext[MAXLOGTEXT];
1010         for (i = 0; i < methodindent; i++)
1011                 logtext[i] = '\t';
1012         if (methodindent)
1013                 methodindent--;
1014         else
1015                 log_text("WARNING: unmatched methodindent--");
1016
1017         sprintf(logtext + methodindent, "finished: ");
1018         utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1019         sprintf(logtext + strlen(logtext), ".");
1020         utf_sprint(logtext + strlen(logtext), m->name);
1021         utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
1022
1023         switch (m->returntype) {
1024         case TYPE_INT:
1025                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1026                 break;
1027
1028         case TYPE_LONG:
1029 #if defined(__I386__) || defined(__POWERPC__)
1030                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1031 #else
1032                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1033 #endif
1034                 break;
1035
1036         case TYPE_ADDRESS:
1037 #if defined(__I386__) || defined(__POWERPC__)
1038                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1039 #else
1040                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1041 #endif
1042                 break;
1043
1044         case TYPE_FLOAT:
1045                 sprintf(logtext + strlen(logtext), "->%g", f);
1046                 break;
1047
1048         case TYPE_DOUBLE:
1049                 sprintf(logtext + strlen(logtext), "->%g", d);
1050                 break;
1051         }
1052         log_text(logtext);
1053 }
1054
1055
1056 /****************************************************************************
1057                          SYNCHRONIZATION FUNCTIONS
1058 *****************************************************************************/
1059
1060 /*
1061  * Lock the mutex of an object.
1062  */
1063 void internal_lock_mutex_for_object(java_objectheader *object)
1064 {
1065 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1066         mutexHashEntry *entry;
1067         int hashValue;
1068
1069         assert(object != 0);
1070
1071         hashValue = MUTEX_HASH_VALUE(object);
1072         entry = &mutexHashTable[hashValue];
1073
1074         if (entry->object != 0) {
1075                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1076                         entry->object = 0;
1077                         entry->mutex.holder = 0;
1078                         entry->mutex.count = 0;
1079                         entry->mutex.muxWaiters = 0;
1080
1081                 } else {
1082                         while (entry->next != 0 && entry->object != object)
1083                                 entry = entry->next;
1084
1085                         if (entry->object != object) {
1086                                 entry->next = firstFreeOverflowEntry;
1087                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1088
1089                                 entry = entry->next;
1090                                 entry->object = 0;
1091                                 entry->next = 0;
1092                                 assert(entry->conditionCount == 0);
1093                         }
1094                 }
1095
1096         } else {
1097                 entry->mutex.holder = 0;
1098                 entry->mutex.count = 0;
1099                 entry->mutex.muxWaiters = 0;
1100         }
1101
1102         if (entry->object == 0)
1103                 entry->object = object;
1104         
1105         internal_lock_mutex(&entry->mutex);
1106 #endif
1107 }
1108
1109
1110 /*
1111  * Unlocks the mutex of an object.
1112  */
1113 void internal_unlock_mutex_for_object (java_objectheader *object)
1114 {
1115 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1116         int hashValue;
1117         mutexHashEntry *entry;
1118
1119         hashValue = MUTEX_HASH_VALUE(object);
1120         entry = &mutexHashTable[hashValue];
1121
1122         if (entry->object == object) {
1123                 internal_unlock_mutex(&entry->mutex);
1124
1125         } else {
1126                 while (entry->next != 0 && entry->next->object != object)
1127                         entry = entry->next;
1128
1129                 assert(entry->next != 0);
1130
1131                 internal_unlock_mutex(&entry->next->mutex);
1132
1133                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1134                         mutexHashEntry *unlinked = entry->next;
1135
1136                         entry->next = unlinked->next;
1137                         unlinked->next = firstFreeOverflowEntry;
1138                         firstFreeOverflowEntry = unlinked;
1139                 }
1140         }
1141 #endif
1142 }
1143
1144
1145 void builtin_monitorenter(java_objectheader *o)
1146 {
1147 #if defined(USE_THREADS)
1148 #if !defined(NATIVE_THREADS)
1149         int hashValue;
1150
1151         ++blockInts;
1152
1153         hashValue = MUTEX_HASH_VALUE(o);
1154         if (mutexHashTable[hashValue].object == o 
1155                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1156                 ++mutexHashTable[hashValue].mutex.count;
1157         else
1158                 internal_lock_mutex_for_object(o);
1159
1160         --blockInts;
1161 #else
1162         monitorEnter((threadobject *) THREADOBJECT, o);
1163 #endif
1164 #endif
1165
1166 }
1167
1168 /*
1169  * Locks the class object - needed for static synchronized methods.
1170  * The use_class_as_object call is needed in order to circumvent a
1171  * possible deadlock with builtin_monitorenter called by another
1172  * thread calling use_class_as_object.
1173  */
1174 void builtin_staticmonitorenter(classinfo *c)
1175 {
1176         use_class_as_object(c);
1177         builtin_monitorenter(&c->header);
1178 }
1179
1180
1181 void *builtin_monitorexit(java_objectheader *o)
1182 {
1183 #if defined(USE_THREADS)
1184 #if !defined(NATIVE_THREADS)
1185         int hashValue;
1186
1187         ++blockInts;
1188
1189         hashValue = MUTEX_HASH_VALUE(o);
1190         if (mutexHashTable[hashValue].object == o) {
1191                 if (mutexHashTable[hashValue].mutex.count == 1
1192                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1193                         internal_unlock_mutex_for_object(o);
1194                 else
1195                         --mutexHashTable[hashValue].mutex.count;
1196
1197         } else
1198                 internal_unlock_mutex_for_object(o);
1199
1200         --blockInts;
1201         return o;
1202 #else
1203         monitorExit((threadobject *) THREADOBJECT, o);
1204         return o;
1205 #endif
1206 #endif
1207 }
1208
1209
1210 /*****************************************************************************
1211                           MISCELLANEOUS HELPER FUNCTIONS
1212 *****************************************************************************/
1213
1214
1215
1216 /*********** Functions for integer divisions *****************************
1217  
1218         On some systems (eg. DEC ALPHA), integer division is not supported by the
1219         CPU. These helper functions implement the missing functionality.
1220
1221 ******************************************************************************/
1222
1223 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1224 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1225
1226
1227 /************** Functions for long arithmetics *******************************
1228
1229         On systems where 64 bit Integers are not supported by the CPU, these
1230         functions are needed.
1231
1232 ******************************************************************************/
1233
1234
1235 s8 builtin_ladd(s8 a, s8 b)
1236
1237 #if U8_AVAILABLE
1238         return a + b; 
1239 #else
1240         return builtin_i2l(0);
1241 #endif
1242 }
1243
1244 s8 builtin_lsub(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_lmul(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_ldiv(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_lrem(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_lshl(s8 a, s4 b) 
1281
1282 #if U8_AVAILABLE
1283         return a << (b & 63);
1284 #else
1285         return builtin_i2l(0);
1286 #endif
1287 }
1288
1289 s8 builtin_lshr(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_lushr(s8 a, s4 b) 
1299
1300 #if U8_AVAILABLE
1301         return ((u8) a) >> (b & 63);
1302 #else
1303         return builtin_i2l(0);
1304 #endif
1305 }
1306
1307 s8 builtin_land(s8 a, s8 b) 
1308
1309 #if U8_AVAILABLE
1310         return a & b; 
1311 #else
1312         return builtin_i2l(0);
1313 #endif
1314 }
1315
1316 s8 builtin_lor(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_lxor(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_lneg(s8 a) 
1335
1336 #if U8_AVAILABLE
1337         return -a;
1338 #else
1339         return builtin_i2l(0);
1340 #endif
1341 }
1342
1343 s4 builtin_lcmp(s8 a, s8 b) 
1344
1345 #if U8_AVAILABLE
1346         if (a < b) return -1;
1347         if (a > b) return 1;
1348         return 0;
1349 #else
1350         return 0;
1351 #endif
1352 }
1353
1354
1355
1356
1357
1358 /*********** Functions for floating point operations *************************/
1359
1360 float builtin_fadd(float a, float b)
1361 {
1362         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1363         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1364         if (finitef(a)) {
1365                 if (finitef(b))
1366                         return a + b;
1367                 else
1368                         return b;
1369         }
1370         else {
1371                 if (finitef(b))
1372                         return a;
1373                 else {
1374                         if (copysignf(1.0, a) == copysignf(1.0, b))
1375                                 return a;
1376                         else
1377                                 return intBitsToFloat(FLT_NAN);
1378                 }
1379         }
1380 }
1381
1382
1383 float builtin_fsub(float a, float b)
1384 {
1385         return builtin_fadd(a, builtin_fneg(b));
1386 }
1387
1388
1389 float builtin_fmul(float a, float b)
1390 {
1391         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1392         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1393         if (finitef(a)) {
1394                 if (finitef(b)) return a * b;
1395                 else {
1396                         if (a == 0) return intBitsToFloat(FLT_NAN);
1397                         else return copysignf(b, copysignf(1.0, b)*a);
1398                 }
1399         }
1400         else {
1401                 if (finitef(b)) {
1402                         if (b == 0) return intBitsToFloat(FLT_NAN);
1403                         else return copysignf(a, copysignf(1.0, a)*b);
1404                 }
1405                 else {
1406                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1407                 }
1408         }
1409 }
1410
1411
1412 float builtin_fdiv(float a, float b)
1413 {
1414         if (finitef(a) && finitef(b)) {
1415                 if (b != 0)
1416                         return a / b;
1417                 else {
1418                         if (a > 0)
1419                                 return intBitsToFloat(FLT_POSINF);
1420                         else if (a < 0)
1421                                 return intBitsToFloat(FLT_NEGINF);
1422                 }
1423         }
1424         return intBitsToFloat(FLT_NAN);
1425 }
1426
1427
1428 float builtin_frem(float a, float b)
1429 {
1430         return fmodf(a, b);
1431 }
1432
1433
1434 float builtin_fneg(float a)
1435 {
1436         if (isnanf(a)) return a;
1437         else {
1438                 if (finitef(a)) return -a;
1439                 else return copysignf(a, -copysignf(1.0, a));
1440         }
1441 }
1442
1443
1444 s4 builtin_fcmpl(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 s4 builtin_fcmpg(float a, float b)
1459 {
1460         if (isnanf(a)) return 1;
1461         if (isnanf(b)) return 1;
1462         if (!finitef(a) || !finitef(b)) {
1463                 a = finitef(a) ? 0 : copysignf(1.0, a);
1464                 b = finitef(b) ? 0 : copysignf(1.0, b);
1465         }
1466         if (a > b) return 1;
1467         if (a == b) return 0;
1468         return -1;
1469 }
1470
1471
1472
1473 /************************* Functions for doubles ****************************/
1474
1475 double builtin_dadd(double a, double b)
1476 {
1477         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1478         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1479         if (finite(a)) {
1480                 if (finite(b)) return a + b;
1481                 else return b;
1482         }
1483         else {
1484                 if (finite(b)) return a;
1485                 else {
1486                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1487                         else return longBitsToDouble(DBL_NAN);
1488                 }
1489         }
1490 }
1491
1492
1493 double builtin_dsub(double a, double b)
1494 {
1495         return builtin_dadd(a, builtin_dneg(b));
1496 }
1497
1498
1499 double builtin_dmul(double a, double b)
1500 {
1501         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1502         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1503         if (finite(a)) {
1504                 if (finite(b)) return a * b;
1505                 else {
1506                         if (a == 0) return longBitsToDouble(DBL_NAN);
1507                         else return copysign(b, copysign(1.0, b) * a);
1508                 }
1509         }
1510         else {
1511                 if (finite(b)) {
1512                         if (b == 0) return longBitsToDouble(DBL_NAN);
1513                         else return copysign(a, copysign(1.0, a) * b);
1514                 }
1515                 else {
1516                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1517                 }
1518         }
1519 }
1520
1521
1522 double builtin_ddiv(double a, double b)
1523 {
1524         if (finite(a)) {
1525                 if (finite(b)) {
1526                         return a / b;
1527
1528                 } else {
1529                         if (isnan(b))
1530                                 return longBitsToDouble(DBL_NAN);
1531                         else
1532                                 return copysign(0.0, b);
1533                 }
1534
1535         } else {
1536                 if (finite(b)) {
1537                         if (a > 0)
1538                                 return longBitsToDouble(DBL_POSINF);
1539                         else if (a < 0)
1540                                 return longBitsToDouble(DBL_NEGINF);
1541
1542                 } else
1543                         return longBitsToDouble(DBL_NAN);
1544         }
1545
1546 /*      if (finite(a) && finite(b)) { */
1547 /*              if (b != 0) */
1548 /*                      return a / b; */
1549 /*              else { */
1550 /*                      if (a > 0) */
1551 /*                              return longBitsToDouble(DBL_POSINF); */
1552 /*                      else if (a < 0) */
1553 /*                              return longBitsToDouble(DBL_NEGINF); */
1554 /*              } */
1555 /*      } */
1556
1557         /* keep compiler happy */
1558         return 0;
1559 }
1560
1561
1562 double builtin_drem(double a, double b)
1563 {
1564         return fmod(a, b);
1565 }
1566
1567
1568 double builtin_dneg(double a)
1569 {
1570         if (isnan(a)) return a;
1571         else {
1572                 if (finite(a)) return -a;
1573                 else return copysign(a, -copysign(1.0, a));
1574         }
1575 }
1576
1577
1578 s4 builtin_dcmpl(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 s4 builtin_dcmpg(double a, double b)
1593 {
1594         if (isnan(a)) return 1;
1595         if (isnan(b)) return 1;
1596         if (!finite(a) || !finite(b)) {
1597                 a = finite(a) ? 0 : copysign(1.0, a);
1598                 b = finite(b) ? 0 : copysign(1.0, b);
1599         }
1600         if (a > b) return 1;
1601         if (a == b) return 0;
1602         return -1;
1603 }
1604
1605
1606 /*********************** Conversion operations ****************************/
1607
1608 s8 builtin_i2l(s4 i)
1609 {
1610 #if U8_AVAILABLE
1611         return i;
1612 #else
1613         s8 v;
1614         v.high = 0;
1615         v.low = i;
1616         return v;
1617 #endif
1618 }
1619
1620
1621 float builtin_i2f(s4 a)
1622 {
1623         float f = (float) a;
1624         return f;
1625 }
1626
1627
1628 double builtin_i2d(s4 a)
1629 {
1630         double d = (double) a;
1631         return d;
1632 }
1633
1634
1635 s4 builtin_l2i(s8 l)
1636 {
1637 #if U8_AVAILABLE
1638         return (s4) l;
1639 #else
1640         return l.low;
1641 #endif
1642 }
1643
1644
1645 float builtin_l2f(s8 a)
1646 {
1647 #if U8_AVAILABLE
1648         float f = (float) a;
1649         return f;
1650 #else
1651         return 0.0;
1652 #endif
1653 }
1654
1655
1656 double builtin_l2d(s8 a)
1657 {
1658 #if U8_AVAILABLE
1659         double d = (double) a;
1660         return d;
1661 #else
1662         return 0.0;
1663 #endif
1664 }
1665
1666
1667 s4 builtin_f2i(float a) 
1668 {
1669
1670         return builtin_d2i((double) a);
1671
1672         /*      float f;
1673         
1674                 if (isnanf(a))
1675                 return 0;
1676                 if (finitef(a)) {
1677                 if (a > 2147483647)
1678                 return 2147483647;
1679                 if (a < (-2147483648))
1680                 return (-2147483648);
1681                 return (s4) a;
1682                 }
1683                 f = copysignf((float) 1.0, a);
1684                 if (f > 0)
1685                 return 2147483647;
1686                 return (-2147483648); */
1687 }
1688
1689
1690 s8 builtin_f2l(float a)
1691 {
1692
1693         return builtin_d2l((double) a);
1694
1695         /*      float f;
1696         
1697                 if (finitef(a)) {
1698                 if (a > 9223372036854775807L)
1699                 return 9223372036854775807L;
1700                 if (a < (-9223372036854775808L))
1701                 return (-9223372036854775808L);
1702                 return (s8) a;
1703                 }
1704                 if (isnanf(a))
1705                 return 0;
1706                 f = copysignf((float) 1.0, a);
1707                 if (f > 0)
1708                 return 9223372036854775807L;
1709                 return (-9223372036854775808L); */
1710 }
1711
1712
1713 double builtin_f2d(float a)
1714 {
1715         if (finitef(a)) return (double) a;
1716         else {
1717                 if (isnanf(a))
1718                         return longBitsToDouble(DBL_NAN);
1719                 else
1720                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1721         }
1722 }
1723
1724
1725 s4 builtin_d2i(double a) 
1726
1727         double d;
1728         
1729         if (finite(a)) {
1730                 if (a >= 2147483647)
1731                         return 2147483647;
1732                 if (a <= (-2147483647-1))
1733                         return (-2147483647-1);
1734                 return (s4) a;
1735         }
1736         if (isnan(a))
1737                 return 0;
1738         d = copysign(1.0, a);
1739         if (d > 0)
1740                 return 2147483647;
1741         return (-2147483647-1);
1742 }
1743
1744
1745 s8 builtin_d2l(double a)
1746 {
1747         double d;
1748         
1749         if (finite(a)) {
1750                 if (a >= 9223372036854775807LL)
1751                         return 9223372036854775807LL;
1752                 if (a <= (-9223372036854775807LL-1))
1753                         return (-9223372036854775807LL-1);
1754                 return (s8) a;
1755         }
1756         if (isnan(a))
1757                 return 0;
1758         d = copysign(1.0, a);
1759         if (d > 0)
1760                 return 9223372036854775807LL;
1761         return (-9223372036854775807LL-1);
1762 }
1763
1764
1765 float builtin_d2f(double a)
1766 {
1767         if (finite(a))
1768                 return (float) a;
1769         else {
1770                 if (isnan(a))
1771                         return intBitsToFloat(FLT_NAN);
1772                 else
1773                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1774         }
1775 }
1776
1777
1778 /* used to convert FLT_xxx defines into float values */
1779
1780 inline float intBitsToFloat(s4 i)
1781 {
1782         imm_union imb;
1783
1784         imb.i = i;
1785         return imb.f;
1786 }
1787
1788
1789 /* used to convert DBL_xxx defines into double values */
1790
1791 inline float longBitsToDouble(s8 l)
1792 {
1793         imm_union imb;
1794
1795         imb.l = l;
1796         return imb.d;
1797 }
1798
1799
1800 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1801 {
1802         return (java_arrayheader *)
1803                 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1804 }
1805
1806
1807 s4 builtin_dummy()
1808 {
1809         panic("Internal error: builtin_dummy called (native function is missing)");
1810         return 0; /* for the compiler */
1811 }
1812
1813
1814 /* builtin_asm_get_exceptionptrptr *********************************************
1815
1816    this is a wrapper for calls from asmpart
1817
1818 *******************************************************************************/
1819
1820 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1821 java_objectheader **builtin_asm_get_exceptionptrptr()
1822 {
1823         return builtin_get_exceptionptrptr();
1824 }
1825 #endif
1826
1827
1828 methodinfo *builtin_asm_get_threadrootmethod()
1829 {
1830         return *threadrootmethod;
1831 }
1832
1833
1834 inline void* builtin_asm_get_stackframeinfo()
1835 {
1836 /*log_text("builtin_asm_get_stackframeinfo()");*/
1837 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1838         return &THREADINFO->_stackframeinfo;
1839 #else
1840 #if defined(__GNUC__)
1841 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1842 #endif
1843                 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1844 #endif
1845 }
1846
1847 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1848 /*      stacktraceelement *el;*/
1849         size_t s;
1850         s=(end-begin);
1851         /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1852         *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1853 #if 0
1854         *el=MNEW(stacktraceelement,s+1); /*GC*/
1855 #endif
1856         memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1857         (*el)[s].method=0;
1858 #if defined(__GNUC__)
1859 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1860 #endif
1861         (*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 */
1862         return *el;
1863 }
1864
1865 /*
1866  * These are local overrides for various environment variables in Emacs.
1867  * Please do not remove this and leave it at the end of the file, where
1868  * Emacs will automagically detect them.
1869  * ---------------------------------------------------------------------
1870  * Local variables:
1871  * mode: c
1872  * indent-tabs-mode: t
1873  * c-basic-offset: 4
1874  * tab-width: 4
1875  * End:
1876  */