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