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