* class_java_lang_NoSuchMethodError: Added.
[cacao.git] / src / vm / builtin.c
1 /* src/vm/builtin.c - functions for unsupported operations
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
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    Changes: Christian Thalinger
32
33    Contains C functions for JavaVM Instructions that cannot be
34    translated to machine language directly. Consequently, the
35    generated machine code for these instructions contains function
36    calls instead of machine instructions, using the C calling
37    convention.
38
39    $Id: builtin.c 3613 2005-11-07 17:57:56Z twisti $
40
41 */
42
43
44 #include <assert.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include "config.h"
49 #include "vm/types.h"
50
51 #include "arch.h"
52 #include "md-abi.h"
53
54 #include "fdlibm/fdlibm.h"
55
56 #include "mm/boehm.h"
57 #include "mm/memory.h"
58 #include "native/native.h"
59 #include "native/include/java_lang_Cloneable.h"
60 #include "native/include/java_lang_Object.h"          /* required by VMObject */
61 #include "native/include/java_lang_VMObject.h"
62 #include "native/include/java_lang_Throwable.h"
63 #include "native/include/java_lang_VMThrowable.h"
64
65 #if defined(USE_THREADS)
66 # if defined(NATIVE_THREADS)
67 #  include "threads/native/threads.h"
68 # else
69 #  include "threads/green/threads.h"
70 #  include "threads/green/locks.h"
71 # endif
72 #endif
73
74 #include "toolbox/logging.h"
75 #include "toolbox/util.h"
76 #include "vm/builtin.h"
77 #include "vm/exceptions.h"
78 #include "vm/global.h"
79 #include "vm/initialize.h"
80 #include "vm/loader.h"
81 #include "vm/options.h"
82 #include "vm/stringlocal.h"
83 #include "vm/tables.h"
84 #include "vm/jit/asmpart.h"
85 #include "vm/jit/patcher.h"
86
87
88 /* include builtin tables *****************************************************/
89
90 #include "vm/builtintable.inc"
91
92
93 /* builtintable_init ***********************************************************
94
95    Parse the descriptors of builtin functions and create the parsed
96    descriptors.
97
98 *******************************************************************************/
99
100 static bool builtintable_init(void)
101 {
102         descriptor_pool *descpool;
103         s4               dumpsize;
104         utf             *descriptor;
105         s4               entries_internal;
106         s4               entries_automatic;
107         s4               i;
108
109         /* mark start of dump memory area */
110
111         dumpsize = dump_size();
112
113         /* create a new descriptor pool */
114
115         descpool = descriptor_pool_new(class_java_lang_Object);
116
117         /* add some entries we need */
118
119         if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
120                 return false;
121
122         if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
123                 return false;
124
125         /* calculate table entries statically */
126
127         entries_internal =
128                 sizeof(builtintable_internal) / sizeof(builtintable_entry);
129
130         entries_automatic =
131                 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
132                 - 1; /* last filler entry (comment see builtintable.inc) */
133
134         /* first add all descriptors to the pool */
135
136         for (i = 0; i < entries_internal; i++) {
137                 /* create a utf8 string from descriptor */
138
139                 descriptor = utf_new_char(builtintable_internal[i].descriptor);
140
141                 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
142                         /* release dump area */
143
144                         dump_release(dumpsize);
145
146                         return false;
147                 }
148         }
149
150         for (i = 0; i < entries_automatic; i++) {
151                 /* create a utf8 string from descriptor */
152
153                 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
154
155                 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
156                         /* release dump area */
157
158                         dump_release(dumpsize);
159
160                         return false;
161                 }
162         }
163
164         /* create the class reference table */
165
166         (void) descriptor_pool_create_classrefs(descpool, NULL);
167
168         /* allocate space for the parsed descriptors */
169
170         descriptor_pool_alloc_parsed_descriptors(descpool);
171
172         /* now parse all descriptors */
173
174         for (i = 0; i < entries_internal; i++) {
175                 /* create a utf8 string from descriptor */
176
177                 descriptor = utf_new_char(builtintable_internal[i].descriptor);
178
179                 /* parse the descriptor, builtin is always static (no `this' pointer) */
180
181                 builtintable_internal[i].md =
182                         descriptor_pool_parse_method_descriptor(descpool, descriptor,
183                                                                                                         ACC_STATIC, NULL);
184         }
185
186         for (i = 0; i < entries_automatic; i++) {
187                 /* create a utf8 string from descriptor */
188
189                 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
190
191                 /* parse the descriptor, builtin is always static (no `this' pointer) */
192
193                 builtintable_automatic[i].md =
194                         descriptor_pool_parse_method_descriptor(descpool, descriptor,
195                                                                                                         ACC_STATIC, NULL);
196         }
197
198         /* release dump area */
199
200         dump_release(dumpsize);
201
202         return true;
203 }
204
205
206 /* builtintable_comparator *****************************************************
207
208    qsort comparator for the automatic builtin table.
209
210 *******************************************************************************/
211
212 static int builtintable_comparator(const void *a, const void *b)
213 {
214         builtintable_entry *bte1;
215         builtintable_entry *bte2;
216
217         bte1 = (builtintable_entry *) a;
218         bte2 = (builtintable_entry *) b;
219
220         return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
221 }
222
223
224 /* builtintable_sort_automatic *************************************************
225
226    Sorts the automatic builtin table.
227
228 *******************************************************************************/
229
230 static void builtintable_sort_automatic(void)
231 {
232         s4 entries;
233
234         /* calculate table size statically (`- 1' comment see builtintable.inc) */
235
236         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
237
238         qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
239                   builtintable_comparator);
240 }
241
242
243 /* builtin_init ****************************************************************
244
245    XXX
246
247 *******************************************************************************/
248
249 bool builtin_init(void)
250 {
251         /* initialize the builtin tables */
252
253         if (!builtintable_init())
254                 return false;
255
256         /* sort builtin tables */
257
258         builtintable_sort_automatic();
259
260         return true;
261 }
262
263
264 /* builtintable_get_internal ***************************************************
265
266    Finds an entry in the builtintable for internal functions and
267    returns the a pointer to the structure.
268
269 *******************************************************************************/
270
271 builtintable_entry *builtintable_get_internal(functionptr fp)
272 {
273         s4 i;
274
275         for (i = 0; builtintable_internal[i].fp != NULL; i++) {
276                 if (builtintable_internal[i].fp == fp)
277                         return &builtintable_internal[i];
278         }
279
280         return NULL;
281 }
282
283
284 /* builtintable_get_automatic **************************************************
285
286    Finds an entry in the builtintable for functions which are replaced
287    automatically and returns the a pointer to the structure.
288
289 *******************************************************************************/
290
291 builtintable_entry *builtintable_get_automatic(s4 opcode)
292 {
293         builtintable_entry *first;
294         builtintable_entry *last;
295         builtintable_entry *middle;
296         s4                  half;
297         s4                  entries;
298
299         /* calculate table size statically (`- 1' comment see builtintable.inc) */
300
301         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
302
303         first = builtintable_automatic;
304         last = builtintable_automatic + entries;
305
306         while (entries > 0) {
307                 half = entries / 2;
308                 middle = first + half;
309
310                 if (middle->opcode < opcode) {
311                         first = middle + 1;
312                         entries -= half + 1;
313                 } else
314                         entries = half;
315         }
316
317         return (first != last ? first : NULL);
318 }
319
320
321 /*****************************************************************************
322                                                                 TYPE CHECKS
323 *****************************************************************************/
324
325
326
327 /*************** internal function: builtin_isanysubclass *********************
328
329         Checks a subclass relation between two classes. Implemented interfaces
330         are interpreted as super classes.
331         Return value:  1 ... sub is subclass of super
332                                    0 ... otherwise
333                                         
334 *****************************************************************************/                                  
335 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
336 {
337         s4 res;
338         castinfo classvalues;
339
340         if (sub == super)
341                 return 1;
342
343         if (super->flags & ACC_INTERFACE) {
344                 res = (sub->vftbl->interfacetablelength > super->index) &&
345                         (sub->vftbl->interfacetable[-super->index] != NULL);
346
347         } else {
348                 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
349
350                 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
351                         (u4) classvalues.super_diffval;
352         }
353
354         return res;
355 }
356
357
358 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
359 {
360         s4 res;
361         s4 base;
362         castinfo classvalues;
363
364         if (sub == super)
365                 return 1;
366
367         asm_getclassvalues_atomic(super, sub, &classvalues);
368
369         if ((base = classvalues.super_baseval) <= 0) {
370                 /* super is an interface */
371                 res = (sub->interfacetablelength > -base) &&
372                         (sub->interfacetable[base] != NULL);
373         } else {
374             res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
375                         <= (u4) classvalues.super_diffval;
376         }
377
378         return res;
379 }
380
381
382 /****************** function: builtin_instanceof *****************************
383
384         Checks if an object is an instance of some given class (or subclass of
385         that class). If class is an interface, checks if the interface is
386         implemented.
387         Return value:  1 ... obj is an instance of class or implements the interface
388                                    0 ... otherwise or if obj == NULL
389                          
390 *****************************************************************************/
391
392 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
393 {
394         if (!obj)
395                 return 0;
396
397         return builtin_isanysubclass(obj->vftbl->class, class);
398 }
399
400
401
402 /**************** function: builtin_checkcast *******************************
403
404         The same as builtin_instanceof except that 1 is returned when
405         obj == NULL
406                           
407 ****************************************************************************/
408
409 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
410 {
411         if (obj == NULL)
412                 return 1;
413
414         if (builtin_isanysubclass(obj->vftbl->class, class))
415                 return 1;
416
417         return 0;
418 }
419
420
421 /* builtin_descriptorscompatible ***********************************************
422
423    Checks if two array type descriptors are assignment compatible
424
425    Return value: 1 ... target = desc is possible
426                  0 ... otherwise
427                         
428 *******************************************************************************/
429
430 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
431                                                                                 arraydescriptor *target)
432 {
433         if (desc == target)
434                 return 1;
435
436         if (desc->arraytype != target->arraytype)
437                 return 0;
438
439         if (desc->arraytype != ARRAYTYPE_OBJECT)
440                 return 1;
441         
442         /* {both arrays are arrays of references} */
443
444         if (desc->dimension == target->dimension) {
445                 /* an array which contains elements of interface types is
446            allowed to be casted to Object (JOWENN)*/
447
448                 if ((desc->elementvftbl->baseval < 0) &&
449                         (target->elementvftbl->baseval == 1))
450                         return 1;
451
452                 return builtin_isanysubclass_vftbl(desc->elementvftbl,
453                                                                                    target->elementvftbl);
454         }
455
456         if (desc->dimension < target->dimension)
457                 return 0;
458
459         /* {desc has higher dimension than target} */
460
461         return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
462                                                                            target->elementvftbl);
463 }
464
465
466 /* builtin_arraycheckcast ******************************************************
467
468    Checks if an object is really a subtype of the requested array
469    type.  The object has to be an array to begin with. For simple
470    arrays (int, short, double, etc.) the types have to match exactly.
471    For arrays of objects, the type of elements in the array has to be
472    a subtype (or the same type) of the requested element type. For
473    arrays of arrays (which in turn can again be arrays of arrays), the
474    types at the lowest level have to satisfy the corresponding sub
475    class relation.
476         
477 *******************************************************************************/
478
479 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
480 {
481         arraydescriptor *desc;
482
483         if (!o)
484                 return 1;
485
486         if ((desc = o->vftbl->arraydesc) == NULL)
487                 return 0;
488  
489         return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
490 }
491
492
493 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
494 {
495         if (!o)
496                 return 0;
497
498         return builtin_arraycheckcast(o, targetclass);
499 }
500
501
502 /************************** exception functions *******************************
503
504 ******************************************************************************/
505
506 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
507 {
508     java_lang_Throwable *t;
509         char                *logtext;
510         s4                   logtextlen;
511         s4                   dumpsize;
512
513         if (opt_verbose) {
514                 t = (java_lang_Throwable *) xptr;
515
516                 /* calculate message length */
517
518                 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
519
520                 if (t) {
521                         logtextlen +=
522                                 utf_strlen(xptr->vftbl->class->name) +
523                                 strlen(": ") +
524                                 javastring_strlen((java_objectheader *) t->detailMessage);
525
526                 } else
527                         logtextlen += strlen("(nil)");
528
529                 /* allocate memory */
530
531                 dumpsize = dump_size();
532
533                 logtext = DMNEW(char, logtextlen);
534
535                 strcpy(logtext, "Builtin exception thrown: ");
536
537                 if (t) {
538                         utf_sprint_classname(logtext + strlen(logtext),
539                                                                  xptr->vftbl->class->name);
540
541                         if (t->detailMessage) {
542                                 char *buf;
543
544                                 buf = javastring_tochar((java_objectheader *) t->detailMessage);
545                                 strcat(logtext, ": ");
546                                 strcat(logtext, buf);
547                                 MFREE(buf, char, strlen(buf));
548                         }
549
550                 } else {
551                         strcat(logtext, "(nil)");
552                 }
553
554                 log_text(logtext);
555
556                 /* release memory */
557
558                 dump_release(dumpsize);
559         }
560
561         *exceptionptr = xptr;
562
563         return xptr;
564 }
565
566
567
568 /* builtin_canstore ************************************************************
569
570    Checks, if an object can be stored in an array.
571
572    Return value: 1 ... possible
573                  0 ... otherwise
574
575 *******************************************************************************/
576
577 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
578 {
579         arraydescriptor *desc;
580         arraydescriptor *valuedesc;
581         vftbl_t         *componentvftbl;
582         vftbl_t         *valuevftbl;
583         s4               base;
584         castinfo         classvalues;
585         
586         if (!o)
587                 return 1;
588
589         /* The following is guaranteed (by verifier checks):
590          *
591          *     *) a->...vftbl->arraydesc != NULL
592          *     *) a->...vftbl->arraydesc->componentvftbl != NULL
593          *     *) o->vftbl is not an interface vftbl
594          */
595         
596         desc           = oa->header.objheader.vftbl->arraydesc;
597         componentvftbl = desc->componentvftbl;
598         valuevftbl     = o->vftbl;
599
600         if ((desc->dimension - 1) == 0) {
601                 s4 res;
602
603                 /* {a is a one-dimensional array} */
604                 /* {a is an array of references} */
605                 
606                 if (valuevftbl == componentvftbl)
607                         return 1;
608
609                 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
610
611                 if ((base = classvalues.super_baseval) <= 0)
612                         /* an array of interface references */
613                         return (valuevftbl->interfacetablelength > -base &&
614                                         valuevftbl->interfacetable[base] != NULL);
615                 
616                 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
617                            <= (unsigned) classvalues.super_diffval);
618
619                 return res;
620         }
621
622         /* {a has dimension > 1} */
623         /* {componentvftbl->arraydesc != NULL} */
624
625         /* check if o is an array */
626
627         if ((valuedesc = valuevftbl->arraydesc) == NULL)
628                 return 0;
629
630         /* {o is an array} */
631
632         return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
633 }
634
635
636 /* This is an optimized version where a is guaranteed to be one-dimensional */
637 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
638 {
639         arraydescriptor *desc;
640         vftbl_t *elementvftbl;
641         vftbl_t *valuevftbl;
642         s4 res;
643         int base;
644         castinfo classvalues;
645         
646         if (!o) return 1;
647
648         /* The following is guaranteed (by verifier checks):
649          *
650          *     *) a->...vftbl->arraydesc != NULL
651          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
652          *     *) a->...vftbl->arraydesc->dimension == 1
653          *     *) o->vftbl is not an interface vftbl
654          */
655
656         desc = a->header.objheader.vftbl->arraydesc;
657     elementvftbl = desc->elementvftbl;
658         valuevftbl = o->vftbl;
659
660         /* {a is a one-dimensional array} */
661         
662         if (valuevftbl == elementvftbl)
663                 return 1;
664
665         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
666
667         if ((base = classvalues.super_baseval) <= 0)
668                 /* an array of interface references */
669                 return (valuevftbl->interfacetablelength > -base &&
670                                 valuevftbl->interfacetable[base] != NULL);
671
672         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
673                 <= (unsigned) classvalues.super_diffval;
674
675         return res;
676 }
677
678
679 /* This is an optimized version where a is guaranteed to be a
680  * one-dimensional array of a class type */
681 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
682 {
683         vftbl_t *elementvftbl;
684         vftbl_t *valuevftbl;
685         s4 res;
686         castinfo classvalues;
687         
688         if (!o) return 1;
689
690         /* The following is guaranteed (by verifier checks):
691          *
692          *     *) a->...vftbl->arraydesc != NULL
693          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
694          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
695          *     *) a->...vftbl->arraydesc->dimension == 1
696          *     *) o->vftbl is not an interface vftbl
697          */
698
699     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
700         valuevftbl = o->vftbl;
701
702         /* {a is a one-dimensional array} */
703         
704         if (valuevftbl == elementvftbl)
705                 return 1;
706
707         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
708
709         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
710                 <= (unsigned) classvalues.super_diffval;
711
712         return res;
713 }
714
715
716 /* builtin_new *****************************************************************
717
718    Creates a new instance of class c on the heap.
719
720    Return value: pointer to the object or NULL if no memory is
721    available
722                         
723 *******************************************************************************/
724
725 java_objectheader *builtin_new(classinfo *c)
726 {
727         java_objectheader *o;
728
729         /* is the class loaded */
730
731         assert(c->loaded);
732
733         /* check if we can instantiate this class */
734
735         if (c->flags & ACC_ABSTRACT) {
736                 *exceptionptr =
737                         new_exception_utfmessage(string_java_lang_InstantiationError,
738                                                                          c->name);
739                 return NULL;
740         }
741
742         /* is the class linked */
743         if (!c->linked)
744                 if (!link_class(c))
745                         return NULL;
746
747         if (!c->initialized) {
748                 if (initverbose)
749                         log_message_class("Initialize class (from builtin_new): ", c);
750
751                 if (!initialize_class(c))
752                         return NULL;
753         }
754
755         o = heap_allocate(c->instancesize, true, c->finalizer);
756
757         if (!o)
758                 return NULL;
759
760         o->vftbl = c->vftbl;
761
762 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
763         initObjectLock(o);
764 #endif
765
766         return o;
767 }
768
769
770 /* builtin_newarray ************************************************************
771
772    Creates an array with the given vftbl on the heap. This function
773    takes as class argument an array class.
774
775    Return value: pointer to the array or NULL if no memory is available
776
777 *******************************************************************************/
778
779 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
780 {
781         arraydescriptor  *desc;
782         s4                dataoffset;
783         s4                componentsize;
784         s4                actualsize;
785         java_arrayheader *a;
786
787         desc          = arrayclass->vftbl->arraydesc;
788         dataoffset    = desc->dataoffset;
789         componentsize = desc->componentsize;
790
791         if (size < 0) {
792                 *exceptionptr = new_negativearraysizeexception();
793                 return NULL;
794         }
795
796         actualsize = dataoffset + size * componentsize;
797
798         if (((u4) actualsize) < ((u4) size)) { /* overflow */
799                 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
800                 return NULL;
801         }
802
803         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
804
805         if (!a)
806                 return NULL;
807
808         a->objheader.vftbl = arrayclass->vftbl;
809
810 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
811         initObjectLock(&a->objheader);
812 #endif
813
814         a->size = size;
815
816         return a;
817 }
818
819
820 /* builtin_anewarray ***********************************************************
821
822    Creates an array of references to the given class type on the heap.
823
824    Return value: pointer to the array or NULL if no memory is
825    available
826
827 *******************************************************************************/
828
829 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
830 {
831         classinfo *arrayclass;
832         
833         /* is class loaded */
834
835         assert(componentclass->loaded);
836
837         /* is class linked */
838
839         if (!componentclass->linked)
840                 if (!link_class(componentclass))
841                         return NULL;
842
843         arrayclass = class_array_of(componentclass, true);
844
845         if (!arrayclass)
846                 return NULL;
847
848         return (java_objectarray *) builtin_newarray(size, arrayclass);
849 }
850
851
852 /* builtin_newarray_boolean ****************************************************
853
854    Creates an array of bytes on the heap. The array is designated as
855    an array of booleans (important for casts)
856         
857    Return value: pointer to the array or NULL if no memory is
858    available
859
860 *******************************************************************************/
861
862 java_booleanarray *builtin_newarray_boolean(s4 size)
863 {
864         return (java_booleanarray *)
865                 builtin_newarray(size,
866                                                  primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
867 }
868
869
870 /* builtin_newarray_byte *******************************************************
871
872    Creates an array of 8 bit Integers on the heap.
873
874    Return value: pointer to the array or NULL if no memory is
875    available
876
877 *******************************************************************************/
878
879 java_bytearray *builtin_newarray_byte(s4 size)
880 {
881         return (java_bytearray *)
882                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
883 }
884
885
886 /* builtin_newarray_char *******************************************************
887
888    Creates an array of characters on the heap.
889
890    Return value: pointer to the array or NULL if no memory is
891    available
892
893 *******************************************************************************/
894
895 java_chararray *builtin_newarray_char(s4 size)
896 {
897         return (java_chararray *)
898                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
899 }
900
901
902 /* builtin_newarray_short ******************************************************
903
904    Creates an array of 16 bit Integers on the heap.
905
906    Return value: pointer to the array or NULL if no memory is
907    available
908
909 *******************************************************************************/
910
911 java_shortarray *builtin_newarray_short(s4 size)
912 {
913         return (java_shortarray *)
914                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
915 }
916
917
918 /* builtin_newarray_int ********************************************************
919
920    Creates an array of 32 bit Integers on the heap.
921
922    Return value: pointer to the array or NULL if no memory is
923    available
924
925 *******************************************************************************/
926
927 java_intarray *builtin_newarray_int(s4 size)
928 {
929         return (java_intarray *)
930                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
931 }
932
933
934 /* builtin_newarray_long *******************************************************
935
936    Creates an array of 64 bit Integers on the heap.
937
938    Return value: pointer to the array or NULL if no memory is
939    available
940
941 *******************************************************************************/
942
943 java_longarray *builtin_newarray_long(s4 size)
944 {
945         return (java_longarray *)
946                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
947 }
948
949
950 /* builtin_newarray_float ******************************************************
951
952    Creates an array of 32 bit IEEE floats on the heap.
953
954    Return value: pointer to the array or NULL if no memory is
955    available
956
957 *******************************************************************************/
958
959 java_floatarray *builtin_newarray_float(s4 size)
960 {
961         return (java_floatarray *)
962                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
963 }
964
965
966 /* builtin_newarray_double *****************************************************
967
968    Creates an array of 64 bit IEEE floats on the heap.
969
970    Return value: pointer to the array or NULL if no memory is
971    available
972
973 *******************************************************************************/
974
975 java_doublearray *builtin_newarray_double(s4 size)
976 {
977         return (java_doublearray *)
978                 builtin_newarray(size,
979                                                  primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
980 }
981
982
983 /* builtin_multianewarray_intern ***********************************************
984
985    Creates a multi-dimensional array on the heap. The dimensions are
986    passed in an array of longs.
987
988    Arguments:
989        n............number of dimensions to create
990        arrayvftbl...vftbl of the array class
991        dims.........array containing the size of each dimension to create
992
993    Return value: pointer to the array or NULL if no memory is
994    available
995
996 ******************************************************************************/
997
998 static java_arrayheader *builtin_multianewarray_intern(int n,
999                                                                                                            classinfo *arrayclass,
1000                                                                                                            long *dims)
1001 {
1002         s4                size;
1003         java_arrayheader *a;
1004         classinfo        *componentclass;
1005         s4                i;
1006
1007         /* create this dimension */
1008
1009         size = (s4) dims[0];
1010         a = builtin_newarray(size, arrayclass);
1011
1012         if (!a)
1013                 return NULL;
1014
1015         /* if this is the last dimension return */
1016
1017         if (!--n)
1018                 return a;
1019
1020         /* get the class of the components to create */
1021
1022         componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1023
1024         /* The verifier guarantees that the dimension count is in the range. */
1025
1026         /* create the component arrays */
1027
1028         for (i = 0; i < size; i++) {
1029                 java_arrayheader *ea =
1030 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1031                         /* we save an s4 to a s8 slot, 8-byte aligned */
1032
1033                         builtin_multianewarray_intern(n, componentclass, dims + 2);
1034 #else
1035                         builtin_multianewarray_intern(n, componentclass, dims + 1);
1036 #endif
1037
1038                 if (!ea)
1039                         return NULL;
1040                 
1041                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1042         }
1043
1044         return a;
1045 }
1046
1047
1048 /* builtin_multianewarray ******************************************************
1049
1050    Wrapper for builtin_multianewarray_intern which checks all
1051    dimensions before we start allocating.
1052
1053 ******************************************************************************/
1054
1055 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1056                                                                                  long *dims)
1057 {
1058         s4 i;
1059         s4 size;
1060
1061         /* check all dimensions before doing anything */
1062
1063         for (i = 0; i < n; i++) {
1064 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1065                 /* we save an s4 to a s8 slot, 8-byte aligned */
1066                 size = (s4) dims[i * 2];
1067 #else
1068                 size = (s4) dims[i];
1069 #endif
1070
1071                 if (size < 0) {
1072                         *exceptionptr = new_negativearraysizeexception();
1073                         return NULL;
1074                 }
1075         }
1076
1077         /* now call the real function */
1078
1079         return builtin_multianewarray_intern(n, arrayclass, dims);
1080 }
1081
1082
1083 /*****************************************************************************
1084                                           METHOD LOGGING
1085
1086         Various functions for printing a message at method entry or exit (for
1087         debugging)
1088         
1089 *****************************************************************************/
1090
1091 s4 methodindent = 0;
1092
1093 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1094                                                                                    methodinfo *m,
1095                                                                                    void *pos,
1096                                                                                    s4 indent)
1097 {
1098         char *logtext;
1099         s4    logtextlen;
1100         s4    dumpsize;
1101
1102         if (opt_verbose || runverbose || opt_verboseexception) {
1103                 /* when running with verbosecall we remove one indent level */
1104
1105                 if (runverbose && indent)
1106                         methodindent--;
1107
1108                 /* calculate message length */
1109
1110                 if (xptr) {
1111                         logtextlen =
1112                                 strlen("Exception ") +
1113                                 utf_strlen(xptr->vftbl->class->name);
1114
1115                 } else {
1116                         logtextlen = strlen("Some Throwable");
1117                 }
1118
1119                 logtextlen += strlen(" thrown in ");
1120
1121                 if (m) {
1122                         logtextlen +=
1123                                 utf_strlen(m->class->name) +
1124                                 strlen(".") +
1125                                 utf_strlen(m->name) +
1126                                 utf_strlen(m->descriptor) +
1127                                 strlen("(NOSYNC,NATIVE");
1128
1129 #if SIZEOF_VOID_P == 8
1130                         logtextlen +=
1131                                 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1132 #else
1133                         logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1134 #endif
1135
1136                         if (m->class->sourcefile == NULL)
1137                                 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1138                         else
1139                                 logtextlen += utf_strlen(m->class->sourcefile);
1140
1141                         logtextlen += strlen(":65536)");
1142
1143                 } else
1144                         logtextlen += strlen("call_java_method");
1145
1146                 logtextlen += strlen("0");
1147
1148                 /* allocate memory */
1149
1150                 dumpsize = dump_size();
1151
1152                 logtext = DMNEW(char, logtextlen);
1153
1154                 if (xptr) {
1155                         strcpy(logtext, "Exception ");
1156                         utf_strcat_classname(logtext, xptr->vftbl->class->name);
1157
1158                 } else {
1159                         strcpy(logtext, "Some Throwable");
1160                 }
1161
1162                 strcat(logtext, " thrown in ");
1163
1164                 if (m) {
1165                         utf_strcat_classname(logtext, m->class->name);
1166                         strcat(logtext, ".");
1167                         utf_strcat(logtext, m->name);
1168                         utf_strcat(logtext, m->descriptor);
1169
1170                         if (m->flags & ACC_SYNCHRONIZED)
1171                                 strcat(logtext, "(SYNC");
1172                         else
1173                                 strcat(logtext, "(NOSYNC");
1174
1175                         if (m->flags & ACC_NATIVE) {
1176                                 strcat(logtext, ",NATIVE");
1177
1178 #if SIZEOF_VOID_P == 8
1179                                 sprintf(logtext + strlen(logtext),
1180                                                 ")(0x%016lx) at position 0x%016lx",
1181                                                 (ptrint) m->entrypoint, (ptrint) pos);
1182 #else
1183                                 sprintf(logtext + strlen(logtext),
1184                                                 ")(0x%08x) at position 0x%08x",
1185                                                 (ptrint) m->entrypoint, (ptrint) pos);
1186 #endif
1187
1188                         } else {
1189 #if SIZEOF_VOID_P == 8
1190                                 sprintf(logtext + strlen(logtext),
1191                                                 ")(0x%016lx) at position 0x%016lx (",
1192                                                 (ptrint) m->entrypoint, (ptrint) pos);
1193 #else
1194                                 sprintf(logtext + strlen(logtext),
1195                                                 ")(0x%08x) at position 0x%08x (",
1196                                                 (ptrint) m->entrypoint, (ptrint) pos);
1197 #endif
1198
1199                                 if (m->class->sourcefile == NULL)
1200                                         strcat(logtext, "<NO CLASSFILE INFORMATION>");
1201                                 else
1202                                         utf_strcat(logtext, m->class->sourcefile);
1203
1204                                 sprintf(logtext + strlen(logtext), ":%d)", 0);
1205                         }
1206
1207                 } else
1208                         strcat(logtext, "call_java_method");
1209
1210                 log_text(logtext);
1211
1212                 /* release memory */
1213
1214                 dump_release(dumpsize);
1215
1216                 /* print stacktrace for exception */
1217
1218                 if (opt_verboseexception) {
1219                         java_lang_Throwable   *t;
1220                         java_lang_VMThrowable *vmt;
1221                         java_lang_Throwable   *cause;
1222                         utf                   *u;
1223                         stackTraceBuffer      *stb;
1224
1225                         t = (java_lang_Throwable *) xptr;
1226                         cause = t->cause;
1227
1228                         /* print the root exception */
1229
1230                         utf_display_classname(t->header.vftbl->class->name);
1231
1232                         if (t->detailMessage) {
1233                                 u = javastring_toutf(t->detailMessage, false);
1234
1235                                 printf(": ");
1236                                 utf_display(u);
1237                         }
1238
1239                         putc('\n', stdout);
1240
1241                         /* print the cause if available */
1242
1243                         if (cause && (cause != t)) {
1244                                 printf("Caused by: ");
1245                                 utf_display_classname(cause->header.vftbl->class->name);
1246
1247                                 if (cause->detailMessage) {
1248                                         u = javastring_toutf(cause->detailMessage, false);
1249
1250                                         printf(": ");
1251                                         utf_display(u);
1252                                 }
1253
1254                                 putc('\n', stdout);
1255                         }
1256
1257                         /* now print the stacktrace */
1258
1259                         vmt = t->vmState;
1260                         stb = (stackTraceBuffer *) vmt->vmData;
1261
1262                         stacktrace_print_trace(stb);
1263                 }
1264         }
1265
1266         return xptr;
1267 }
1268
1269
1270 /* builtin_trace_args **********************************************************
1271
1272    XXX
1273
1274 *******************************************************************************/
1275
1276 #ifdef TRACE_ARGS_NUM
1277 void builtin_trace_args(s8 a0, s8 a1,
1278 #if TRACE_ARGS_NUM >= 4
1279                                                 s8 a2, s8 a3,
1280 #endif /* TRACE_ARGS_NUM >= 4 */
1281 #if TRACE_ARGS_NUM >= 6
1282                                                 s8 a4, s8 a5,
1283 #endif /* TRACE_ARGS_NUM >= 6 */
1284 #if TRACE_ARGS_NUM == 8
1285                                                 s8 a6, s8 a7,
1286 #endif /* TRACE_ARGS_NUM == 8 */
1287                                                 methodinfo *m)
1288 {
1289         methoddesc *md;
1290         char       *logtext;
1291         s4          logtextlen;
1292         s4          dumpsize;
1293         s4          i;
1294         s4          pos;
1295
1296         md = m->parseddesc;
1297
1298         /* calculate message length */
1299
1300         logtextlen =
1301                 6 + methodindent + strlen("called: ") +
1302                 utf_strlen(m->class->name) +
1303                 strlen(".") +
1304                 utf_strlen(m->name) +
1305                 utf_strlen(m->descriptor) +
1306                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1307
1308         /* add maximal argument length */
1309
1310         logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1311
1312         /* allocate memory */
1313
1314         dumpsize = dump_size();
1315
1316         logtext = DMNEW(char, logtextlen);
1317
1318         sprintf(logtext,"-%d-",methodindent);
1319         pos = strlen(logtext);
1320
1321         for (i = 0; i < methodindent; i++)
1322                 logtext[pos++] = '\t';
1323
1324         strcpy(logtext + pos, "called: ");
1325
1326         utf_strcat_classname(logtext, m->class->name);
1327         strcat(logtext, ".");
1328         utf_strcat(logtext, m->name);
1329         utf_strcat(logtext, m->descriptor);
1330
1331         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1332         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1333         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1334         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1335         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1336         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1337         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1338         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1339         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1340         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1341         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1342
1343         strcat(logtext, "(");
1344
1345         /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso)                */
1346         /* Only Arguments in integer Registers are passed correctly here */
1347         /* long longs spilled on Stack have an wrong offset of +4        */
1348         /* So preliminary Bugfix: Only pass 3 params at once to sprintf  */
1349         /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8                 */
1350         switch (md->paramcount) {
1351         case 0:
1352                 break;
1353
1354 #if SIZEOF_VOID_P == 4
1355         case 1:
1356                 sprintf(logtext + strlen(logtext),
1357                                 "0x%llx",
1358                                 a0);
1359                 break;
1360
1361         case 2:
1362                 sprintf(logtext + strlen(logtext),
1363                                 "0x%llx, 0x%llx",
1364                                 a0, a1);
1365                 break;
1366
1367 #if TRACE_ARGS_NUM >= 4
1368         case 3:
1369                 sprintf(logtext + strlen(logtext),
1370                                 "0x%llx, 0x%llx, 0x%llx",
1371                                 a0, a1, a2);
1372                 break;
1373
1374         case 4:
1375                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1376                                 , a0, a1, a2);
1377                 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1378
1379                 break;
1380 #endif /* TRACE_ARGS_NUM >= 4 */
1381
1382 #if TRACE_ARGS_NUM >= 6
1383         case 5:
1384                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1385                                 , a0, a1, a2);
1386                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1387                 break;
1388
1389
1390         case 6:
1391                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1392                                 , a0, a1, a2);
1393                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1394                                 , a3, a4, a5);
1395                 break;
1396 #endif /* TRACE_ARGS_NUM >= 6 */
1397
1398 #if TRACE_ARGS_NUM == 8
1399         case 7:
1400                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1401                                 , a0, a1, a2);
1402                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1403                                 , a3, a4, a5);
1404                 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1405                 break;
1406
1407         case 8:
1408                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1409                                 , a0, a1, a2);
1410                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1411                                 , a3, a4, a5);
1412                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1413                 break;
1414 #endif /* TRACE_ARGS_NUM == 8 */
1415
1416         default:
1417 #if TRACE_ARGS_NUM == 2
1418                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1419
1420 #elif TRACE_ARGS_NUM == 4
1421                 sprintf(logtext + strlen(logtext),
1422                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1423                                 a0, a1, a2, a3, md->paramcount - 4);
1424
1425 #elif TRACE_ARGS_NUM == 6
1426                 sprintf(logtext + strlen(logtext),
1427                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1428                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1429
1430 #elif TRACE_ARGS_NUM == 8
1431                 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1432                                 , a0, a1, a2);
1433                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1434                                 , a3, a4, a5);
1435                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1436                                 , a6, a7, md->paramcount - 8);
1437 #endif
1438                 break;
1439
1440 #else /* SIZEOF_VOID_P == 4 */
1441
1442         case 1:
1443                 sprintf(logtext + strlen(logtext),
1444                                 "0x%lx",
1445                                 a0);
1446                 break;
1447
1448         case 2:
1449                 sprintf(logtext + strlen(logtext),
1450                                 "0x%lx, 0x%lx",
1451                                 a0, a1);
1452                 break;
1453
1454         case 3:
1455                 sprintf(logtext + strlen(logtext),
1456                                 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1457                 break;
1458
1459         case 4:
1460                 sprintf(logtext + strlen(logtext),
1461                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1462                                 a0, a1, a2, a3);
1463                 break;
1464
1465 #if TRACE_ARGS_NUM >= 6
1466         case 5:
1467                 sprintf(logtext + strlen(logtext),
1468                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1469                                 a0, a1, a2, a3, a4);
1470                 break;
1471
1472         case 6:
1473                 sprintf(logtext + strlen(logtext),
1474                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1475                                 a0, a1, a2, a3, a4, a5);
1476                 break;
1477 #endif /* TRACE_ARGS_NUM >= 6 */
1478
1479 #if TRACE_ARGS_NUM == 8
1480         case 7:
1481                 sprintf(logtext + strlen(logtext),
1482                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1483                                 a0, a1, a2, a3, a4, a5, a6);
1484                 break;
1485
1486         case 8:
1487                 sprintf(logtext + strlen(logtext),
1488                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1489                                 a0, a1, a2, a3, a4, a5, a6, a7);
1490                 break;
1491 #endif /* TRACE_ARGS_NUM == 8 */
1492
1493         default:
1494 #if TRACE_ARGS_NUM == 4
1495                 sprintf(logtext + strlen(logtext),
1496                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1497                                 a0, a1, a2, a3, md->paramcount - 4);
1498
1499 #elif TRACE_ARGS_NUM == 6
1500                 sprintf(logtext + strlen(logtext),
1501                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1502                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1503
1504 #elif TRACE_ARGS_NUM == 8
1505                 sprintf(logtext + strlen(logtext),
1506                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1507                                 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1508 #endif
1509                 break;
1510 #endif /* SIZEOF_VOID_P == 4 */
1511         }
1512
1513         strcat(logtext, ")");
1514
1515         log_text(logtext);
1516
1517         /* release memory */
1518
1519         dump_release(dumpsize);
1520
1521         methodindent++;
1522 }
1523 #endif
1524
1525
1526 /* builtin_displaymethodstop ***************************************************
1527
1528    XXX
1529
1530 *******************************************************************************/
1531
1532 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1533 {
1534         methoddesc *md;
1535         char       *logtext;
1536         s4          logtextlen;
1537         s4          dumpsize;
1538         s4          i;
1539         s4          pos;
1540         imm_union   imu;
1541
1542         md = m->parseddesc;
1543
1544         /* calculate message length */
1545
1546         logtextlen =
1547                 6 + methodindent + strlen("finished: ") +
1548                 utf_strlen(m->class->name) +
1549                 strlen(".") +
1550                 utf_strlen(m->name) +
1551                 utf_strlen(m->descriptor) +
1552                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1553
1554         /* add maximal argument length */
1555
1556         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1557
1558         /* allocate memory */
1559
1560         dumpsize = dump_size();
1561
1562         logtext = DMNEW(char, logtextlen);
1563
1564         /* outdent the log message */
1565
1566         if (methodindent)
1567                 methodindent--;
1568         else
1569                 log_text("WARNING: unmatched methodindent--");
1570
1571         /* generate the message */
1572
1573         sprintf(logtext,"-%d-",methodindent);
1574         pos = strlen(logtext);
1575
1576         for (i = 0; i < methodindent; i++)
1577                 logtext[pos++] = '\t';
1578
1579         strcpy(logtext + pos, "finished: ");
1580         utf_strcat_classname(logtext, m->class->name);
1581         strcat(logtext, ".");
1582         utf_strcat(logtext, m->name);
1583         utf_strcat(logtext, m->descriptor);
1584
1585         switch (md->returntype.type) {
1586         case TYPE_INT:
1587                 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1588                 break;
1589
1590         case TYPE_LNG:
1591 #if SIZEOF_VOID_P == 4
1592                 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1593 #else
1594                 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1595 #endif
1596                 break;
1597
1598         case TYPE_ADR:
1599                 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1600                 break;
1601
1602         case TYPE_FLT:
1603                 imu.f = f;
1604                 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1605                 break;
1606
1607         case TYPE_DBL:
1608                 imu.d = d;
1609 #if SIZEOF_VOID_P == 4
1610                 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1611 #else
1612                 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1613 #endif
1614                 break;
1615         }
1616
1617         log_text(logtext);
1618
1619         /* release memory */
1620
1621         dump_release(dumpsize);
1622 }
1623
1624
1625 /****************************************************************************
1626                          SYNCHRONIZATION FUNCTIONS
1627 *****************************************************************************/
1628
1629 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1630 /*
1631  * Lock the mutex of an object.
1632  */
1633 void internal_lock_mutex_for_object(java_objectheader *object)
1634 {
1635         mutexHashEntry *entry;
1636         int hashValue;
1637
1638         assert(object != 0);
1639
1640         hashValue = MUTEX_HASH_VALUE(object);
1641         entry = &mutexHashTable[hashValue];
1642
1643         if (entry->object != 0) {
1644                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1645                         entry->object = 0;
1646                         entry->mutex.holder = 0;
1647                         entry->mutex.count = 0;
1648                         entry->mutex.muxWaiters = 0;
1649
1650                 } else {
1651                         while (entry->next != 0 && entry->object != object)
1652                                 entry = entry->next;
1653
1654                         if (entry->object != object) {
1655                                 entry->next = firstFreeOverflowEntry;
1656                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1657
1658                                 entry = entry->next;
1659                                 entry->object = 0;
1660                                 entry->next = 0;
1661                                 assert(entry->conditionCount == 0);
1662                         }
1663                 }
1664
1665         } else {
1666                 entry->mutex.holder = 0;
1667                 entry->mutex.count = 0;
1668                 entry->mutex.muxWaiters = 0;
1669         }
1670
1671         if (entry->object == 0)
1672                 entry->object = object;
1673         
1674         internal_lock_mutex(&entry->mutex);
1675 }
1676 #endif
1677
1678
1679 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1680 /*
1681  * Unlocks the mutex of an object.
1682  */
1683 void internal_unlock_mutex_for_object (java_objectheader *object)
1684 {
1685         int hashValue;
1686         mutexHashEntry *entry;
1687
1688         hashValue = MUTEX_HASH_VALUE(object);
1689         entry = &mutexHashTable[hashValue];
1690
1691         if (entry->object == object) {
1692                 internal_unlock_mutex(&entry->mutex);
1693
1694         } else {
1695                 while (entry->next != 0 && entry->next->object != object)
1696                         entry = entry->next;
1697
1698                 assert(entry->next != 0);
1699
1700                 internal_unlock_mutex(&entry->next->mutex);
1701
1702                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1703                         mutexHashEntry *unlinked = entry->next;
1704
1705                         entry->next = unlinked->next;
1706                         unlinked->next = firstFreeOverflowEntry;
1707                         firstFreeOverflowEntry = unlinked;
1708                 }
1709         }
1710 }
1711 #endif
1712
1713
1714 #if defined(USE_THREADS)
1715 void builtin_monitorenter(java_objectheader *o)
1716 {
1717 #if !defined(NATIVE_THREADS)
1718         int hashValue;
1719
1720         ++blockInts;
1721
1722         hashValue = MUTEX_HASH_VALUE(o);
1723         if (mutexHashTable[hashValue].object == o 
1724                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1725                 ++mutexHashTable[hashValue].mutex.count;
1726         else
1727                 internal_lock_mutex_for_object(o);
1728
1729         --blockInts;
1730 #else
1731         monitorEnter((threadobject *) THREADOBJECT, o);
1732 #endif
1733 }
1734 #endif
1735
1736
1737 #if defined(USE_THREADS)
1738 /*
1739  * Locks the class object - needed for static synchronized methods.
1740  * The use_class_as_object call is needed in order to circumvent a
1741  * possible deadlock with builtin_monitorenter called by another
1742  * thread calling use_class_as_object.
1743  */
1744 void builtin_staticmonitorenter(classinfo *c)
1745 {
1746         use_class_as_object(c);
1747         builtin_monitorenter(&c->header);
1748 }
1749 #endif
1750
1751
1752 #if defined(USE_THREADS)
1753 void builtin_monitorexit(java_objectheader *o)
1754 {
1755 #if !defined(NATIVE_THREADS)
1756         int hashValue;
1757
1758         ++blockInts;
1759
1760         hashValue = MUTEX_HASH_VALUE(o);
1761         if (mutexHashTable[hashValue].object == o) {
1762                 if (mutexHashTable[hashValue].mutex.count == 1
1763                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1764                         internal_unlock_mutex_for_object(o);
1765                 else
1766                         --mutexHashTable[hashValue].mutex.count;
1767
1768         } else
1769                 internal_unlock_mutex_for_object(o);
1770
1771         --blockInts;
1772 #else
1773         monitorExit((threadobject *) THREADOBJECT, o);
1774 #endif
1775 }
1776 #endif
1777
1778
1779 /*****************************************************************************
1780                           MISCELLANEOUS HELPER FUNCTIONS
1781 *****************************************************************************/
1782
1783
1784
1785 /*********** Functions for integer divisions *****************************
1786  
1787         On some systems (eg. DEC ALPHA), integer division is not supported by the
1788         CPU. These helper functions implement the missing functionality.
1789
1790 ******************************************************************************/
1791
1792 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1793 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1794
1795
1796 /************** Functions for long arithmetics *******************************
1797
1798         On systems where 64 bit Integers are not supported by the CPU, these
1799         functions are needed.
1800
1801 ******************************************************************************/
1802
1803 s8 builtin_ladd(s8 a, s8 b)
1804 {
1805         s8 c;
1806
1807 #if U8_AVAILABLE
1808         c = a + b; 
1809 #else
1810         c = builtin_i2l(0);
1811 #endif
1812
1813         return c;
1814 }
1815
1816 s8 builtin_lsub(s8 a, s8 b) 
1817 {
1818         s8 c;
1819
1820 #if U8_AVAILABLE
1821         c = a - b; 
1822 #else
1823         c = builtin_i2l(0);
1824 #endif
1825
1826         return c;
1827 }
1828
1829 s8 builtin_lmul(s8 a, s8 b) 
1830 {
1831         s8 c;
1832
1833 #if U8_AVAILABLE
1834         c = a * b; 
1835 #else
1836         c = builtin_i2l(0);
1837 #endif
1838
1839         return c;
1840 }
1841
1842 s8 builtin_ldiv(s8 a, s8 b) 
1843 {
1844         s8 c;
1845
1846 #if U8_AVAILABLE
1847         c = a / b; 
1848 #else
1849         c = builtin_i2l(0);
1850 #endif
1851
1852         return c;
1853 }
1854
1855 s8 builtin_lrem(s8 a, s8 b) 
1856 {
1857         s8 c;
1858
1859 #if U8_AVAILABLE
1860         c = a % b; 
1861 #else
1862         c = builtin_i2l(0);
1863 #endif
1864
1865         return c;
1866 }
1867
1868 s8 builtin_lshl(s8 a, s4 b) 
1869 {
1870         s8 c;
1871
1872 #if U8_AVAILABLE
1873         c = a << (b & 63);
1874 #else
1875         c = builtin_i2l(0);
1876 #endif
1877
1878         return c;
1879 }
1880
1881 s8 builtin_lshr(s8 a, s4 b) 
1882 {
1883         s8 c;
1884
1885 #if U8_AVAILABLE
1886         c = a >> (b & 63);
1887 #else
1888         c = builtin_i2l(0);
1889 #endif
1890
1891         return c;
1892 }
1893
1894 s8 builtin_lushr(s8 a, s4 b) 
1895 {
1896         s8 c;
1897
1898 #if U8_AVAILABLE
1899         c = ((u8) a) >> (b & 63);
1900 #else
1901         c = builtin_i2l(0);
1902 #endif
1903
1904         return c;
1905 }
1906
1907 s8 builtin_land(s8 a, s8 b) 
1908 {
1909         s8 c;
1910
1911 #if U8_AVAILABLE
1912         c = a & b; 
1913 #else
1914         c = builtin_i2l(0);
1915 #endif
1916
1917         return c;
1918 }
1919
1920 s8 builtin_lor(s8 a, s8 b) 
1921 {
1922         s8 c;
1923
1924 #if U8_AVAILABLE
1925         c = a | b; 
1926 #else
1927         c = builtin_i2l(0);
1928 #endif
1929
1930         return c;
1931 }
1932
1933 s8 builtin_lxor(s8 a, s8 b) 
1934 {
1935         s8 c;
1936
1937 #if U8_AVAILABLE
1938         c = a ^ b; 
1939 #else
1940         c = builtin_i2l(0);
1941 #endif
1942
1943         return c;
1944 }
1945
1946 s8 builtin_lneg(s8 a) 
1947 {
1948         s8 c;
1949
1950 #if U8_AVAILABLE
1951         c = -a;
1952 #else
1953         c = builtin_i2l(0);
1954 #endif
1955
1956         return c;
1957 }
1958
1959 s4 builtin_lcmp(s8 a, s8 b) 
1960
1961 #if U8_AVAILABLE
1962         if (a < b) return -1;
1963         if (a > b) return 1;
1964         return 0;
1965 #else
1966         return 0;
1967 #endif
1968 }
1969
1970
1971
1972
1973
1974 /*********** Functions for floating point operations *************************/
1975
1976 /* used to convert FLT_xxx defines into float values */
1977
1978 static inline float intBitsToFloat(s4 i)
1979 {
1980         imm_union imb;
1981
1982         imb.i = i;
1983         return imb.f;
1984 }
1985
1986
1987 /* used to convert DBL_xxx defines into double values */
1988
1989 static inline float longBitsToDouble(s8 l)
1990 {
1991         imm_union imb;
1992
1993         imb.l = l;
1994         return imb.d;
1995 }
1996
1997
1998 float builtin_fadd(float a, float b)
1999 {
2000         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2001         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2002         if (finitef(a)) {
2003                 if (finitef(b))
2004                         return a + b;
2005                 else
2006                         return b;
2007         }
2008         else {
2009                 if (finitef(b))
2010                         return a;
2011                 else {
2012                         if (copysignf(1.0, a) == copysignf(1.0, b))
2013                                 return a;
2014                         else
2015                                 return intBitsToFloat(FLT_NAN);
2016                 }
2017         }
2018 }
2019
2020
2021 float builtin_fsub(float a, float b)
2022 {
2023         return builtin_fadd(a, builtin_fneg(b));
2024 }
2025
2026
2027 float builtin_fmul(float a, float b)
2028 {
2029         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2030         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2031         if (finitef(a)) {
2032                 if (finitef(b)) return a * b;
2033                 else {
2034                         if (a == 0) return intBitsToFloat(FLT_NAN);
2035                         else return copysignf(b, copysignf(1.0, b)*a);
2036                 }
2037         }
2038         else {
2039                 if (finitef(b)) {
2040                         if (b == 0) return intBitsToFloat(FLT_NAN);
2041                         else return copysignf(a, copysignf(1.0, a)*b);
2042                 }
2043                 else {
2044                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2045                 }
2046         }
2047 }
2048
2049
2050 /* builtin_ddiv ****************************************************************
2051
2052    Implementation as described in VM Spec.
2053
2054 *******************************************************************************/
2055
2056 float builtin_fdiv(float a, float b)
2057 {
2058         if (finitef(a)) {
2059                 if (finitef(b)) {
2060                         /* If neither value1' nor value2' is NaN, the sign of the result */
2061                         /* is positive if both values have the same sign, negative if the */
2062                         /* values have different signs. */
2063
2064                         return a / b;
2065
2066                 } else {
2067                         if (isnanf(b)) {
2068                                 /* If either value1' or value2' is NaN, the result is NaN. */
2069
2070                                 return intBitsToFloat(FLT_NAN);
2071
2072                         } else {
2073                                 /* Division of a finite value by an infinity results in a */
2074                                 /* signed zero, with the sign-producing rule just given. */
2075
2076                                 /* is sign equal? */
2077
2078                                 if (copysignf(1.0, a) == copysignf(1.0, b))
2079                                         return 0.0;
2080                                 else
2081                                         return -0.0;
2082                         }
2083                 }
2084
2085         } else {
2086                 if (isnanf(a)) {
2087                         /* If either value1' or value2' is NaN, the result is NaN. */
2088
2089                         return intBitsToFloat(FLT_NAN);
2090
2091                 } else if (finitef(b)) {
2092                         /* Division of an infinity by a finite value results in a signed */
2093                         /* infinity, with the sign-producing rule just given. */
2094
2095                         /* is sign equal? */
2096
2097                         if (copysignf(1.0, a) == copysignf(1.0, b))
2098                                 return intBitsToFloat(FLT_POSINF);
2099                         else
2100                                 return intBitsToFloat(FLT_NEGINF);
2101
2102                 } else {
2103                         /* Division of an infinity by an infinity results in NaN. */
2104
2105                         return intBitsToFloat(FLT_NAN);
2106                 }
2107         }
2108 }
2109
2110
2111 float builtin_frem(float a, float b)
2112 {
2113         return fmodf(a, b);
2114 }
2115
2116
2117 float builtin_fneg(float a)
2118 {
2119         if (isnanf(a)) return a;
2120         else {
2121                 if (finitef(a)) return -a;
2122                 else return copysignf(a, -copysignf(1.0, a));
2123         }
2124 }
2125
2126
2127 s4 builtin_fcmpl(float a, float b)
2128 {
2129         if (isnanf(a)) return -1;
2130         if (isnanf(b)) return -1;
2131         if (!finitef(a) || !finitef(b)) {
2132                 a = finitef(a) ? 0 : copysignf(1.0,     a);
2133                 b = finitef(b) ? 0 : copysignf(1.0, b);
2134         }
2135         if (a > b) return 1;
2136         if (a == b) return 0;
2137         return -1;
2138 }
2139
2140
2141 s4 builtin_fcmpg(float a, float b)
2142 {
2143         if (isnanf(a)) return 1;
2144         if (isnanf(b)) return 1;
2145         if (!finitef(a) || !finitef(b)) {
2146                 a = finitef(a) ? 0 : copysignf(1.0, a);
2147                 b = finitef(b) ? 0 : copysignf(1.0, b);
2148         }
2149         if (a > b) return 1;
2150         if (a == b) return 0;
2151         return -1;
2152 }
2153
2154
2155
2156 /************************* Functions for doubles ****************************/
2157
2158 double builtin_dadd(double a, double b)
2159 {
2160         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2161         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2162         if (finite(a)) {
2163                 if (finite(b)) return a + b;
2164                 else return b;
2165         }
2166         else {
2167                 if (finite(b)) return a;
2168                 else {
2169                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
2170                         else return longBitsToDouble(DBL_NAN);
2171                 }
2172         }
2173 }
2174
2175
2176 double builtin_dsub(double a, double b)
2177 {
2178         return builtin_dadd(a, builtin_dneg(b));
2179 }
2180
2181
2182 double builtin_dmul(double a, double b)
2183 {
2184         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2185         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2186         if (finite(a)) {
2187                 if (finite(b)) return a * b;
2188                 else {
2189                         if (a == 0) return longBitsToDouble(DBL_NAN);
2190                         else return copysign(b, copysign(1.0, b) * a);
2191                 }
2192         }
2193         else {
2194                 if (finite(b)) {
2195                         if (b == 0) return longBitsToDouble(DBL_NAN);
2196                         else return copysign(a, copysign(1.0, a) * b);
2197                 }
2198                 else {
2199                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2200                 }
2201         }
2202 }
2203
2204
2205 /* builtin_ddiv ****************************************************************
2206
2207    Implementation as described in VM Spec.
2208
2209 *******************************************************************************/
2210
2211 double builtin_ddiv(double a, double b)
2212 {
2213         if (finite(a)) {
2214                 if (finite(b)) {
2215                         /* If neither value1' nor value2' is NaN, the sign of the result */
2216                         /* is positive if both values have the same sign, negative if the */
2217                         /* values have different signs. */
2218
2219                         return a / b;
2220
2221                 } else {
2222                         if (isnan(b)) {
2223                                 /* If either value1' or value2' is NaN, the result is NaN. */
2224
2225                                 return longBitsToDouble(DBL_NAN);
2226
2227                         } else {
2228                                 /* Division of a finite value by an infinity results in a */
2229                                 /* signed zero, with the sign-producing rule just given. */
2230
2231                                 /* is sign equal? */
2232
2233                                 if (copysign(1.0, a) == copysign(1.0, b))
2234                                         return 0.0;
2235                                 else
2236                                         return -0.0;
2237                         }
2238                 }
2239
2240         } else {
2241                 if (isnan(a)) {
2242                         /* If either value1' or value2' is NaN, the result is NaN. */
2243
2244                         return longBitsToDouble(DBL_NAN);
2245
2246                 } else if (finite(b)) {
2247                         /* Division of an infinity by a finite value results in a signed */
2248                         /* infinity, with the sign-producing rule just given. */
2249
2250                         /* is sign equal? */
2251
2252                         if (copysign(1.0, a) == copysign(1.0, b))
2253                                 return longBitsToDouble(DBL_POSINF);
2254                         else
2255                                 return longBitsToDouble(DBL_NEGINF);
2256
2257                 } else {
2258                         /* Division of an infinity by an infinity results in NaN. */
2259
2260                         return longBitsToDouble(DBL_NAN);
2261                 }
2262         }
2263 }
2264
2265
2266 double builtin_drem(double a, double b)
2267 {
2268         return fmod(a, b);
2269 }
2270
2271 /* builtin_dneg ****************************************************************
2272
2273    Implemented as described in VM Spec.
2274
2275 *******************************************************************************/
2276
2277 double builtin_dneg(double a)
2278 {
2279         if (isnan(a)) {
2280                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2281                 /* sign). */
2282
2283                 return a;
2284
2285         } else {
2286                 if (finite(a)) {
2287                         /* If the operand is a zero, the result is the zero of opposite */
2288                         /* sign. */
2289
2290                         return -a;
2291
2292                 } else {
2293                         /* If the operand is an infinity, the result is the infinity of */
2294                         /* opposite sign. */
2295
2296                         return copysign(a, -copysign(1.0, a));
2297                 }
2298         }
2299 }
2300
2301
2302 s4 builtin_dcmpl(double a, double b)
2303 {
2304         if (isnan(a)) return -1;
2305         if (isnan(b)) return -1;
2306         if (!finite(a) || !finite(b)) {
2307                 a = finite(a) ? 0 : copysign(1.0, a);
2308                 b = finite(b) ? 0 : copysign(1.0, b);
2309         }
2310         if (a > b) return 1;
2311         if (a == b) return 0;
2312         return -1;
2313 }
2314
2315
2316 s4 builtin_dcmpg(double a, double b)
2317 {
2318         if (isnan(a)) return 1;
2319         if (isnan(b)) return 1;
2320         if (!finite(a) || !finite(b)) {
2321                 a = finite(a) ? 0 : copysign(1.0, a);
2322                 b = finite(b) ? 0 : copysign(1.0, b);
2323         }
2324         if (a > b) return 1;
2325         if (a == b) return 0;
2326         return -1;
2327 }
2328
2329
2330 /*********************** Conversion operations ****************************/
2331
2332 s8 builtin_i2l(s4 i)
2333 {
2334 #if U8_AVAILABLE
2335         return i;
2336 #else
2337         s8 v;
2338         v.high = 0;
2339         v.low = i;
2340         return v;
2341 #endif
2342 }
2343
2344
2345 float builtin_i2f(s4 a)
2346 {
2347         float f = (float) a;
2348         return f;
2349 }
2350
2351
2352 double builtin_i2d(s4 a)
2353 {
2354         double d = (double) a;
2355         return d;
2356 }
2357
2358
2359 s4 builtin_l2i(s8 l)
2360 {
2361 #if U8_AVAILABLE
2362         return (s4) l;
2363 #else
2364         return l.low;
2365 #endif
2366 }
2367
2368
2369 float builtin_l2f(s8 a)
2370 {
2371 #if U8_AVAILABLE
2372         float f = (float) a;
2373         return f;
2374 #else
2375         return 0.0;
2376 #endif
2377 }
2378
2379
2380 double builtin_l2d(s8 a)
2381 {
2382 #if U8_AVAILABLE
2383         double d = (double) a;
2384         return d;
2385 #else
2386         return 0.0;
2387 #endif
2388 }
2389
2390
2391 s4 builtin_f2i(float a) 
2392 {
2393         s4 i;
2394
2395         i = builtin_d2i((double) a);
2396
2397         return i;
2398
2399         /*      float f;
2400         
2401                 if (isnanf(a))
2402                 return 0;
2403                 if (finitef(a)) {
2404                 if (a > 2147483647)
2405                 return 2147483647;
2406                 if (a < (-2147483648))
2407                 return (-2147483648);
2408                 return (s4) a;
2409                 }
2410                 f = copysignf((float) 1.0, a);
2411                 if (f > 0)
2412                 return 2147483647;
2413                 return (-2147483648); */
2414 }
2415
2416
2417 s8 builtin_f2l(float a)
2418 {
2419         s8 l;
2420
2421         l = builtin_d2l((double) a);
2422
2423         return l;
2424
2425         /*      float f;
2426         
2427                 if (finitef(a)) {
2428                 if (a > 9223372036854775807L)
2429                 return 9223372036854775807L;
2430                 if (a < (-9223372036854775808L))
2431                 return (-9223372036854775808L);
2432                 return (s8) a;
2433                 }
2434                 if (isnanf(a))
2435                 return 0;
2436                 f = copysignf((float) 1.0, a);
2437                 if (f > 0)
2438                 return 9223372036854775807L;
2439                 return (-9223372036854775808L); */
2440 }
2441
2442
2443 double builtin_f2d(float a)
2444 {
2445         if (finitef(a)) return (double) a;
2446         else {
2447                 if (isnanf(a))
2448                         return longBitsToDouble(DBL_NAN);
2449                 else
2450                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2451         }
2452 }
2453
2454
2455 s4 builtin_d2i(double a) 
2456
2457         double d;
2458         
2459         if (finite(a)) {
2460                 if (a >= 2147483647)
2461                         return 2147483647;
2462                 if (a <= (-2147483647-1))
2463                         return (-2147483647-1);
2464                 return (s4) a;
2465         }
2466         if (isnan(a))
2467                 return 0;
2468         d = copysign(1.0, a);
2469         if (d > 0)
2470                 return 2147483647;
2471         return (-2147483647-1);
2472 }
2473
2474
2475 s8 builtin_d2l(double a)
2476 {
2477         double d;
2478         
2479         if (finite(a)) {
2480                 if (a >= 9223372036854775807LL)
2481                         return 9223372036854775807LL;
2482                 if (a <= (-9223372036854775807LL-1))
2483                         return (-9223372036854775807LL-1);
2484                 return (s8) a;
2485         }
2486         if (isnan(a))
2487                 return 0;
2488         d = copysign(1.0, a);
2489         if (d > 0)
2490                 return 9223372036854775807LL;
2491         return (-9223372036854775807LL-1);
2492 }
2493
2494
2495 float builtin_d2f(double a)
2496 {
2497         if (finite(a))
2498                 return (float) a;
2499         else {
2500                 if (isnan(a))
2501                         return intBitsToFloat(FLT_NAN);
2502                 else
2503                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2504         }
2505 }
2506
2507
2508 /* builtin_clone_array *********************************************************
2509
2510    Wrapper function for cloning arrays.
2511
2512 *******************************************************************************/
2513
2514 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2515 {
2516         java_arrayheader    *ah;
2517         java_lang_Cloneable *c;
2518
2519         c = (java_lang_Cloneable *) o;
2520
2521         ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2522
2523         return ah;
2524 }
2525
2526
2527 /* builtin_asm_get_exceptionptrptr *********************************************
2528
2529    this is a wrapper for calls from asmpart
2530
2531 *******************************************************************************/
2532
2533 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2534 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2535 {
2536         return builtin_get_exceptionptrptr();
2537 }
2538 #endif
2539
2540
2541 /*
2542  * These are local overrides for various environment variables in Emacs.
2543  * Please do not remove this and leave it at the end of the file, where
2544  * Emacs will automagically detect them.
2545  * ---------------------------------------------------------------------
2546  * Local variables:
2547  * mode: c
2548  * indent-tabs-mode: t
2549  * c-basic-offset: 4
2550  * tab-width: 4
2551  * End:
2552  */