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