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