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