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