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