Bug fix in builtin_monitor* with green threads: monitors must be
[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 1194 2004-06-19 12:59:20Z twisti $
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         ++blockInts;
1122
1123         hashValue = MUTEX_HASH_VALUE(o);
1124         if (mutexHashTable[hashValue].object == o 
1125                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1126                 ++mutexHashTable[hashValue].mutex.count;
1127         else
1128                 internal_lock_mutex_for_object(o);
1129
1130         --blockInts;
1131 #else
1132         monitorEnter((threadobject *) THREADOBJECT, o);
1133 #endif
1134 #endif
1135 }
1136
1137
1138 void builtin_monitorexit(java_objectheader *o)
1139 {
1140 #if defined(USE_THREADS)
1141 #if !defined(NATIVE_THREADS)
1142         int hashValue;
1143
1144         ++blockInts;
1145
1146         hashValue = MUTEX_HASH_VALUE(o);
1147         if (mutexHashTable[hashValue].object == o) {
1148                 if (mutexHashTable[hashValue].mutex.count == 1
1149                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1150                         internal_unlock_mutex_for_object(o);
1151                 else
1152                         --mutexHashTable[hashValue].mutex.count;
1153
1154         } else
1155                 internal_unlock_mutex_for_object(o);
1156
1157         --blockInts;
1158 #else
1159         monitorExit((threadobject *) THREADOBJECT, o);
1160 #endif
1161 #endif
1162 }
1163
1164
1165 /*****************************************************************************
1166                           MISCELLANEOUS HELPER FUNCTIONS
1167 *****************************************************************************/
1168
1169
1170
1171 /*********** Functions for integer divisions *****************************
1172  
1173         On some systems (eg. DEC ALPHA), integer division is not supported by the
1174         CPU. These helper functions implement the missing functionality.
1175
1176 ******************************************************************************/
1177
1178 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1179 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1180
1181
1182 /************** Functions for long arithmetics *******************************
1183
1184         On systems where 64 bit Integers are not supported by the CPU, these
1185         functions are needed.
1186
1187 ******************************************************************************/
1188
1189
1190 s8 builtin_ladd(s8 a, s8 b)
1191
1192 #if U8_AVAILABLE
1193         return a + b; 
1194 #else
1195         return builtin_i2l(0);
1196 #endif
1197 }
1198
1199 s8 builtin_lsub(s8 a, s8 b) 
1200
1201 #if U8_AVAILABLE
1202         return a - b; 
1203 #else
1204         return builtin_i2l(0);
1205 #endif
1206 }
1207
1208 s8 builtin_lmul(s8 a, s8 b) 
1209
1210 #if U8_AVAILABLE
1211         return a * b; 
1212 #else
1213         return builtin_i2l(0);
1214 #endif
1215 }
1216
1217 s8 builtin_ldiv(s8 a, s8 b) 
1218
1219 #if U8_AVAILABLE
1220         return a / b; 
1221 #else
1222         return builtin_i2l(0);
1223 #endif
1224 }
1225
1226 s8 builtin_lrem(s8 a, s8 b) 
1227
1228 #if U8_AVAILABLE
1229         return a % b; 
1230 #else
1231         return builtin_i2l(0);
1232 #endif
1233 }
1234
1235 s8 builtin_lshl(s8 a, s4 b) 
1236
1237 #if U8_AVAILABLE
1238         return a << (b & 63);
1239 #else
1240         return builtin_i2l(0);
1241 #endif
1242 }
1243
1244 s8 builtin_lshr(s8 a, s4 b) 
1245
1246 #if U8_AVAILABLE
1247         return a >> (b & 63);
1248 #else
1249         return builtin_i2l(0);
1250 #endif
1251 }
1252
1253 s8 builtin_lushr(s8 a, s4 b) 
1254
1255 #if U8_AVAILABLE
1256         return ((u8) a) >> (b & 63);
1257 #else
1258         return builtin_i2l(0);
1259 #endif
1260 }
1261
1262 s8 builtin_land(s8 a, s8 b) 
1263
1264 #if U8_AVAILABLE
1265         return a & b; 
1266 #else
1267         return builtin_i2l(0);
1268 #endif
1269 }
1270
1271 s8 builtin_lor(s8 a, s8 b) 
1272
1273 #if U8_AVAILABLE
1274         return a | b; 
1275 #else
1276         return builtin_i2l(0);
1277 #endif
1278 }
1279
1280 s8 builtin_lxor(s8 a, s8 b) 
1281
1282 #if U8_AVAILABLE
1283         return a ^ b; 
1284 #else
1285         return builtin_i2l(0);
1286 #endif
1287 }
1288
1289 s8 builtin_lneg(s8 a) 
1290
1291 #if U8_AVAILABLE
1292         return -a;
1293 #else
1294         return builtin_i2l(0);
1295 #endif
1296 }
1297
1298 s4 builtin_lcmp(s8 a, s8 b) 
1299
1300 #if U8_AVAILABLE
1301         if (a < b) return -1;
1302         if (a > b) return 1;
1303         return 0;
1304 #else
1305         return 0;
1306 #endif
1307 }
1308
1309
1310
1311
1312
1313 /*********** Functions for floating point operations *************************/
1314
1315 float builtin_fadd(float a, float b)
1316 {
1317         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1318         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1319         if (finitef(a)) {
1320                 if (finitef(b))
1321                         return a + b;
1322                 else
1323                         return b;
1324         }
1325         else {
1326                 if (finitef(b))
1327                         return a;
1328                 else {
1329                         if (copysignf(1.0, a) == copysignf(1.0, b))
1330                                 return a;
1331                         else
1332                                 return intBitsToFloat(FLT_NAN);
1333                 }
1334         }
1335 }
1336
1337
1338 float builtin_fsub(float a, float b)
1339 {
1340         return builtin_fadd(a, builtin_fneg(b));
1341 }
1342
1343
1344 float builtin_fmul(float a, float b)
1345 {
1346         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1347         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1348         if (finitef(a)) {
1349                 if (finitef(b)) return a * b;
1350                 else {
1351                         if (a == 0) return intBitsToFloat(FLT_NAN);
1352                         else return copysignf(b, copysignf(1.0, b)*a);
1353                 }
1354         }
1355         else {
1356                 if (finitef(b)) {
1357                         if (b == 0) return intBitsToFloat(FLT_NAN);
1358                         else return copysignf(a, copysignf(1.0, a)*b);
1359                 }
1360                 else {
1361                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1362                 }
1363         }
1364 }
1365
1366
1367 float builtin_fdiv(float a, float b)
1368 {
1369         if (finitef(a) && finitef(b)) {
1370                 if (b != 0)
1371                         return a / b;
1372                 else {
1373                         if (a > 0)
1374                                 return intBitsToFloat(FLT_POSINF);
1375                         else if (a < 0)
1376                                 return intBitsToFloat(FLT_NEGINF);
1377                 }
1378         }
1379         return intBitsToFloat(FLT_NAN);
1380 }
1381
1382
1383 float builtin_frem(float a, float b)
1384 {
1385         return fmodf(a, b);
1386 }
1387
1388
1389 float builtin_fneg(float a)
1390 {
1391         if (isnanf(a)) return a;
1392         else {
1393                 if (finitef(a)) return -a;
1394                 else return copysignf(a, -copysignf(1.0, a));
1395         }
1396 }
1397
1398
1399 s4 builtin_fcmpl(float a, float b)
1400 {
1401         if (isnanf(a)) return -1;
1402         if (isnanf(b)) return -1;
1403         if (!finitef(a) || !finitef(b)) {
1404                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1405                 b = finitef(b) ? 0 : copysignf(1.0, b);
1406         }
1407         if (a > b) return 1;
1408         if (a == b) return 0;
1409         return -1;
1410 }
1411
1412
1413 s4 builtin_fcmpg(float a, float b)
1414 {
1415         if (isnanf(a)) return 1;
1416         if (isnanf(b)) return 1;
1417         if (!finitef(a) || !finitef(b)) {
1418                 a = finitef(a) ? 0 : copysignf(1.0, a);
1419                 b = finitef(b) ? 0 : copysignf(1.0, b);
1420         }
1421         if (a > b) return 1;
1422         if (a == b) return 0;
1423         return -1;
1424 }
1425
1426
1427
1428 /************************* Functions for doubles ****************************/
1429
1430 double builtin_dadd(double a, double b)
1431 {
1432         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1433         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1434         if (finite(a)) {
1435                 if (finite(b)) return a + b;
1436                 else return b;
1437         }
1438         else {
1439                 if (finite(b)) return a;
1440                 else {
1441                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1442                         else return longBitsToDouble(DBL_NAN);
1443                 }
1444         }
1445 }
1446
1447
1448 double builtin_dsub(double a, double b)
1449 {
1450         return builtin_dadd(a, builtin_dneg(b));
1451 }
1452
1453
1454 double builtin_dmul(double a, double b)
1455 {
1456         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1457         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1458         if (finite(a)) {
1459                 if (finite(b)) return a * b;
1460                 else {
1461                         if (a == 0) return longBitsToDouble(DBL_NAN);
1462                         else return copysign(b, copysign(1.0, b) * a);
1463                 }
1464         }
1465         else {
1466                 if (finite(b)) {
1467                         if (b == 0) return longBitsToDouble(DBL_NAN);
1468                         else return copysign(a, copysign(1.0, a) * b);
1469                 }
1470                 else {
1471                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1472                 }
1473         }
1474 }
1475
1476
1477 double builtin_ddiv(double a, double b)
1478 {
1479         if (finite(a)) {
1480                 if (finite(b)) {
1481                         return a / b;
1482
1483                 } else {
1484                         if (isnan(b))
1485                                 return longBitsToDouble(DBL_NAN);
1486                         else
1487                                 return copysign(0.0, b);
1488                 }
1489
1490         } else {
1491                 if (finite(b)) {
1492                         if (a > 0)
1493                                 return longBitsToDouble(DBL_POSINF);
1494                         else if (a < 0)
1495                                 return longBitsToDouble(DBL_NEGINF);
1496
1497                 } else
1498                         return longBitsToDouble(DBL_NAN);
1499         }
1500
1501 /*      if (finite(a) && finite(b)) { */
1502 /*              if (b != 0) */
1503 /*                      return a / b; */
1504 /*              else { */
1505 /*                      if (a > 0) */
1506 /*                              return longBitsToDouble(DBL_POSINF); */
1507 /*                      else if (a < 0) */
1508 /*                              return longBitsToDouble(DBL_NEGINF); */
1509 /*              } */
1510 /*      } */
1511
1512         /* keep compiler happy */
1513         return 0;
1514 }
1515
1516
1517 double builtin_drem(double a, double b)
1518 {
1519         return fmod(a, b);
1520 }
1521
1522
1523 double builtin_dneg(double a)
1524 {
1525         if (isnan(a)) return a;
1526         else {
1527                 if (finite(a)) return -a;
1528                 else return copysign(a, -copysign(1.0, a));
1529         }
1530 }
1531
1532
1533 s4 builtin_dcmpl(double a, double b)
1534 {
1535         if (isnan(a)) return -1;
1536         if (isnan(b)) return -1;
1537         if (!finite(a) || !finite(b)) {
1538                 a = finite(a) ? 0 : copysign(1.0, a);
1539                 b = finite(b) ? 0 : copysign(1.0, b);
1540         }
1541         if (a > b) return 1;
1542         if (a == b) return 0;
1543         return -1;
1544 }
1545
1546
1547 s4 builtin_dcmpg(double a, double b)
1548 {
1549         if (isnan(a)) return 1;
1550         if (isnan(b)) return 1;
1551         if (!finite(a) || !finite(b)) {
1552                 a = finite(a) ? 0 : copysign(1.0, a);
1553                 b = finite(b) ? 0 : copysign(1.0, b);
1554         }
1555         if (a > b) return 1;
1556         if (a == b) return 0;
1557         return -1;
1558 }
1559
1560
1561 /*********************** Conversion operations ****************************/
1562
1563 s8 builtin_i2l(s4 i)
1564 {
1565 #if U8_AVAILABLE
1566         return i;
1567 #else
1568         s8 v;
1569         v.high = 0;
1570         v.low = i;
1571         return v;
1572 #endif
1573 }
1574
1575
1576 float builtin_i2f(s4 a)
1577 {
1578         float f = (float) a;
1579         return f;
1580 }
1581
1582
1583 double builtin_i2d(s4 a)
1584 {
1585         double d = (double) a;
1586         return d;
1587 }
1588
1589
1590 s4 builtin_l2i(s8 l)
1591 {
1592 #if U8_AVAILABLE
1593         return (s4) l;
1594 #else
1595         return l.low;
1596 #endif
1597 }
1598
1599
1600 float builtin_l2f(s8 a)
1601 {
1602 #if U8_AVAILABLE
1603         float f = (float) a;
1604         return f;
1605 #else
1606         return 0.0;
1607 #endif
1608 }
1609
1610
1611 double builtin_l2d(s8 a)
1612 {
1613 #if U8_AVAILABLE
1614         double d = (double) a;
1615         return d;
1616 #else
1617         return 0.0;
1618 #endif
1619 }
1620
1621
1622 s4 builtin_f2i(float a) 
1623 {
1624
1625         return builtin_d2i((double) a);
1626
1627         /*      float f;
1628         
1629                 if (isnanf(a))
1630                 return 0;
1631                 if (finitef(a)) {
1632                 if (a > 2147483647)
1633                 return 2147483647;
1634                 if (a < (-2147483648))
1635                 return (-2147483648);
1636                 return (s4) a;
1637                 }
1638                 f = copysignf((float) 1.0, a);
1639                 if (f > 0)
1640                 return 2147483647;
1641                 return (-2147483648); */
1642 }
1643
1644
1645 s8 builtin_f2l(float a)
1646 {
1647
1648         return builtin_d2l((double) a);
1649
1650         /*      float f;
1651         
1652                 if (finitef(a)) {
1653                 if (a > 9223372036854775807L)
1654                 return 9223372036854775807L;
1655                 if (a < (-9223372036854775808L))
1656                 return (-9223372036854775808L);
1657                 return (s8) a;
1658                 }
1659                 if (isnanf(a))
1660                 return 0;
1661                 f = copysignf((float) 1.0, a);
1662                 if (f > 0)
1663                 return 9223372036854775807L;
1664                 return (-9223372036854775808L); */
1665 }
1666
1667
1668 double builtin_f2d(float a)
1669 {
1670         if (finitef(a)) return (double) a;
1671         else {
1672                 if (isnanf(a))
1673                         return longBitsToDouble(DBL_NAN);
1674                 else
1675                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1676         }
1677 }
1678
1679
1680 s4 builtin_d2i(double a) 
1681
1682         double d;
1683         
1684         if (finite(a)) {
1685                 if (a >= 2147483647)
1686                         return 2147483647;
1687                 if (a <= (-2147483647-1))
1688                         return (-2147483647-1);
1689                 return (s4) a;
1690         }
1691         if (isnan(a))
1692                 return 0;
1693         d = copysign(1.0, a);
1694         if (d > 0)
1695                 return 2147483647;
1696         return (-2147483647-1);
1697 }
1698
1699
1700 s8 builtin_d2l(double a)
1701 {
1702         double d;
1703         
1704         if (finite(a)) {
1705                 if (a >= 9223372036854775807LL)
1706                         return 9223372036854775807LL;
1707                 if (a <= (-9223372036854775807LL-1))
1708                         return (-9223372036854775807LL-1);
1709                 return (s8) a;
1710         }
1711         if (isnan(a))
1712                 return 0;
1713         d = copysign(1.0, a);
1714         if (d > 0)
1715                 return 9223372036854775807LL;
1716         return (-9223372036854775807LL-1);
1717 }
1718
1719
1720 float builtin_d2f(double a)
1721 {
1722         if (finite(a))
1723                 return (float) a;
1724         else {
1725                 if (isnan(a))
1726                         return intBitsToFloat(FLT_NAN);
1727                 else
1728                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1729         }
1730 }
1731
1732
1733 /* used to convert FLT_xxx defines into float values */
1734
1735 inline float intBitsToFloat(s4 i)
1736 {
1737         imm_union imb;
1738
1739         imb.i = i;
1740         return imb.f;
1741 }
1742
1743
1744 /* used to convert DBL_xxx defines into double values */
1745
1746 inline float longBitsToDouble(s8 l)
1747 {
1748         imm_union imb;
1749
1750         imb.l = l;
1751         return imb.d;
1752 }
1753
1754
1755 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1756 {
1757         return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1758 }
1759
1760
1761 s4 builtin_dummy()
1762 {
1763         panic("Internal error: builtin_dummy called (native function is missing)");
1764         return 0; /* for the compiler */
1765 }
1766
1767
1768 /* builtin_asm_get_exceptionptrptr *********************************************
1769
1770    this is a wrapper for calls from asmpart
1771
1772 *******************************************************************************/
1773
1774 java_objectheader **builtin_asm_get_exceptionptrptr()
1775 {
1776         return builtin_get_exceptionptrptr();
1777 }
1778
1779
1780 methodinfo *builtin_asm_get_threadrootmethod()
1781 {
1782         return *threadrootmethod;
1783 }
1784
1785
1786 inline void* builtin_asm_get_stackframeinfo()
1787 {
1788 /*log_text("builtin_asm_get_stackframeinfo()");*/
1789 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1790         return &THREADINFO->_stackframeinfo;
1791 #else
1792 #if defined(__GNUC__)
1793 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1794 #endif
1795                 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1796 #endif
1797 }
1798
1799 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1800 /*      stacktraceelement *el;*/
1801         size_t s;
1802         s=(end-begin);
1803         /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1804         *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1805 #if 0
1806         *el=MNEW(stacktraceelement,s+1); /*GC*/
1807 #endif
1808         memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1809         (*el)[s].method=0;
1810 #if defined(__GNUC__)
1811 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1812 #endif
1813         (*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 */
1814         return *el;
1815 }
1816
1817 /*
1818  * These are local overrides for various environment variables in Emacs.
1819  * Please do not remove this and leave it at the end of the file, where
1820  * Emacs will automagically detect them.
1821  * ---------------------------------------------------------------------
1822  * Local variables:
1823  * mode: c
1824  * indent-tabs-mode: t
1825  * c-basic-offset: 4
1826  * tab-width: 4
1827  * End:
1828  */