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