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