Static analysis changes to parse starting with Object.<clinit>
[cacao.git] / src / vm / 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 907 2004-01-29 13:20:05Z carolyn $
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 (initverbose) {
485                 char logtext[MAXLOGTEXT];
486                 sprintf(logtext, "Initialize class ");
487                 utf_sprint(logtext + strlen(logtext), c->name);
488                 sprintf(logtext + strlen(logtext), " (from builtin_new)");
489                 log_text(logtext);
490         }
491         class_init(c);
492
493 #ifdef SIZE_FROM_CLASSINFO
494         c->alignedsize = align_size(c->instancesize);
495         o = heap_allocate(c->alignedsize, true, c->finalizer);
496 #else
497         o = heap_allocate(c->instancesize, true, c->finalizer);
498 #endif
499         if (!o) return NULL;
500         
501         memset(o, 0, c->instancesize);
502
503         o->vftbl = c->vftbl;
504
505         return o;
506 }
507
508 /********************** Function: builtin_newarray **************************
509
510         Creates an array with the given vftbl on the heap.
511
512         Return value:  pointer to the array or NULL if no memory is available
513
514     CAUTION: The given vftbl must be the vftbl of the *array* class,
515     not of the element class.
516
517 *****************************************************************************/
518
519 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
520 {
521         java_arrayheader *a;
522         arraydescriptor *desc = arrayvftbl->arraydesc;
523         s4 dataoffset = desc->dataoffset;
524         s4 componentsize = desc->componentsize;
525         s4 actualsize;
526
527         if (size<0) {
528                 *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
529                 return NULL;
530         }
531 #ifdef SIZE_FROM_CLASSINFO
532         actualsize = align_size(dataoffset + size * componentsize);
533 #else
534         actualsize = dataoffset + size * componentsize;
535 #endif
536
537         if (((u4)actualsize)<((u4)size)) { /* overflow */
538                 *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
539                 return NULL;
540         }
541         a = heap_allocate(actualsize,
542                                           (desc->arraytype == ARRAYTYPE_OBJECT),
543                                           NULL);
544
545         if (!a) return NULL;
546         memset(a, 0, actualsize);
547
548
549         /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
550
551         a->objheader.vftbl = arrayvftbl;
552         a->size = size;
553 #ifdef SIZE_FROM_CLASSINFO
554         a->alignedsize = actualsize;
555 #endif
556
557         return a;
558 }
559
560
561 /********************** Function: builtin_anewarray *************************
562
563         Creates an array of references to the given class type on the heap.
564
565         Return value:  pointer to the array or NULL if no memory is available
566
567     XXX This function does not do The Right Thing, because it uses a
568     classinfo pointer at runtime. builtin_newarray should be used
569     instead.
570
571 *****************************************************************************/
572
573 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
574 {
575         return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
576 }
577
578
579 /******************** Function: builtin_newarray_int ***********************
580
581         Creates an array of 32 bit Integers on the heap.
582
583         Return value:  pointer to the array or NULL if no memory is available
584
585 *****************************************************************************/
586
587 java_intarray *builtin_newarray_int(s4 size)
588 {
589         return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
590 }
591
592
593 /******************** Function: builtin_newarray_long ***********************
594
595         Creates an array of 64 bit Integers on the heap.
596
597         Return value:  pointer to the array or NULL if no memory is available
598
599 *****************************************************************************/
600
601 java_longarray *builtin_newarray_long(s4 size)
602 {
603         return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
604 }
605
606
607 /******************** function: builtin_newarray_float ***********************
608
609         Creates an array of 32 bit IEEE floats on the heap.
610
611         Return value:  pointer to the array or NULL if no memory is available
612
613 *****************************************************************************/
614
615 java_floatarray *builtin_newarray_float(s4 size)
616 {
617         return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
618 }
619
620
621 /******************** function: builtin_newarray_double ***********************
622
623         Creates an array of 64 bit IEEE floats on the heap.
624
625         Return value:  pointer to the array or NULL if no memory is available
626
627 *****************************************************************************/
628
629 java_doublearray *builtin_newarray_double(s4 size)
630 {
631         return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
632 }
633
634
635 /******************** function: builtin_newarray_byte ***********************
636
637         Creates an array of 8 bit Integers on the heap.
638
639         Return value:  pointer to the array or NULL if no memory is available
640
641 *****************************************************************************/
642
643 java_bytearray *builtin_newarray_byte(s4 size)
644 {
645         return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
646 }
647
648
649 /******************** function: builtin_newarray_char ************************
650
651         Creates an array of characters on the heap.
652
653         Return value:  pointer to the array or NULL if no memory is available
654
655 *****************************************************************************/
656
657 java_chararray *builtin_newarray_char(s4 size)
658 {
659         return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
660 }
661
662
663 /******************** function: builtin_newarray_short ***********************
664
665         Creates an array of 16 bit Integers on the heap.
666
667         Return value:  pointer to the array or NULL if no memory is available
668
669 *****************************************************************************/
670
671 java_shortarray *builtin_newarray_short(s4 size)
672 {
673         return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
674 }
675
676
677 /******************** function: builtin_newarray_boolean ************************
678
679         Creates an array of bytes on the heap. The array is designated as an array
680         of booleans (important for casts)
681         
682         Return value:  pointer to the array or NULL if no memory is available
683
684 *****************************************************************************/
685
686 java_booleanarray *builtin_newarray_boolean(s4 size)
687 {
688         return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
689 }
690
691
692 /**************** function: builtin_nmultianewarray ***************************
693
694         Creates a multi-dimensional array on the heap. The dimensions are passed in
695         an array of longs.
696
697     Arguments:
698         n............number of dimensions to create
699         arrayvftbl...vftbl of the array class
700         dims.........array containing the size of each dimension to create
701
702         Return value:  pointer to the array or NULL if no memory is available
703
704 ******************************************************************************/
705
706         /* Helper functions */
707
708 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
709 {
710         int size, i;
711         java_arrayheader *a;
712         vftbl *componentvftbl;
713
714         /* create this dimension */
715         size = (int) dims[0];
716         a = builtin_newarray(size,arrayvftbl);
717         if (!a) return NULL;
718
719         /* if this is the last dimension return */
720         if (!--n) return a;
721
722         /* get the vftbl of the components to create */
723         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
724
725         /* The verifier guarantees this. */
726         /* if (!componentvftbl) */
727         /*      panic ("multianewarray with too many dimensions"); */
728
729         /* create the component arrays */
730         for (i = 0; i < size; i++) {
731                 java_arrayheader *ea = 
732                         builtin_nmultianewarray(n,componentvftbl,dims+1);
733                 if (!ea) return NULL;
734                 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
735         }
736
737         return a;
738 }
739
740
741 /*****************************************************************************
742                                           METHOD LOGGING
743
744         Various functions for printing a message at method entry or exit (for
745         debugging)
746         
747 *****************************************************************************/
748
749
750 u4 methodindent = 0;
751
752 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
753                                                                                    methodinfo *method, int *pos, 
754                                                                                    int noindent)
755 {
756         if (!noindent) {
757                 if (methodindent)
758                         methodindent--;
759                 else
760                         log_text("WARNING: unmatched methodindent--");
761         }
762         if (verbose || runverbose) {
763                 printf("Exception ");
764                 if (_exceptionptr) {
765                         utf_display (_exceptionptr->vftbl->class->name);
766                 }
767                 else {
768                         printf("Error: <Nullpointer instead of exception>");
769                         if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
770                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
771                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
772                         if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
773                         if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
774                         if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
775                         if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
776                         if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
777                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
778                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
779
780                 }
781                 printf(" thrown in ");
782                 if (method) {
783                         utf_display (method->class->name);
784                         printf(".");
785                         utf_display (method->name);
786                         if (method->flags & ACC_SYNCHRONIZED)
787                                 printf("(SYNC)");
788                         else
789                                 printf("(NOSYNC)");
790                         printf("(%p) at position %p\n", method->entrypoint, pos);
791                 }
792                 else
793                         printf("call_java_method\n");
794                 fflush (stdout);
795         }
796         return _exceptionptr;
797 }
798
799
800 #ifdef TRACE_ARGS_NUM
801 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
802 #if TRACE_ARGS_NUM > 6
803                                                 s8 a6, s8 a7,
804 #endif
805                                                 methodinfo *method)
806 {
807         int i;
808         char logtext[MAXLOGTEXT];
809         for (i = 0; i < methodindent; i++)
810                 logtext[i] = '\t';
811         sprintf(logtext + methodindent, "called: ");
812         utf_sprint(logtext + strlen(logtext), method->class->name);
813         sprintf(logtext + strlen(logtext), ".");
814         utf_sprint(logtext + strlen(logtext), method->name);
815         utf_sprint(logtext + strlen(logtext), method->descriptor);
816
817         if ( method->flags & ACC_PUBLIC )       sprintf (logtext + strlen(logtext)," PUBLIC");
818         if ( method->flags & ACC_PRIVATE )      sprintf (logtext + strlen(logtext)," PRIVATE");
819         if ( method->flags & ACC_PROTECTED )    sprintf (logtext + strlen(logtext)," PROTECTED");
820         if ( method->flags & ACC_STATIC )       sprintf (logtext + strlen(logtext)," STATIC");
821         if ( method->flags & ACC_FINAL )        sprintf (logtext + strlen(logtext)," FINAL");
822         if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
823         if ( method->flags & ACC_VOLATILE )     sprintf (logtext + strlen(logtext)," VOLATILE");
824         if ( method->flags & ACC_TRANSIENT )    sprintf (logtext + strlen(logtext)," TRANSIENT");
825         if ( method->flags & ACC_NATIVE )       sprintf (logtext + strlen(logtext)," NATIVE");
826         if ( method->flags & ACC_INTERFACE )    sprintf (logtext + strlen(logtext)," INTERFACE");
827         if ( method->flags & ACC_ABSTRACT )     sprintf (logtext + strlen(logtext)," ABSTRACT");
828         
829
830         sprintf(logtext + strlen(logtext), "(");
831
832         switch (method->paramcount) {
833         case 0:
834                 break;
835
836 #if defined(__I386__)
837         case 1:
838                 sprintf(logtext+strlen(logtext), "%llx", a0);
839                 break;
840
841         case 2:
842                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
843                 break;
844
845         case 3:
846                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
847                 break;
848
849         case 4:
850                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
851                                 a0,   a1,   a2,   a3);
852                 break;
853
854         case 5:
855                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
856                                 a0,   a1,   a2,   a3,   a4);
857                 break;
858
859         case 6:
860                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
861                                 a0,   a1,   a2,   a3,   a4,   a5);
862                 break;
863
864 #if TRACE_ARGS_NUM > 6
865         case 7:
866                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
867                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
868                 break;
869
870         case 8:
871                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
872                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
873                 break;
874
875         default:
876                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
877                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   method->paramcount - 8);
878                 break;
879 #else
880         default:
881                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
882                                 a0,   a1,   a2,   a3,   a4,   a5,   method->paramcount - 6);
883                 break;
884 #endif
885 #else
886         case 1:
887                 sprintf(logtext+strlen(logtext), "%lx", a0);
888                 break;
889
890         case 2:
891                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
892                 break;
893
894         case 3:
895                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
896                 break;
897
898         case 4:
899                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
900                                 a0,  a1,  a2,  a3);
901                 break;
902
903         case 5:
904                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
905                                 a0,  a1,  a2,  a3,  a4);
906                 break;
907
908         case 6:
909                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
910                                 a0,  a1,  a2,  a3,  a4,  a5);
911                 break;
912
913 #if TRACE_ARGS_NUM > 6
914         case 7:
915                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
916                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
917                 break;
918
919         case 8:
920                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
921                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
922                 break;
923
924         default:
925                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
926                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  method->paramcount - 8);
927                 break;
928 #else
929         default:
930                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
931                                 a0,  a1,  a2,  a3,  a4,  a5,   method->paramcount - 6);
932                 break;
933 #endif
934 #endif
935         }
936         sprintf (logtext+strlen(logtext), ")");
937         log_text(logtext);
938
939         methodindent++;
940 }
941 #endif
942
943
944 void builtin_displaymethodstart(methodinfo *method)
945 {
946         char logtext[MAXLOGTEXT];
947         sprintf(logtext, "                                                                                              ");
948         sprintf(logtext + methodindent, "called: ");
949         utf_sprint(logtext + strlen(logtext), method->class->name);
950         sprintf(logtext + strlen(logtext), ".");
951         utf_sprint(logtext + strlen(logtext), method->name);
952         utf_sprint(logtext + strlen(logtext), method->descriptor);
953
954         if ( method->flags & ACC_PUBLIC )       sprintf (logtext + strlen(logtext)," PUBLIC");
955         if ( method->flags & ACC_PRIVATE )      sprintf (logtext + strlen(logtext)," PRIVATE");
956         if ( method->flags & ACC_PROTECTED )    sprintf (logtext + strlen(logtext)," PROTECTED");
957         if ( method->flags & ACC_STATIC )       sprintf (logtext + strlen(logtext)," STATIC");
958         if ( method->flags & ACC_FINAL )        sprintf (logtext + strlen(logtext)," FINAL");
959         if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
960         if ( method->flags & ACC_VOLATILE )     sprintf (logtext + strlen(logtext)," VOLATILE");
961         if ( method->flags & ACC_TRANSIENT )    sprintf (logtext + strlen(logtext)," TRANSIENT");
962         if ( method->flags & ACC_NATIVE )       sprintf (logtext + strlen(logtext)," NATIVE");
963         if ( method->flags & ACC_INTERFACE )    sprintf (logtext + strlen(logtext)," INTERFACE");
964         if ( method->flags & ACC_ABSTRACT )     sprintf (logtext + strlen(logtext)," ABSTRACT");
965
966         log_text(logtext);
967         methodindent++;
968 }
969
970
971 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
972 {
973         int i;
974         char logtext[MAXLOGTEXT];
975         for (i = 0; i < methodindent; i++)
976                 logtext[i] = '\t';
977         if (methodindent)
978                 methodindent--;
979         else
980                 log_text("WARNING: unmatched methodindent--");
981         sprintf(logtext + methodindent, "finished: ");
982         utf_sprint(logtext + strlen(logtext), method->class->name);
983         sprintf(logtext + strlen(logtext), ".");
984         utf_sprint(logtext + strlen(logtext), method->name);
985         utf_sprint(logtext + strlen(logtext), method->descriptor);
986
987         switch (method->returntype) {
988         case TYPE_INT:
989                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
990                 break;
991         case TYPE_LONG:
992 #if defined(__I386__)
993                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
994 #else
995                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
996 #endif
997                 break;
998         case TYPE_ADDRESS:
999 #if defined(__I386__)
1000                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1001 #else
1002                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1003 #endif
1004                 break;
1005         case TYPE_FLOAT:
1006                 sprintf(logtext + strlen(logtext), "->%g", f);
1007                 break;
1008         case TYPE_DOUBLE:
1009                 sprintf(logtext + strlen(logtext), "->%g", d);
1010                 break;
1011         }
1012         log_text(logtext);
1013 }
1014
1015
1016 void builtin_displaymethodexception(methodinfo *method)
1017 {
1018         int i;
1019         char logtext[MAXLOGTEXT];
1020         for (i = 0; i < methodindent; i++)
1021                 logtext[i] = '\t';
1022         sprintf(logtext + methodindent, "exception abort: ");
1023         utf_sprint(logtext + strlen(logtext), method->class->name);
1024         sprintf(logtext + strlen(logtext), ".");
1025         utf_sprint(logtext + strlen(logtext), method->name);
1026         utf_sprint(logtext + strlen(logtext), method->descriptor);
1027         log_text(logtext);
1028 }
1029
1030
1031 /****************************************************************************
1032                          SYNCHRONIZATION FUNCTIONS
1033 *****************************************************************************/
1034
1035 /*
1036  * Lock the mutex of an object.
1037  */
1038 void internal_lock_mutex_for_object(java_objectheader *object)
1039 {
1040 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1041         mutexHashEntry *entry;
1042         int hashValue;
1043
1044         assert(object != 0);
1045
1046         hashValue = MUTEX_HASH_VALUE(object);
1047         entry = &mutexHashTable[hashValue];
1048
1049         if (entry->object != 0) {
1050                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1051                         entry->object = 0;
1052                         entry->mutex.holder = 0;
1053                         entry->mutex.count = 0;
1054                         entry->mutex.muxWaiters = 0;
1055
1056                 } else {
1057                         while (entry->next != 0 && entry->object != object)
1058                                 entry = entry->next;
1059
1060                         if (entry->object != object) {
1061                                 entry->next = firstFreeOverflowEntry;
1062                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1063
1064                                 entry = entry->next;
1065                                 entry->object = 0;
1066                                 entry->next = 0;
1067                                 assert(entry->conditionCount == 0);
1068                         }
1069                 }
1070
1071         } else {
1072                 entry->mutex.holder = 0;
1073                 entry->mutex.count = 0;
1074                 entry->mutex.muxWaiters = 0;
1075         }
1076
1077         if (entry->object == 0)
1078                 entry->object = object;
1079         
1080         internal_lock_mutex(&entry->mutex);
1081 #endif
1082 }
1083
1084
1085 /*
1086  * Unlocks the mutex of an object.
1087  */
1088 void internal_unlock_mutex_for_object (java_objectheader *object)
1089 {
1090 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1091         int hashValue;
1092         mutexHashEntry *entry;
1093
1094         hashValue = MUTEX_HASH_VALUE(object);
1095         entry = &mutexHashTable[hashValue];
1096
1097         if (entry->object == object) {
1098                 internal_unlock_mutex(&entry->mutex);
1099
1100         } else {
1101                 while (entry->next != 0 && entry->next->object != object)
1102                         entry = entry->next;
1103
1104                 assert(entry->next != 0);
1105
1106                 internal_unlock_mutex(&entry->next->mutex);
1107
1108                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1109                         mutexHashEntry *unlinked = entry->next;
1110
1111                         entry->next = unlinked->next;
1112                         unlinked->next = firstFreeOverflowEntry;
1113                         firstFreeOverflowEntry = unlinked;
1114                 }
1115         }
1116 #endif
1117 }
1118
1119
1120 void builtin_monitorenter(java_objectheader *o)
1121 {
1122 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1123         int hashValue;
1124
1125         assert(blockInts == 0);
1126
1127         ++blockInts;
1128
1129         hashValue = MUTEX_HASH_VALUE(o);
1130         if (mutexHashTable[hashValue].object == o 
1131                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1132                 ++mutexHashTable[hashValue].mutex.count;
1133         else
1134                 internal_lock_mutex_for_object(o);
1135
1136         --blockInts;
1137
1138         assert(blockInts == 0);
1139 #endif
1140 }
1141
1142
1143 void builtin_monitorexit (java_objectheader *o)
1144 {
1145 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1146         int hashValue;
1147
1148         assert(blockInts == 0);
1149
1150         ++blockInts;
1151
1152         hashValue = MUTEX_HASH_VALUE(o);
1153         if (mutexHashTable[hashValue].object == o) {
1154                 if (mutexHashTable[hashValue].mutex.count == 1
1155                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1156                         internal_unlock_mutex_for_object(o);
1157                 else
1158                         --mutexHashTable[hashValue].mutex.count;
1159
1160         } else
1161                 internal_unlock_mutex_for_object(o);
1162
1163         --blockInts;
1164
1165         assert(blockInts == 0);
1166 #endif
1167 }
1168
1169
1170 /*****************************************************************************
1171                           MISCELLANEOUS HELPER FUNCTIONS
1172 *****************************************************************************/
1173
1174
1175
1176 /*********** Functions for integer divisions *****************************
1177  
1178         On some systems (eg. DEC ALPHA), integer division is not supported by the
1179         CPU. These helper functions implement the missing functionality.
1180
1181 ******************************************************************************/
1182
1183 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1184 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1185
1186
1187 /************** Functions for long arithmetics *******************************
1188
1189         On systems where 64 bit Integers are not supported by the CPU, these
1190         functions are needed.
1191
1192 ******************************************************************************/
1193
1194
1195 s8 builtin_ladd(s8 a, s8 b)
1196
1197 #if U8_AVAILABLE
1198         return a + b; 
1199 #else
1200         return builtin_i2l(0);
1201 #endif
1202 }
1203
1204 s8 builtin_lsub(s8 a, s8 b) 
1205
1206 #if U8_AVAILABLE
1207         return a - b; 
1208 #else
1209         return builtin_i2l(0);
1210 #endif
1211 }
1212
1213 s8 builtin_lmul(s8 a, s8 b) 
1214
1215 #if U8_AVAILABLE
1216         return a * b; 
1217 #else
1218         return builtin_i2l(0);
1219 #endif
1220 }
1221
1222 s8 builtin_ldiv(s8 a, s8 b) 
1223
1224 #if U8_AVAILABLE
1225         return a / b; 
1226 #else
1227         return builtin_i2l(0);
1228 #endif
1229 }
1230
1231 s8 builtin_lrem(s8 a, s8 b) 
1232
1233 #if U8_AVAILABLE
1234         return a % b; 
1235 #else
1236         return builtin_i2l(0);
1237 #endif
1238 }
1239
1240 s8 builtin_lshl(s8 a, s4 b) 
1241
1242 #if U8_AVAILABLE
1243         return a << (b & 63);
1244 #else
1245         return builtin_i2l(0);
1246 #endif
1247 }
1248
1249 s8 builtin_lshr(s8 a, s4 b) 
1250
1251 #if U8_AVAILABLE
1252         return a >> (b & 63);
1253 #else
1254         return builtin_i2l(0);
1255 #endif
1256 }
1257
1258 s8 builtin_lushr(s8 a, s4 b) 
1259
1260 #if U8_AVAILABLE
1261         return ((u8) a) >> (b & 63);
1262 #else
1263         return builtin_i2l(0);
1264 #endif
1265 }
1266
1267 s8 builtin_land(s8 a, s8 b) 
1268
1269 #if U8_AVAILABLE
1270         return a & b; 
1271 #else
1272         return builtin_i2l(0);
1273 #endif
1274 }
1275
1276 s8 builtin_lor(s8 a, s8 b) 
1277
1278 #if U8_AVAILABLE
1279         return a | b; 
1280 #else
1281         return builtin_i2l(0);
1282 #endif
1283 }
1284
1285 s8 builtin_lxor(s8 a, s8 b) 
1286
1287 #if U8_AVAILABLE
1288         return a ^ b; 
1289 #else
1290         return builtin_i2l(0);
1291 #endif
1292 }
1293
1294 s8 builtin_lneg(s8 a) 
1295
1296 #if U8_AVAILABLE
1297         return -a;
1298 #else
1299         return builtin_i2l(0);
1300 #endif
1301 }
1302
1303 s4 builtin_lcmp(s8 a, s8 b) 
1304
1305 #if U8_AVAILABLE
1306         if (a < b) return -1;
1307         if (a > b) return 1;
1308         return 0;
1309 #else
1310         return 0;
1311 #endif
1312 }
1313
1314
1315
1316
1317
1318 /*********** Functions for floating point operations *************************/
1319
1320 float builtin_fadd(float a, float b)
1321 {
1322         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1323         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1324         if (finitef(a)) {
1325                 if (finitef(b))
1326                         return a + b;
1327                 else
1328                         return b;
1329         }
1330         else {
1331                 if (finitef(b))
1332                         return a;
1333                 else {
1334                         if (copysignf(1.0, a) == copysignf(1.0, b))
1335                                 return a;
1336                         else
1337                                 return intBitsToFloat(FLT_NAN);
1338                 }
1339         }
1340 }
1341
1342
1343 float builtin_fsub(float a, float b)
1344 {
1345         return builtin_fadd(a, builtin_fneg(b));
1346 }
1347
1348
1349 float builtin_fmul(float a, float b)
1350 {
1351         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1352         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1353         if (finitef(a)) {
1354                 if (finitef(b)) return a * b;
1355                 else {
1356                         if (a == 0) return intBitsToFloat(FLT_NAN);
1357                         else return copysignf(b, copysignf(1.0, b)*a);
1358                 }
1359         }
1360         else {
1361                 if (finitef(b)) {
1362                         if (b == 0) return intBitsToFloat(FLT_NAN);
1363                         else return copysignf(a, copysignf(1.0, a)*b);
1364                 }
1365                 else {
1366                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1367                 }
1368         }
1369 }
1370
1371
1372 float builtin_fdiv(float a, float b)
1373 {
1374         if (finitef(a) && finitef(b)) {
1375                 if (b != 0)
1376                         return a / b;
1377                 else {
1378                         if (a > 0)
1379                                 return intBitsToFloat(FLT_POSINF);
1380                         else if (a < 0)
1381                                 return intBitsToFloat(FLT_NEGINF);
1382                 }
1383         }
1384         return intBitsToFloat(FLT_NAN);
1385 }
1386
1387
1388 float builtin_frem(float a, float b)
1389 {
1390         return fmodf(a, b);
1391 }
1392
1393
1394 float builtin_fneg(float a)
1395 {
1396         if (isnanf(a)) return a;
1397         else {
1398                 if (finitef(a)) return -a;
1399                 else return copysignf(a, -copysignf(1.0, a));
1400         }
1401 }
1402
1403
1404 s4 builtin_fcmpl(float a, float b)
1405 {
1406         if (isnanf(a)) return -1;
1407         if (isnanf(b)) return -1;
1408         if (!finitef(a) || !finitef(b)) {
1409                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1410                 b = finitef(b) ? 0 : copysignf(1.0, b);
1411         }
1412         if (a > b) return 1;
1413         if (a == b) return 0;
1414         return -1;
1415 }
1416
1417
1418 s4 builtin_fcmpg(float a, float b)
1419 {
1420         if (isnanf(a)) return 1;
1421         if (isnanf(b)) return 1;
1422         if (!finitef(a) || !finitef(b)) {
1423                 a = finitef(a) ? 0 : copysignf(1.0, a);
1424                 b = finitef(b) ? 0 : copysignf(1.0, b);
1425         }
1426         if (a > b) return 1;
1427         if (a == b) return 0;
1428         return -1;
1429 }
1430
1431
1432
1433 /************************* Functions for doubles ****************************/
1434
1435 double builtin_dadd(double a, double b)
1436 {
1437         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1438         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1439         if (finite(a)) {
1440                 if (finite(b)) return a + b;
1441                 else return b;
1442         }
1443         else {
1444                 if (finite(b)) return a;
1445                 else {
1446                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1447                         else return longBitsToDouble(DBL_NAN);
1448                 }
1449         }
1450 }
1451
1452
1453 double builtin_dsub(double a, double b)
1454 {
1455         return builtin_dadd(a, builtin_dneg(b));
1456 }
1457
1458
1459 double builtin_dmul(double a, double b)
1460 {
1461         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1462         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1463         if (finite(a)) {
1464                 if (finite(b)) return a * b;
1465                 else {
1466                         if (a == 0) return longBitsToDouble(DBL_NAN);
1467                         else return copysign(b, copysign(1.0, b) * a);
1468                 }
1469         }
1470         else {
1471                 if (finite(b)) {
1472                         if (b == 0) return longBitsToDouble(DBL_NAN);
1473                         else return copysign(a, copysign(1.0, a) * b);
1474                 }
1475                 else {
1476                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1477                 }
1478         }
1479 }
1480
1481
1482 double builtin_ddiv(double a, double b)
1483 {
1484         if (finite(a)) {
1485                 if (finite(b)) {
1486                         return a / b;
1487
1488                 } else {
1489                         if (isnan(b))
1490                                 return longBitsToDouble(DBL_NAN);
1491                         else
1492                                 return copysign(0.0, b);
1493                 }
1494
1495         } else {
1496                 if (finite(b)) {
1497                         if (a > 0)
1498                                 return longBitsToDouble(DBL_POSINF);
1499                         else if (a < 0)
1500                                 return longBitsToDouble(DBL_NEGINF);
1501
1502                 } else
1503                         return longBitsToDouble(DBL_NAN);
1504         }
1505
1506 /*      if (finite(a) && finite(b)) { */
1507 /*              if (b != 0) */
1508 /*                      return a / b; */
1509 /*              else { */
1510 /*                      if (a > 0) */
1511 /*                              return longBitsToDouble(DBL_POSINF); */
1512 /*                      else if (a < 0) */
1513 /*                              return longBitsToDouble(DBL_NEGINF); */
1514 /*              } */
1515 /*      } */
1516
1517         /* keep compiler happy */
1518         return 0;
1519 }
1520
1521
1522 double builtin_drem(double a, double b)
1523 {
1524         return fmod(a, b);
1525 }
1526
1527
1528 double builtin_dneg(double a)
1529 {
1530         if (isnan(a)) return a;
1531         else {
1532                 if (finite(a)) return -a;
1533                 else return copysign(a, -copysign(1.0, a));
1534         }
1535 }
1536
1537
1538 s4 builtin_dcmpl(double a, double b)
1539 {
1540         if (isnan(a)) return -1;
1541         if (isnan(b)) return -1;
1542         if (!finite(a) || !finite(b)) {
1543                 a = finite(a) ? 0 : copysign(1.0, a);
1544                 b = finite(b) ? 0 : copysign(1.0, b);
1545         }
1546         if (a > b) return 1;
1547         if (a == b) return 0;
1548         return -1;
1549 }
1550
1551
1552 s4 builtin_dcmpg(double a, double b)
1553 {
1554         if (isnan(a)) return 1;
1555         if (isnan(b)) return 1;
1556         if (!finite(a) || !finite(b)) {
1557                 a = finite(a) ? 0 : copysign(1.0, a);
1558                 b = finite(b) ? 0 : copysign(1.0, b);
1559         }
1560         if (a > b) return 1;
1561         if (a == b) return 0;
1562         return -1;
1563 }
1564
1565
1566 /*********************** Conversion operations ****************************/
1567
1568 s8 builtin_i2l(s4 i)
1569 {
1570 #if U8_AVAILABLE
1571         return i;
1572 #else
1573         s8 v;
1574         v.high = 0;
1575         v.low = i;
1576         return v;
1577 #endif
1578 }
1579
1580
1581 float builtin_i2f(s4 a)
1582 {
1583         float f = (float) a;
1584         return f;
1585 }
1586
1587
1588 double builtin_i2d(s4 a)
1589 {
1590         double d = (double) a;
1591         return d;
1592 }
1593
1594
1595 s4 builtin_l2i(s8 l)
1596 {
1597 #if U8_AVAILABLE
1598         return (s4) l;
1599 #else
1600         return l.low;
1601 #endif
1602 }
1603
1604
1605 float builtin_l2f(s8 a)
1606 {
1607 #if U8_AVAILABLE
1608         float f = (float) a;
1609         return f;
1610 #else
1611         return 0.0;
1612 #endif
1613 }
1614
1615
1616 double builtin_l2d(s8 a)
1617 {
1618 #if U8_AVAILABLE
1619         double d = (double) a;
1620         return d;
1621 #else
1622         return 0.0;
1623 #endif
1624 }
1625
1626
1627 s4 builtin_f2i(float a) 
1628 {
1629
1630         return builtin_d2i((double) a);
1631
1632         /*      float f;
1633         
1634                 if (isnanf(a))
1635                 return 0;
1636                 if (finitef(a)) {
1637                 if (a > 2147483647)
1638                 return 2147483647;
1639                 if (a < (-2147483648))
1640                 return (-2147483648);
1641                 return (s4) a;
1642                 }
1643                 f = copysignf((float) 1.0, a);
1644                 if (f > 0)
1645                 return 2147483647;
1646                 return (-2147483648); */
1647 }
1648
1649
1650 s8 builtin_f2l(float a)
1651 {
1652
1653         return builtin_d2l((double) a);
1654
1655         /*      float f;
1656         
1657                 if (finitef(a)) {
1658                 if (a > 9223372036854775807L)
1659                 return 9223372036854775807L;
1660                 if (a < (-9223372036854775808L))
1661                 return (-9223372036854775808L);
1662                 return (s8) a;
1663                 }
1664                 if (isnanf(a))
1665                 return 0;
1666                 f = copysignf((float) 1.0, a);
1667                 if (f > 0)
1668                 return 9223372036854775807L;
1669                 return (-9223372036854775808L); */
1670 }
1671
1672
1673 double builtin_f2d(float a)
1674 {
1675         if (finitef(a)) return (double) a;
1676         else {
1677                 if (isnanf(a))
1678                         return longBitsToDouble(DBL_NAN);
1679                 else
1680                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1681         }
1682 }
1683
1684
1685 s4 builtin_d2i(double a) 
1686
1687         double d;
1688         
1689         if (finite(a)) {
1690                 if (a >= 2147483647)
1691                         return 2147483647;
1692                 if (a <= (-2147483647-1))
1693                         return (-2147483647-1);
1694                 return (s4) a;
1695         }
1696         if (isnan(a))
1697                 return 0;
1698         d = copysign(1.0, a);
1699         if (d > 0)
1700                 return 2147483647;
1701         return (-2147483647-1);
1702 }
1703
1704
1705 s8 builtin_d2l(double a)
1706 {
1707         double d;
1708         
1709         if (finite(a)) {
1710                 if (a >= 9223372036854775807LL)
1711                         return 9223372036854775807LL;
1712                 if (a <= (-9223372036854775807LL-1))
1713                         return (-9223372036854775807LL-1);
1714                 return (s8) a;
1715         }
1716         if (isnan(a))
1717                 return 0;
1718         d = copysign(1.0, a);
1719         if (d > 0)
1720                 return 9223372036854775807LL;
1721         return (-9223372036854775807LL-1);
1722 }
1723
1724
1725 float builtin_d2f(double a)
1726 {
1727         if (finite(a))
1728                 return (float) a;
1729         else {
1730                 if (isnan(a))
1731                         return intBitsToFloat(FLT_NAN);
1732                 else
1733                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1734         }
1735 }
1736
1737
1738 /* used to convert FLT_xxx defines into float values */
1739
1740 inline float intBitsToFloat(s4 i)
1741 {
1742         imm_union imb;
1743
1744         imb.i = i;
1745         return imb.f;
1746 }
1747
1748
1749 /* used to convert DBL_xxx defines into double values */
1750
1751 inline float longBitsToDouble(s8 l)
1752 {
1753         imm_union imb;
1754
1755         imb.l = l;
1756         return imb.d;
1757 }
1758
1759
1760 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1761 {
1762         return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1763 }
1764
1765 s4 builtin_dummy()
1766 {
1767         panic("Internal error: builtin_dummy called (native function is missing)");
1768         return 0; /* for the compiler */
1769 }
1770
1771
1772 /*
1773  * These are local overrides for various environment variables in Emacs.
1774  * Please do not remove this and leave it at the end of the file, where
1775  * Emacs will automagically detect them.
1776  * ---------------------------------------------------------------------
1777  * Local variables:
1778  * mode: c
1779  * indent-tabs-mode: t
1780  * c-basic-offset: 4
1781  * tab-width: 4
1782  * End:
1783  */