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