* builtin_new: Check for java.lang.InstantiationError.
[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 3582 2005-11-05 19:51:18Z 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 *a, java_objectheader *o)
578 {
579         arraydescriptor *desc;
580         arraydescriptor *valuedesc;
581         vftbl_t *componentvftbl;
582         vftbl_t *valuevftbl;
583         int 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 = a->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         if ((valuedesc = valuevftbl->arraydesc) == NULL)
627                 return 0;
628         /* {o is an array} */
629
630         return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
631 }
632
633
634 /* This is an optimized version where a is guaranteed to be one-dimensional */
635 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
636 {
637         arraydescriptor *desc;
638         vftbl_t *elementvftbl;
639         vftbl_t *valuevftbl;
640         s4 res;
641         int base;
642         castinfo classvalues;
643         
644         if (!o) return 1;
645
646         /* The following is guaranteed (by verifier checks):
647          *
648          *     *) a->...vftbl->arraydesc != NULL
649          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
650          *     *) a->...vftbl->arraydesc->dimension == 1
651          *     *) o->vftbl is not an interface vftbl
652          */
653
654         desc = a->header.objheader.vftbl->arraydesc;
655     elementvftbl = desc->elementvftbl;
656         valuevftbl = o->vftbl;
657
658         /* {a is a one-dimensional array} */
659         
660         if (valuevftbl == elementvftbl)
661                 return 1;
662
663         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
664
665         if ((base = classvalues.super_baseval) <= 0)
666                 /* an array of interface references */
667                 return (valuevftbl->interfacetablelength > -base &&
668                                 valuevftbl->interfacetable[base] != NULL);
669
670         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
671                 <= (unsigned) classvalues.super_diffval;
672
673         return res;
674 }
675
676
677 /* This is an optimized version where a is guaranteed to be a
678  * one-dimensional array of a class type */
679 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
680 {
681         vftbl_t *elementvftbl;
682         vftbl_t *valuevftbl;
683         s4 res;
684         castinfo classvalues;
685         
686         if (!o) return 1;
687
688         /* The following is guaranteed (by verifier checks):
689          *
690          *     *) a->...vftbl->arraydesc != NULL
691          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
692          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
693          *     *) a->...vftbl->arraydesc->dimension == 1
694          *     *) o->vftbl is not an interface vftbl
695          */
696
697     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
698         valuevftbl = o->vftbl;
699
700         /* {a is a one-dimensional array} */
701         
702         if (valuevftbl == elementvftbl)
703                 return 1;
704
705         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
706
707         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
708                 <= (unsigned) classvalues.super_diffval;
709
710         return res;
711 }
712
713
714 /* builtin_new *****************************************************************
715
716    Creates a new instance of class c on the heap.
717
718    Return value: pointer to the object or NULL if no memory is
719    available
720                         
721 *******************************************************************************/
722
723 java_objectheader *builtin_new(classinfo *c)
724 {
725         java_objectheader *o;
726
727         /* is the class loaded */
728
729         assert(c->loaded);
730
731         /* check if we can instantiate this class */
732
733         if (c->flags & ACC_ABSTRACT) {
734                 *exceptionptr =
735                         new_exception_utfmessage(string_java_lang_InstantiationError,
736                                                                          c->name);
737                 return NULL;
738         }
739
740         /* is the class linked */
741         if (!c->linked)
742                 if (!link_class(c))
743                         return NULL;
744
745         if (!c->initialized) {
746                 if (initverbose)
747                         log_message_class("Initialize class (from builtin_new): ", c);
748
749                 if (!initialize_class(c))
750                         return NULL;
751         }
752
753         o = heap_allocate(c->instancesize, true, c->finalizer);
754
755         if (!o)
756                 return NULL;
757
758         o->vftbl = c->vftbl;
759
760 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
761         initObjectLock(o);
762 #endif
763
764         return o;
765 }
766
767
768 /* builtin_newarray ************************************************************
769
770    Creates an array with the given vftbl on the heap. This function
771    takes as class argument an array class.
772
773    Return value: pointer to the array or NULL if no memory is available
774
775 *******************************************************************************/
776
777 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
778 {
779         arraydescriptor  *desc;
780         s4                dataoffset;
781         s4                componentsize;
782         s4                actualsize;
783         java_arrayheader *a;
784
785         desc          = arrayclass->vftbl->arraydesc;
786         dataoffset    = desc->dataoffset;
787         componentsize = desc->componentsize;
788
789         if (size < 0) {
790                 *exceptionptr = new_negativearraysizeexception();
791                 return NULL;
792         }
793
794         actualsize = dataoffset + size * componentsize;
795
796         if (((u4) actualsize) < ((u4) size)) { /* overflow */
797                 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
798                 return NULL;
799         }
800
801         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
802
803         if (!a)
804                 return NULL;
805
806         a->objheader.vftbl = arrayclass->vftbl;
807
808 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
809         initObjectLock(&a->objheader);
810 #endif
811
812         a->size = size;
813
814         return a;
815 }
816
817
818 /* builtin_anewarray ***********************************************************
819
820    Creates an array of references to the given class type on the heap.
821
822    Return value: pointer to the array or NULL if no memory is
823    available
824
825 *******************************************************************************/
826
827 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
828 {
829         classinfo *arrayclass;
830         
831         /* is class loaded */
832
833         assert(componentclass->loaded);
834
835         /* is class linked */
836
837         if (!componentclass->linked)
838                 if (!link_class(componentclass))
839                         return NULL;
840
841         arrayclass = class_array_of(componentclass, true);
842
843         if (!arrayclass)
844                 return NULL;
845
846         return (java_objectarray *) builtin_newarray(size, arrayclass);
847 }
848
849
850 /* builtin_newarray_boolean ****************************************************
851
852    Creates an array of bytes on the heap. The array is designated as
853    an array of booleans (important for casts)
854         
855    Return value: pointer to the array or NULL if no memory is
856    available
857
858 *******************************************************************************/
859
860 java_booleanarray *builtin_newarray_boolean(s4 size)
861 {
862         return (java_booleanarray *)
863                 builtin_newarray(size,
864                                                  primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
865 }
866
867
868 /* builtin_newarray_byte *******************************************************
869
870    Creates an array of 8 bit Integers on the heap.
871
872    Return value: pointer to the array or NULL if no memory is
873    available
874
875 *******************************************************************************/
876
877 java_bytearray *builtin_newarray_byte(s4 size)
878 {
879         return (java_bytearray *)
880                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
881 }
882
883
884 /* builtin_newarray_char *******************************************************
885
886    Creates an array of characters on the heap.
887
888    Return value: pointer to the array or NULL if no memory is
889    available
890
891 *******************************************************************************/
892
893 java_chararray *builtin_newarray_char(s4 size)
894 {
895         return (java_chararray *)
896                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
897 }
898
899
900 /* builtin_newarray_short ******************************************************
901
902    Creates an array of 16 bit Integers on the heap.
903
904    Return value: pointer to the array or NULL if no memory is
905    available
906
907 *******************************************************************************/
908
909 java_shortarray *builtin_newarray_short(s4 size)
910 {
911         return (java_shortarray *)
912                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
913 }
914
915
916 /* builtin_newarray_int ********************************************************
917
918    Creates an array of 32 bit Integers on the heap.
919
920    Return value: pointer to the array or NULL if no memory is
921    available
922
923 *******************************************************************************/
924
925 java_intarray *builtin_newarray_int(s4 size)
926 {
927         return (java_intarray *)
928                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
929 }
930
931
932 /* builtin_newarray_long *******************************************************
933
934    Creates an array of 64 bit Integers on the heap.
935
936    Return value: pointer to the array or NULL if no memory is
937    available
938
939 *******************************************************************************/
940
941 java_longarray *builtin_newarray_long(s4 size)
942 {
943         return (java_longarray *)
944                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
945 }
946
947
948 /* builtin_newarray_float ******************************************************
949
950    Creates an array of 32 bit IEEE floats on the heap.
951
952    Return value: pointer to the array or NULL if no memory is
953    available
954
955 *******************************************************************************/
956
957 java_floatarray *builtin_newarray_float(s4 size)
958 {
959         return (java_floatarray *)
960                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
961 }
962
963
964 /* builtin_newarray_double *****************************************************
965
966    Creates an array of 64 bit IEEE floats on the heap.
967
968    Return value: pointer to the array or NULL if no memory is
969    available
970
971 *******************************************************************************/
972
973 java_doublearray *builtin_newarray_double(s4 size)
974 {
975         return (java_doublearray *)
976                 builtin_newarray(size,
977                                                  primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
978 }
979
980
981 /* builtin_multianewarray_intern ***********************************************
982
983    Creates a multi-dimensional array on the heap. The dimensions are
984    passed in an array of longs.
985
986    Arguments:
987        n............number of dimensions to create
988        arrayvftbl...vftbl of the array class
989        dims.........array containing the size of each dimension to create
990
991    Return value: pointer to the array or NULL if no memory is
992    available
993
994 ******************************************************************************/
995
996 static java_arrayheader *builtin_multianewarray_intern(int n,
997                                                                                                            classinfo *arrayclass,
998                                                                                                            long *dims)
999 {
1000         s4                size;
1001         java_arrayheader *a;
1002         classinfo        *componentclass;
1003         s4                i;
1004
1005         /* create this dimension */
1006
1007         size = (s4) dims[0];
1008         a = builtin_newarray(size, arrayclass);
1009
1010         if (!a)
1011                 return NULL;
1012
1013         /* if this is the last dimension return */
1014
1015         if (!--n)
1016                 return a;
1017
1018         /* get the class of the components to create */
1019
1020         componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1021
1022         /* The verifier guarantees that the dimension count is in the range. */
1023
1024         /* create the component arrays */
1025
1026         for (i = 0; i < size; i++) {
1027                 java_arrayheader *ea =
1028 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1029                         /* we save an s4 to a s8 slot, 8-byte aligned */
1030
1031                         builtin_multianewarray_intern(n, componentclass, dims + 2);
1032 #else
1033                         builtin_multianewarray_intern(n, componentclass, dims + 1);
1034 #endif
1035
1036                 if (!ea)
1037                         return NULL;
1038                 
1039                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1040         }
1041
1042         return a;
1043 }
1044
1045
1046 /* builtin_multianewarray ******************************************************
1047
1048    Wrapper for builtin_multianewarray_intern which checks all
1049    dimensions before we start allocating.
1050
1051 ******************************************************************************/
1052
1053 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1054                                                                                  long *dims)
1055 {
1056         s4 i;
1057         s4 size;
1058
1059         /* check all dimensions before doing anything */
1060
1061         for (i = 0; i < n; i++) {
1062 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1063                 /* we save an s4 to a s8 slot, 8-byte aligned */
1064                 size = (s4) dims[i * 2];
1065 #else
1066                 size = (s4) dims[i];
1067 #endif
1068
1069                 if (size < 0) {
1070                         *exceptionptr = new_negativearraysizeexception();
1071                         return NULL;
1072                 }
1073         }
1074
1075         /* now call the real function */
1076
1077         return builtin_multianewarray_intern(n, arrayclass, dims);
1078 }
1079
1080
1081 /*****************************************************************************
1082                                           METHOD LOGGING
1083
1084         Various functions for printing a message at method entry or exit (for
1085         debugging)
1086         
1087 *****************************************************************************/
1088
1089 s4 methodindent = 0;
1090
1091 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1092                                                                                    methodinfo *m,
1093                                                                                    void *pos,
1094                                                                                    s4 indent)
1095 {
1096         char *logtext;
1097         s4    logtextlen;
1098         s4    dumpsize;
1099
1100         if (opt_verbose || runverbose || opt_verboseexception) {
1101                 /* when running with verbosecall we remove one indent level */
1102
1103                 if (runverbose && indent)
1104                         methodindent--;
1105
1106                 /* calculate message length */
1107
1108                 if (xptr) {
1109                         logtextlen =
1110                                 strlen("Exception ") +
1111                                 utf_strlen(xptr->vftbl->class->name);
1112
1113                 } else {
1114                         logtextlen = strlen("Some Throwable");
1115                 }
1116
1117                 logtextlen += strlen(" thrown in ");
1118
1119                 if (m) {
1120                         logtextlen +=
1121                                 utf_strlen(m->class->name) +
1122                                 strlen(".") +
1123                                 utf_strlen(m->name) +
1124                                 utf_strlen(m->descriptor) +
1125                                 strlen("(NOSYNC,NATIVE");
1126
1127 #if SIZEOF_VOID_P == 8
1128                         logtextlen +=
1129                                 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1130 #else
1131                         logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1132 #endif
1133
1134                         if (m->class->sourcefile == NULL)
1135                                 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1136                         else
1137                                 logtextlen += utf_strlen(m->class->sourcefile);
1138
1139                         logtextlen += strlen(":65536)");
1140
1141                 } else
1142                         logtextlen += strlen("call_java_method");
1143
1144                 logtextlen += strlen("0");
1145
1146                 /* allocate memory */
1147
1148                 dumpsize = dump_size();
1149
1150                 logtext = DMNEW(char, logtextlen);
1151
1152                 if (xptr) {
1153                         strcpy(logtext, "Exception ");
1154                         utf_strcat_classname(logtext, xptr->vftbl->class->name);
1155
1156                 } else {
1157                         strcpy(logtext, "Some Throwable");
1158                 }
1159
1160                 strcat(logtext, " thrown in ");
1161
1162                 if (m) {
1163                         utf_strcat_classname(logtext, m->class->name);
1164                         strcat(logtext, ".");
1165                         utf_strcat(logtext, m->name);
1166                         utf_strcat(logtext, m->descriptor);
1167
1168                         if (m->flags & ACC_SYNCHRONIZED)
1169                                 strcat(logtext, "(SYNC");
1170                         else
1171                                 strcat(logtext, "(NOSYNC");
1172
1173                         if (m->flags & ACC_NATIVE) {
1174                                 strcat(logtext, ",NATIVE");
1175
1176 #if SIZEOF_VOID_P == 8
1177                                 sprintf(logtext + strlen(logtext),
1178                                                 ")(0x%016lx) at position 0x%016lx",
1179                                                 (ptrint) m->entrypoint, (ptrint) pos);
1180 #else
1181                                 sprintf(logtext + strlen(logtext),
1182                                                 ")(0x%08x) at position 0x%08x",
1183                                                 (ptrint) m->entrypoint, (ptrint) pos);
1184 #endif
1185
1186                         } else {
1187 #if SIZEOF_VOID_P == 8
1188                                 sprintf(logtext + strlen(logtext),
1189                                                 ")(0x%016lx) at position 0x%016lx (",
1190                                                 (ptrint) m->entrypoint, (ptrint) pos);
1191 #else
1192                                 sprintf(logtext + strlen(logtext),
1193                                                 ")(0x%08x) at position 0x%08x (",
1194                                                 (ptrint) m->entrypoint, (ptrint) pos);
1195 #endif
1196
1197                                 if (m->class->sourcefile == NULL)
1198                                         strcat(logtext, "<NO CLASSFILE INFORMATION>");
1199                                 else
1200                                         utf_strcat(logtext, m->class->sourcefile);
1201
1202                                 sprintf(logtext + strlen(logtext), ":%d)", 0);
1203                         }
1204
1205                 } else
1206                         strcat(logtext, "call_java_method");
1207
1208                 log_text(logtext);
1209
1210                 /* release memory */
1211
1212                 dump_release(dumpsize);
1213
1214                 /* print stacktrace for exception */
1215
1216                 if (opt_verboseexception) {
1217                         java_lang_Throwable   *t;
1218                         java_lang_VMThrowable *vmt;
1219                         java_lang_Throwable   *cause;
1220                         utf                   *u;
1221                         stackTraceBuffer      *stb;
1222
1223                         t = (java_lang_Throwable *) xptr;
1224                         cause = t->cause;
1225
1226                         /* print the root exception */
1227
1228                         utf_display_classname(t->header.vftbl->class->name);
1229
1230                         if (t->detailMessage) {
1231                                 u = javastring_toutf(t->detailMessage, false);
1232
1233                                 printf(": ");
1234                                 utf_display(u);
1235                         }
1236
1237                         putc('\n', stdout);
1238
1239                         /* print the cause if available */
1240
1241                         if (cause && (cause != t)) {
1242                                 printf("Caused by: ");
1243                                 utf_display_classname(cause->header.vftbl->class->name);
1244
1245                                 if (cause->detailMessage) {
1246                                         u = javastring_toutf(cause->detailMessage, false);
1247
1248                                         printf(": ");
1249                                         utf_display(u);
1250                                 }
1251
1252                                 putc('\n', stdout);
1253                         }
1254
1255                         /* now print the stacktrace */
1256
1257                         vmt = t->vmState;
1258                         stb = (stackTraceBuffer *) vmt->vmData;
1259
1260                         stacktrace_print_trace(stb);
1261                 }
1262         }
1263
1264         return xptr;
1265 }
1266
1267
1268 /* builtin_trace_args **********************************************************
1269
1270    XXX
1271
1272 *******************************************************************************/
1273
1274 #ifdef TRACE_ARGS_NUM
1275 void builtin_trace_args(s8 a0, s8 a1,
1276 #if TRACE_ARGS_NUM >= 4
1277                                                 s8 a2, s8 a3,
1278 #endif /* TRACE_ARGS_NUM >= 4 */
1279 #if TRACE_ARGS_NUM >= 6
1280                                                 s8 a4, s8 a5,
1281 #endif /* TRACE_ARGS_NUM >= 6 */
1282 #if TRACE_ARGS_NUM == 8
1283                                                 s8 a6, s8 a7,
1284 #endif /* TRACE_ARGS_NUM == 8 */
1285                                                 methodinfo *m)
1286 {
1287         methoddesc *md;
1288         char       *logtext;
1289         s4          logtextlen;
1290         s4          dumpsize;
1291         s4          i;
1292         s4          pos;
1293
1294         md = m->parseddesc;
1295
1296         /* calculate message length */
1297
1298         logtextlen =
1299                 6 + methodindent + strlen("called: ") +
1300                 utf_strlen(m->class->name) +
1301                 strlen(".") +
1302                 utf_strlen(m->name) +
1303                 utf_strlen(m->descriptor) +
1304                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1305
1306         /* add maximal argument length */
1307
1308         logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1309
1310         /* allocate memory */
1311
1312         dumpsize = dump_size();
1313
1314         logtext = DMNEW(char, logtextlen);
1315
1316         sprintf(logtext,"-%d-",methodindent);
1317         pos = strlen(logtext);
1318
1319         for (i = 0; i < methodindent; i++)
1320                 logtext[pos++] = '\t';
1321
1322         strcpy(logtext + pos, "called: ");
1323
1324         utf_strcat_classname(logtext, m->class->name);
1325         strcat(logtext, ".");
1326         utf_strcat(logtext, m->name);
1327         utf_strcat(logtext, m->descriptor);
1328
1329         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1330         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1331         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1332         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1333         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1334         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1335         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1336         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1337         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1338         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1339         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1340
1341         strcat(logtext, "(");
1342
1343         /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso)                */
1344         /* Only Arguments in integer Registers are passed correctly here */
1345         /* long longs spilled on Stack have an wrong offset of +4        */
1346         /* So preliminary Bugfix: Only pass 3 params at once to sprintf  */
1347         /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8                 */
1348         switch (md->paramcount) {
1349         case 0:
1350                 break;
1351
1352 #if SIZEOF_VOID_P == 4
1353         case 1:
1354                 sprintf(logtext + strlen(logtext),
1355                                 "0x%llx",
1356                                 a0);
1357                 break;
1358
1359         case 2:
1360                 sprintf(logtext + strlen(logtext),
1361                                 "0x%llx, 0x%llx",
1362                                 a0, a1);
1363                 break;
1364
1365 #if TRACE_ARGS_NUM >= 4
1366         case 3:
1367                 sprintf(logtext + strlen(logtext),
1368                                 "0x%llx, 0x%llx, 0x%llx",
1369                                 a0, a1, a2);
1370                 break;
1371
1372         case 4:
1373                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1374                                 , a0, a1, a2);
1375                 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1376
1377                 break;
1378 #endif /* TRACE_ARGS_NUM >= 4 */
1379
1380 #if TRACE_ARGS_NUM >= 6
1381         case 5:
1382                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1383                                 , a0, a1, a2);
1384                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1385                 break;
1386
1387
1388         case 6:
1389                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1390                                 , a0, a1, a2);
1391                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1392                                 , a3, a4, a5);
1393                 break;
1394 #endif /* TRACE_ARGS_NUM >= 6 */
1395
1396 #if TRACE_ARGS_NUM == 8
1397         case 7:
1398                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1399                                 , a0, a1, a2);
1400                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1401                                 , a3, a4, a5);
1402                 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1403                 break;
1404
1405         case 8:
1406                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1407                                 , a0, a1, a2);
1408                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1409                                 , a3, a4, a5);
1410                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1411                 break;
1412 #endif /* TRACE_ARGS_NUM == 8 */
1413
1414         default:
1415 #if TRACE_ARGS_NUM == 2
1416                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1417
1418 #elif TRACE_ARGS_NUM == 4
1419                 sprintf(logtext + strlen(logtext),
1420                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1421                                 a0, a1, a2, a3, md->paramcount - 4);
1422
1423 #elif TRACE_ARGS_NUM == 6
1424                 sprintf(logtext + strlen(logtext),
1425                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1426                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1427
1428 #elif TRACE_ARGS_NUM == 8
1429                 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1430                                 , a0, a1, a2);
1431                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1432                                 , a3, a4, a5);
1433                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1434                                 , a6, a7, md->paramcount - 8);
1435 #endif
1436                 break;
1437
1438 #else /* SIZEOF_VOID_P == 4 */
1439
1440         case 1:
1441                 sprintf(logtext + strlen(logtext),
1442                                 "0x%lx",
1443                                 a0);
1444                 break;
1445
1446         case 2:
1447                 sprintf(logtext + strlen(logtext),
1448                                 "0x%lx, 0x%lx",
1449                                 a0, a1);
1450                 break;
1451
1452         case 3:
1453                 sprintf(logtext + strlen(logtext),
1454                                 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1455                 break;
1456
1457         case 4:
1458                 sprintf(logtext + strlen(logtext),
1459                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1460                                 a0, a1, a2, a3);
1461                 break;
1462
1463 #if TRACE_ARGS_NUM >= 6
1464         case 5:
1465                 sprintf(logtext + strlen(logtext),
1466                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1467                                 a0, a1, a2, a3, a4);
1468                 break;
1469
1470         case 6:
1471                 sprintf(logtext + strlen(logtext),
1472                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1473                                 a0, a1, a2, a3, a4, a5);
1474                 break;
1475 #endif /* TRACE_ARGS_NUM >= 6 */
1476
1477 #if TRACE_ARGS_NUM == 8
1478         case 7:
1479                 sprintf(logtext + strlen(logtext),
1480                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1481                                 a0, a1, a2, a3, a4, a5, a6);
1482                 break;
1483
1484         case 8:
1485                 sprintf(logtext + strlen(logtext),
1486                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1487                                 a0, a1, a2, a3, a4, a5, a6, a7);
1488                 break;
1489 #endif /* TRACE_ARGS_NUM == 8 */
1490
1491         default:
1492 #if TRACE_ARGS_NUM == 4
1493                 sprintf(logtext + strlen(logtext),
1494                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1495                                 a0, a1, a2, a3, md->paramcount - 4);
1496
1497 #elif TRACE_ARGS_NUM == 6
1498                 sprintf(logtext + strlen(logtext),
1499                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1500                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1501
1502 #elif TRACE_ARGS_NUM == 8
1503                 sprintf(logtext + strlen(logtext),
1504                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1505                                 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1506 #endif
1507                 break;
1508 #endif /* SIZEOF_VOID_P == 4 */
1509         }
1510
1511         strcat(logtext, ")");
1512
1513         log_text(logtext);
1514
1515         /* release memory */
1516
1517         dump_release(dumpsize);
1518
1519         methodindent++;
1520 }
1521 #endif
1522
1523
1524 /* builtin_displaymethodstop ***************************************************
1525
1526    XXX
1527
1528 *******************************************************************************/
1529
1530 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1531 {
1532         methoddesc *md;
1533         char       *logtext;
1534         s4          logtextlen;
1535         s4          dumpsize;
1536         s4          i;
1537         s4          pos;
1538         imm_union   imu;
1539
1540         md = m->parseddesc;
1541
1542         /* calculate message length */
1543
1544         logtextlen =
1545                 6 + methodindent + strlen("finished: ") +
1546                 utf_strlen(m->class->name) +
1547                 strlen(".") +
1548                 utf_strlen(m->name) +
1549                 utf_strlen(m->descriptor) +
1550                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1551
1552         /* add maximal argument length */
1553
1554         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1555
1556         /* allocate memory */
1557
1558         dumpsize = dump_size();
1559
1560         logtext = DMNEW(char, logtextlen);
1561
1562         /* outdent the log message */
1563
1564         if (methodindent)
1565                 methodindent--;
1566         else
1567                 log_text("WARNING: unmatched methodindent--");
1568
1569         /* generate the message */
1570
1571         sprintf(logtext,"-%d-",methodindent);
1572         pos = strlen(logtext);
1573
1574         for (i = 0; i < methodindent; i++)
1575                 logtext[pos++] = '\t';
1576
1577         strcpy(logtext + pos, "finished: ");
1578         utf_strcat_classname(logtext, m->class->name);
1579         strcat(logtext, ".");
1580         utf_strcat(logtext, m->name);
1581         utf_strcat(logtext, m->descriptor);
1582
1583         switch (md->returntype.type) {
1584         case TYPE_INT:
1585                 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1586                 break;
1587
1588         case TYPE_LNG:
1589 #if SIZEOF_VOID_P == 4
1590                 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1591 #else
1592                 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1593 #endif
1594                 break;
1595
1596         case TYPE_ADR:
1597                 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1598                 break;
1599
1600         case TYPE_FLT:
1601                 imu.f = f;
1602                 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1603                 break;
1604
1605         case TYPE_DBL:
1606                 imu.d = d;
1607 #if SIZEOF_VOID_P == 4
1608                 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1609 #else
1610                 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1611 #endif
1612                 break;
1613         }
1614
1615         log_text(logtext);
1616
1617         /* release memory */
1618
1619         dump_release(dumpsize);
1620 }
1621
1622
1623 /****************************************************************************
1624                          SYNCHRONIZATION FUNCTIONS
1625 *****************************************************************************/
1626
1627 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1628 /*
1629  * Lock the mutex of an object.
1630  */
1631 void internal_lock_mutex_for_object(java_objectheader *object)
1632 {
1633         mutexHashEntry *entry;
1634         int hashValue;
1635
1636         assert(object != 0);
1637
1638         hashValue = MUTEX_HASH_VALUE(object);
1639         entry = &mutexHashTable[hashValue];
1640
1641         if (entry->object != 0) {
1642                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1643                         entry->object = 0;
1644                         entry->mutex.holder = 0;
1645                         entry->mutex.count = 0;
1646                         entry->mutex.muxWaiters = 0;
1647
1648                 } else {
1649                         while (entry->next != 0 && entry->object != object)
1650                                 entry = entry->next;
1651
1652                         if (entry->object != object) {
1653                                 entry->next = firstFreeOverflowEntry;
1654                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1655
1656                                 entry = entry->next;
1657                                 entry->object = 0;
1658                                 entry->next = 0;
1659                                 assert(entry->conditionCount == 0);
1660                         }
1661                 }
1662
1663         } else {
1664                 entry->mutex.holder = 0;
1665                 entry->mutex.count = 0;
1666                 entry->mutex.muxWaiters = 0;
1667         }
1668
1669         if (entry->object == 0)
1670                 entry->object = object;
1671         
1672         internal_lock_mutex(&entry->mutex);
1673 }
1674 #endif
1675
1676
1677 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1678 /*
1679  * Unlocks the mutex of an object.
1680  */
1681 void internal_unlock_mutex_for_object (java_objectheader *object)
1682 {
1683         int hashValue;
1684         mutexHashEntry *entry;
1685
1686         hashValue = MUTEX_HASH_VALUE(object);
1687         entry = &mutexHashTable[hashValue];
1688
1689         if (entry->object == object) {
1690                 internal_unlock_mutex(&entry->mutex);
1691
1692         } else {
1693                 while (entry->next != 0 && entry->next->object != object)
1694                         entry = entry->next;
1695
1696                 assert(entry->next != 0);
1697
1698                 internal_unlock_mutex(&entry->next->mutex);
1699
1700                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1701                         mutexHashEntry *unlinked = entry->next;
1702
1703                         entry->next = unlinked->next;
1704                         unlinked->next = firstFreeOverflowEntry;
1705                         firstFreeOverflowEntry = unlinked;
1706                 }
1707         }
1708 }
1709 #endif
1710
1711
1712 #if defined(USE_THREADS)
1713 void builtin_monitorenter(java_objectheader *o)
1714 {
1715 #if !defined(NATIVE_THREADS)
1716         int hashValue;
1717
1718         ++blockInts;
1719
1720         hashValue = MUTEX_HASH_VALUE(o);
1721         if (mutexHashTable[hashValue].object == o 
1722                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1723                 ++mutexHashTable[hashValue].mutex.count;
1724         else
1725                 internal_lock_mutex_for_object(o);
1726
1727         --blockInts;
1728 #else
1729         monitorEnter((threadobject *) THREADOBJECT, o);
1730 #endif
1731 }
1732 #endif
1733
1734
1735 #if defined(USE_THREADS)
1736 /*
1737  * Locks the class object - needed for static synchronized methods.
1738  * The use_class_as_object call is needed in order to circumvent a
1739  * possible deadlock with builtin_monitorenter called by another
1740  * thread calling use_class_as_object.
1741  */
1742 void builtin_staticmonitorenter(classinfo *c)
1743 {
1744         use_class_as_object(c);
1745         builtin_monitorenter(&c->header);
1746 }
1747 #endif
1748
1749
1750 #if defined(USE_THREADS)
1751 void builtin_monitorexit(java_objectheader *o)
1752 {
1753 #if !defined(NATIVE_THREADS)
1754         int hashValue;
1755
1756         ++blockInts;
1757
1758         hashValue = MUTEX_HASH_VALUE(o);
1759         if (mutexHashTable[hashValue].object == o) {
1760                 if (mutexHashTable[hashValue].mutex.count == 1
1761                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1762                         internal_unlock_mutex_for_object(o);
1763                 else
1764                         --mutexHashTable[hashValue].mutex.count;
1765
1766         } else
1767                 internal_unlock_mutex_for_object(o);
1768
1769         --blockInts;
1770 #else
1771         monitorExit((threadobject *) THREADOBJECT, o);
1772 #endif
1773 }
1774 #endif
1775
1776
1777 /*****************************************************************************
1778                           MISCELLANEOUS HELPER FUNCTIONS
1779 *****************************************************************************/
1780
1781
1782
1783 /*********** Functions for integer divisions *****************************
1784  
1785         On some systems (eg. DEC ALPHA), integer division is not supported by the
1786         CPU. These helper functions implement the missing functionality.
1787
1788 ******************************************************************************/
1789
1790 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1791 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1792
1793
1794 /************** Functions for long arithmetics *******************************
1795
1796         On systems where 64 bit Integers are not supported by the CPU, these
1797         functions are needed.
1798
1799 ******************************************************************************/
1800
1801 s8 builtin_ladd(s8 a, s8 b)
1802 {
1803         s8 c;
1804
1805 #if U8_AVAILABLE
1806         c = a + b; 
1807 #else
1808         c = builtin_i2l(0);
1809 #endif
1810
1811         return c;
1812 }
1813
1814 s8 builtin_lsub(s8 a, s8 b) 
1815 {
1816         s8 c;
1817
1818 #if U8_AVAILABLE
1819         c = a - b; 
1820 #else
1821         c = builtin_i2l(0);
1822 #endif
1823
1824         return c;
1825 }
1826
1827 s8 builtin_lmul(s8 a, s8 b) 
1828 {
1829         s8 c;
1830
1831 #if U8_AVAILABLE
1832         c = a * b; 
1833 #else
1834         c = builtin_i2l(0);
1835 #endif
1836
1837         return c;
1838 }
1839
1840 s8 builtin_ldiv(s8 a, s8 b) 
1841 {
1842         s8 c;
1843
1844 #if U8_AVAILABLE
1845         c = a / b; 
1846 #else
1847         c = builtin_i2l(0);
1848 #endif
1849
1850         return c;
1851 }
1852
1853 s8 builtin_lrem(s8 a, s8 b) 
1854 {
1855         s8 c;
1856
1857 #if U8_AVAILABLE
1858         c = a % b; 
1859 #else
1860         c = builtin_i2l(0);
1861 #endif
1862
1863         return c;
1864 }
1865
1866 s8 builtin_lshl(s8 a, s4 b) 
1867 {
1868         s8 c;
1869
1870 #if U8_AVAILABLE
1871         c = a << (b & 63);
1872 #else
1873         c = builtin_i2l(0);
1874 #endif
1875
1876         return c;
1877 }
1878
1879 s8 builtin_lshr(s8 a, s4 b) 
1880 {
1881         s8 c;
1882
1883 #if U8_AVAILABLE
1884         c = a >> (b & 63);
1885 #else
1886         c = builtin_i2l(0);
1887 #endif
1888
1889         return c;
1890 }
1891
1892 s8 builtin_lushr(s8 a, s4 b) 
1893 {
1894         s8 c;
1895
1896 #if U8_AVAILABLE
1897         c = ((u8) a) >> (b & 63);
1898 #else
1899         c = builtin_i2l(0);
1900 #endif
1901
1902         return c;
1903 }
1904
1905 s8 builtin_land(s8 a, s8 b) 
1906 {
1907         s8 c;
1908
1909 #if U8_AVAILABLE
1910         c = a & b; 
1911 #else
1912         c = builtin_i2l(0);
1913 #endif
1914
1915         return c;
1916 }
1917
1918 s8 builtin_lor(s8 a, s8 b) 
1919 {
1920         s8 c;
1921
1922 #if U8_AVAILABLE
1923         c = a | b; 
1924 #else
1925         c = builtin_i2l(0);
1926 #endif
1927
1928         return c;
1929 }
1930
1931 s8 builtin_lxor(s8 a, s8 b) 
1932 {
1933         s8 c;
1934
1935 #if U8_AVAILABLE
1936         c = a ^ b; 
1937 #else
1938         c = builtin_i2l(0);
1939 #endif
1940
1941         return c;
1942 }
1943
1944 s8 builtin_lneg(s8 a) 
1945 {
1946         s8 c;
1947
1948 #if U8_AVAILABLE
1949         c = -a;
1950 #else
1951         c = builtin_i2l(0);
1952 #endif
1953
1954         return c;
1955 }
1956
1957 s4 builtin_lcmp(s8 a, s8 b) 
1958
1959 #if U8_AVAILABLE
1960         if (a < b) return -1;
1961         if (a > b) return 1;
1962         return 0;
1963 #else
1964         return 0;
1965 #endif
1966 }
1967
1968
1969
1970
1971
1972 /*********** Functions for floating point operations *************************/
1973
1974 /* used to convert FLT_xxx defines into float values */
1975
1976 static inline float intBitsToFloat(s4 i)
1977 {
1978         imm_union imb;
1979
1980         imb.i = i;
1981         return imb.f;
1982 }
1983
1984
1985 /* used to convert DBL_xxx defines into double values */
1986
1987 static inline float longBitsToDouble(s8 l)
1988 {
1989         imm_union imb;
1990
1991         imb.l = l;
1992         return imb.d;
1993 }
1994
1995
1996 float builtin_fadd(float a, float b)
1997 {
1998         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1999         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2000         if (finitef(a)) {
2001                 if (finitef(b))
2002                         return a + b;
2003                 else
2004                         return b;
2005         }
2006         else {
2007                 if (finitef(b))
2008                         return a;
2009                 else {
2010                         if (copysignf(1.0, a) == copysignf(1.0, b))
2011                                 return a;
2012                         else
2013                                 return intBitsToFloat(FLT_NAN);
2014                 }
2015         }
2016 }
2017
2018
2019 float builtin_fsub(float a, float b)
2020 {
2021         return builtin_fadd(a, builtin_fneg(b));
2022 }
2023
2024
2025 float builtin_fmul(float a, float b)
2026 {
2027         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2028         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2029         if (finitef(a)) {
2030                 if (finitef(b)) return a * b;
2031                 else {
2032                         if (a == 0) return intBitsToFloat(FLT_NAN);
2033                         else return copysignf(b, copysignf(1.0, b)*a);
2034                 }
2035         }
2036         else {
2037                 if (finitef(b)) {
2038                         if (b == 0) return intBitsToFloat(FLT_NAN);
2039                         else return copysignf(a, copysignf(1.0, a)*b);
2040                 }
2041                 else {
2042                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2043                 }
2044         }
2045 }
2046
2047
2048 /* builtin_ddiv ****************************************************************
2049
2050    Implementation as described in VM Spec.
2051
2052 *******************************************************************************/
2053
2054 float builtin_fdiv(float a, float b)
2055 {
2056         if (finitef(a)) {
2057                 if (finitef(b)) {
2058                         /* If neither value1' nor value2' is NaN, the sign of the result */
2059                         /* is positive if both values have the same sign, negative if the */
2060                         /* values have different signs. */
2061
2062                         return a / b;
2063
2064                 } else {
2065                         if (isnanf(b)) {
2066                                 /* If either value1' or value2' is NaN, the result is NaN. */
2067
2068                                 return intBitsToFloat(FLT_NAN);
2069
2070                         } else {
2071                                 /* Division of a finite value by an infinity results in a */
2072                                 /* signed zero, with the sign-producing rule just given. */
2073
2074                                 /* is sign equal? */
2075
2076                                 if (copysignf(1.0, a) == copysignf(1.0, b))
2077                                         return 0.0;
2078                                 else
2079                                         return -0.0;
2080                         }
2081                 }
2082
2083         } else {
2084                 if (isnanf(a)) {
2085                         /* If either value1' or value2' is NaN, the result is NaN. */
2086
2087                         return intBitsToFloat(FLT_NAN);
2088
2089                 } else if (finitef(b)) {
2090                         /* Division of an infinity by a finite value results in a signed */
2091                         /* infinity, with the sign-producing rule just given. */
2092
2093                         /* is sign equal? */
2094
2095                         if (copysignf(1.0, a) == copysignf(1.0, b))
2096                                 return intBitsToFloat(FLT_POSINF);
2097                         else
2098                                 return intBitsToFloat(FLT_NEGINF);
2099
2100                 } else {
2101                         /* Division of an infinity by an infinity results in NaN. */
2102
2103                         return intBitsToFloat(FLT_NAN);
2104                 }
2105         }
2106 }
2107
2108
2109 float builtin_frem(float a, float b)
2110 {
2111         return fmodf(a, b);
2112 }
2113
2114
2115 float builtin_fneg(float a)
2116 {
2117         if (isnanf(a)) return a;
2118         else {
2119                 if (finitef(a)) return -a;
2120                 else return copysignf(a, -copysignf(1.0, a));
2121         }
2122 }
2123
2124
2125 s4 builtin_fcmpl(float a, float b)
2126 {
2127         if (isnanf(a)) return -1;
2128         if (isnanf(b)) return -1;
2129         if (!finitef(a) || !finitef(b)) {
2130                 a = finitef(a) ? 0 : copysignf(1.0,     a);
2131                 b = finitef(b) ? 0 : copysignf(1.0, b);
2132         }
2133         if (a > b) return 1;
2134         if (a == b) return 0;
2135         return -1;
2136 }
2137
2138
2139 s4 builtin_fcmpg(float a, float b)
2140 {
2141         if (isnanf(a)) return 1;
2142         if (isnanf(b)) return 1;
2143         if (!finitef(a) || !finitef(b)) {
2144                 a = finitef(a) ? 0 : copysignf(1.0, a);
2145                 b = finitef(b) ? 0 : copysignf(1.0, b);
2146         }
2147         if (a > b) return 1;
2148         if (a == b) return 0;
2149         return -1;
2150 }
2151
2152
2153
2154 /************************* Functions for doubles ****************************/
2155
2156 double builtin_dadd(double a, double b)
2157 {
2158         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2159         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2160         if (finite(a)) {
2161                 if (finite(b)) return a + b;
2162                 else return b;
2163         }
2164         else {
2165                 if (finite(b)) return a;
2166                 else {
2167                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
2168                         else return longBitsToDouble(DBL_NAN);
2169                 }
2170         }
2171 }
2172
2173
2174 double builtin_dsub(double a, double b)
2175 {
2176         return builtin_dadd(a, builtin_dneg(b));
2177 }
2178
2179
2180 double builtin_dmul(double a, double b)
2181 {
2182         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2183         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2184         if (finite(a)) {
2185                 if (finite(b)) return a * b;
2186                 else {
2187                         if (a == 0) return longBitsToDouble(DBL_NAN);
2188                         else return copysign(b, copysign(1.0, b) * a);
2189                 }
2190         }
2191         else {
2192                 if (finite(b)) {
2193                         if (b == 0) return longBitsToDouble(DBL_NAN);
2194                         else return copysign(a, copysign(1.0, a) * b);
2195                 }
2196                 else {
2197                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2198                 }
2199         }
2200 }
2201
2202
2203 /* builtin_ddiv ****************************************************************
2204
2205    Implementation as described in VM Spec.
2206
2207 *******************************************************************************/
2208
2209 double builtin_ddiv(double a, double b)
2210 {
2211         if (finite(a)) {
2212                 if (finite(b)) {
2213                         /* If neither value1' nor value2' is NaN, the sign of the result */
2214                         /* is positive if both values have the same sign, negative if the */
2215                         /* values have different signs. */
2216
2217                         return a / b;
2218
2219                 } else {
2220                         if (isnan(b)) {
2221                                 /* If either value1' or value2' is NaN, the result is NaN. */
2222
2223                                 return longBitsToDouble(DBL_NAN);
2224
2225                         } else {
2226                                 /* Division of a finite value by an infinity results in a */
2227                                 /* signed zero, with the sign-producing rule just given. */
2228
2229                                 /* is sign equal? */
2230
2231                                 if (copysign(1.0, a) == copysign(1.0, b))
2232                                         return 0.0;
2233                                 else
2234                                         return -0.0;
2235                         }
2236                 }
2237
2238         } else {
2239                 if (isnan(a)) {
2240                         /* If either value1' or value2' is NaN, the result is NaN. */
2241
2242                         return longBitsToDouble(DBL_NAN);
2243
2244                 } else if (finite(b)) {
2245                         /* Division of an infinity by a finite value results in a signed */
2246                         /* infinity, with the sign-producing rule just given. */
2247
2248                         /* is sign equal? */
2249
2250                         if (copysign(1.0, a) == copysign(1.0, b))
2251                                 return longBitsToDouble(DBL_POSINF);
2252                         else
2253                                 return longBitsToDouble(DBL_NEGINF);
2254
2255                 } else {
2256                         /* Division of an infinity by an infinity results in NaN. */
2257
2258                         return longBitsToDouble(DBL_NAN);
2259                 }
2260         }
2261 }
2262
2263
2264 double builtin_drem(double a, double b)
2265 {
2266         return fmod(a, b);
2267 }
2268
2269 /* builtin_dneg ****************************************************************
2270
2271    Implemented as described in VM Spec.
2272
2273 *******************************************************************************/
2274
2275 double builtin_dneg(double a)
2276 {
2277         if (isnan(a)) {
2278                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2279                 /* sign). */
2280
2281                 return a;
2282
2283         } else {
2284                 if (finite(a)) {
2285                         /* If the operand is a zero, the result is the zero of opposite */
2286                         /* sign. */
2287
2288                         return -a;
2289
2290                 } else {
2291                         /* If the operand is an infinity, the result is the infinity of */
2292                         /* opposite sign. */
2293
2294                         return copysign(a, -copysign(1.0, a));
2295                 }
2296         }
2297 }
2298
2299
2300 s4 builtin_dcmpl(double a, double b)
2301 {
2302         if (isnan(a)) return -1;
2303         if (isnan(b)) return -1;
2304         if (!finite(a) || !finite(b)) {
2305                 a = finite(a) ? 0 : copysign(1.0, a);
2306                 b = finite(b) ? 0 : copysign(1.0, b);
2307         }
2308         if (a > b) return 1;
2309         if (a == b) return 0;
2310         return -1;
2311 }
2312
2313
2314 s4 builtin_dcmpg(double a, double b)
2315 {
2316         if (isnan(a)) return 1;
2317         if (isnan(b)) return 1;
2318         if (!finite(a) || !finite(b)) {
2319                 a = finite(a) ? 0 : copysign(1.0, a);
2320                 b = finite(b) ? 0 : copysign(1.0, b);
2321         }
2322         if (a > b) return 1;
2323         if (a == b) return 0;
2324         return -1;
2325 }
2326
2327
2328 /*********************** Conversion operations ****************************/
2329
2330 s8 builtin_i2l(s4 i)
2331 {
2332 #if U8_AVAILABLE
2333         return i;
2334 #else
2335         s8 v;
2336         v.high = 0;
2337         v.low = i;
2338         return v;
2339 #endif
2340 }
2341
2342
2343 float builtin_i2f(s4 a)
2344 {
2345         float f = (float) a;
2346         return f;
2347 }
2348
2349
2350 double builtin_i2d(s4 a)
2351 {
2352         double d = (double) a;
2353         return d;
2354 }
2355
2356
2357 s4 builtin_l2i(s8 l)
2358 {
2359 #if U8_AVAILABLE
2360         return (s4) l;
2361 #else
2362         return l.low;
2363 #endif
2364 }
2365
2366
2367 float builtin_l2f(s8 a)
2368 {
2369 #if U8_AVAILABLE
2370         float f = (float) a;
2371         return f;
2372 #else
2373         return 0.0;
2374 #endif
2375 }
2376
2377
2378 double builtin_l2d(s8 a)
2379 {
2380 #if U8_AVAILABLE
2381         double d = (double) a;
2382         return d;
2383 #else
2384         return 0.0;
2385 #endif
2386 }
2387
2388
2389 s4 builtin_f2i(float a) 
2390 {
2391         s4 i;
2392
2393         i = builtin_d2i((double) a);
2394
2395         return i;
2396
2397         /*      float f;
2398         
2399                 if (isnanf(a))
2400                 return 0;
2401                 if (finitef(a)) {
2402                 if (a > 2147483647)
2403                 return 2147483647;
2404                 if (a < (-2147483648))
2405                 return (-2147483648);
2406                 return (s4) a;
2407                 }
2408                 f = copysignf((float) 1.0, a);
2409                 if (f > 0)
2410                 return 2147483647;
2411                 return (-2147483648); */
2412 }
2413
2414
2415 s8 builtin_f2l(float a)
2416 {
2417         s8 l;
2418
2419         l = builtin_d2l((double) a);
2420
2421         return l;
2422
2423         /*      float f;
2424         
2425                 if (finitef(a)) {
2426                 if (a > 9223372036854775807L)
2427                 return 9223372036854775807L;
2428                 if (a < (-9223372036854775808L))
2429                 return (-9223372036854775808L);
2430                 return (s8) a;
2431                 }
2432                 if (isnanf(a))
2433                 return 0;
2434                 f = copysignf((float) 1.0, a);
2435                 if (f > 0)
2436                 return 9223372036854775807L;
2437                 return (-9223372036854775808L); */
2438 }
2439
2440
2441 double builtin_f2d(float a)
2442 {
2443         if (finitef(a)) return (double) a;
2444         else {
2445                 if (isnanf(a))
2446                         return longBitsToDouble(DBL_NAN);
2447                 else
2448                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2449         }
2450 }
2451
2452
2453 s4 builtin_d2i(double a) 
2454
2455         double d;
2456         
2457         if (finite(a)) {
2458                 if (a >= 2147483647)
2459                         return 2147483647;
2460                 if (a <= (-2147483647-1))
2461                         return (-2147483647-1);
2462                 return (s4) a;
2463         }
2464         if (isnan(a))
2465                 return 0;
2466         d = copysign(1.0, a);
2467         if (d > 0)
2468                 return 2147483647;
2469         return (-2147483647-1);
2470 }
2471
2472
2473 s8 builtin_d2l(double a)
2474 {
2475         double d;
2476         
2477         if (finite(a)) {
2478                 if (a >= 9223372036854775807LL)
2479                         return 9223372036854775807LL;
2480                 if (a <= (-9223372036854775807LL-1))
2481                         return (-9223372036854775807LL-1);
2482                 return (s8) a;
2483         }
2484         if (isnan(a))
2485                 return 0;
2486         d = copysign(1.0, a);
2487         if (d > 0)
2488                 return 9223372036854775807LL;
2489         return (-9223372036854775807LL-1);
2490 }
2491
2492
2493 float builtin_d2f(double a)
2494 {
2495         if (finite(a))
2496                 return (float) a;
2497         else {
2498                 if (isnan(a))
2499                         return intBitsToFloat(FLT_NAN);
2500                 else
2501                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2502         }
2503 }
2504
2505
2506 /* builtin_clone_array *********************************************************
2507
2508    Wrapper function for cloning arrays.
2509
2510 *******************************************************************************/
2511
2512 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2513 {
2514         java_arrayheader    *ah;
2515         java_lang_Cloneable *c;
2516
2517         c = (java_lang_Cloneable *) o;
2518
2519         ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2520
2521         return ah;
2522 }
2523
2524
2525 /* builtin_asm_get_exceptionptrptr *********************************************
2526
2527    this is a wrapper for calls from asmpart
2528
2529 *******************************************************************************/
2530
2531 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2532 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2533 {
2534         return builtin_get_exceptionptrptr();
2535 }
2536 #endif
2537
2538
2539 /*
2540  * These are local overrides for various environment variables in Emacs.
2541  * Please do not remove this and leave it at the end of the file, where
2542  * Emacs will automagically detect them.
2543  * ---------------------------------------------------------------------
2544  * Local variables:
2545  * mode: c
2546  * indent-tabs-mode: t
2547  * c-basic-offset: 4
2548  * tab-width: 4
2549  * End:
2550  */