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