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