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