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