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