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