* src/vm/jit/show.h (show_filters_init, show_filters_apply, show_filters_test_verbose...
[cacao.git] / src / vm / builtin.c
1 /* src/vm/builtin.c - functions for unsupported operations
2
3    Copyright (C) 1996-2005, 2006, 2007 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    Contains C functions for JavaVM Instructions that cannot be
26    translated to machine language directly. Consequently, the
27    generated machine code for these instructions contains function
28    calls instead of machine instructions, using the C calling
29    convention.
30
31    $Id: builtin.c 7966 2007-05-25 12:41:03Z pm $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39 #include <errno.h>
40 #include <math.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/time.h>
44
45 #include "vm/types.h"
46
47 #include "arch.h"
48 #include "md-abi.h"
49
50 #include "fdlibm/fdlibm.h"
51 #if defined(__CYGWIN__) && defined(Bias)
52 # undef Bias
53 #endif
54
55 #include "mm/gc-common.h"
56 #include "mm/memory.h"
57
58 #include "native/jni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
61
62 #include "threads/lock-common.h"
63
64 #include "toolbox/logging.h"
65 #include "toolbox/util.h"
66
67 #include "vm/builtin.h"
68 #include "vm/cycles-stats.h"
69 #include "vm/exceptions.h"
70 #include "vm/global.h"
71 #include "vm/initialize.h"
72 #include "vm/stringlocal.h"
73
74 #include "vm/jit/asmpart.h"
75 #include "vm/jit/patcher.h"
76
77 #include "vmcore/class.h"
78 #include "vmcore/loader.h"
79 #include "vmcore/options.h"
80 #include "vmcore/rt-timing.h"
81
82 #if defined(ENABLE_VMLOG)
83 #include <vmlog_cacao.h>
84 #endif
85
86 #if defined(ENABLE_DEBUG_FILTER)
87 #       include "vm/jit/show.h"
88 #endif
89
90 /* include builtin tables *****************************************************/
91
92 #include "vm/builtintable.inc"
93
94
95 CYCLES_STATS_DECLARE(builtin_new         ,100,5)
96 CYCLES_STATS_DECLARE(builtin_overhead    , 80,1)
97
98 /* builtintable_init ***********************************************************
99
100    Parse the descriptors of builtin functions and create the parsed
101    descriptors.
102
103 *******************************************************************************/
104
105 static bool builtintable_init(void)
106 {
107         descriptor_pool    *descpool;
108         s4                  dumpsize;
109         builtintable_entry *bte;
110
111         /* mark start of dump memory area */
112
113         dumpsize = dump_size();
114
115         /* create a new descriptor pool */
116
117         descpool = descriptor_pool_new(class_java_lang_Object);
118
119         /* add some entries we need */
120
121         if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
122                 return false;
123
124         if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
125                 return false;
126
127         /* first add all descriptors to the pool */
128
129         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
130                 /* create a utf8 string from descriptor */
131
132                 bte->descriptor = utf_new_char(bte->cdescriptor);
133
134                 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
135                         /* release dump area */
136
137                         dump_release(dumpsize);
138
139                         return false;
140                 }
141         }
142
143         for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
144                 bte->descriptor = utf_new_char(bte->cdescriptor);
145
146                 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
147                         dump_release(dumpsize);
148                         return false;
149                 }
150         }
151
152         for (bte = builtintable_function; bte->fp != NULL; bte++) {
153                 bte->classname  = utf_new_char(bte->cclassname);
154                 bte->name       = utf_new_char(bte->cname);
155                 bte->descriptor = utf_new_char(bte->cdescriptor);
156
157                 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
158                         dump_release(dumpsize);
159                         return false;
160                 }
161         }
162
163         /* create the class reference table */
164
165         (void) descriptor_pool_create_classrefs(descpool, NULL);
166
167         /* allocate space for the parsed descriptors */
168
169         descriptor_pool_alloc_parsed_descriptors(descpool);
170
171         /* now parse all descriptors */
172
173         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
174                 /* parse the descriptor, builtin is always static (no `this' pointer) */
175
176                 bte->md = descriptor_pool_parse_method_descriptor(descpool,
177                                                                                                                   bte->descriptor,
178                                                                                                                   ACC_STATIC, NULL);
179         }
180
181         for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
182                 bte->md = descriptor_pool_parse_method_descriptor(descpool,
183                                                                                                                   bte->descriptor,
184                                                                                                                   ACC_STATIC, NULL);
185         }
186
187         for (bte = builtintable_function; bte->fp != NULL; bte++) {
188                 bte->md = descriptor_pool_parse_method_descriptor(descpool,
189                                                                                                                   bte->descriptor,
190                                                                                                                   ACC_STATIC, NULL);
191         }
192
193         /* release dump area */
194
195         dump_release(dumpsize);
196
197         return true;
198 }
199
200
201 /* builtintable_comparator *****************************************************
202
203    qsort comparator for the automatic builtin table.
204
205 *******************************************************************************/
206
207 static int builtintable_comparator(const void *a, const void *b)
208 {
209         builtintable_entry *bte1;
210         builtintable_entry *bte2;
211
212         bte1 = (builtintable_entry *) a;
213         bte2 = (builtintable_entry *) b;
214
215         return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
216 }
217
218
219 /* builtintable_sort_automatic *************************************************
220
221    Sorts the automatic builtin table.
222
223 *******************************************************************************/
224
225 static void builtintable_sort_automatic(void)
226 {
227         s4 entries;
228
229         /* calculate table size statically (`- 1' comment see builtintable.inc) */
230
231         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
232
233         qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
234                   builtintable_comparator);
235 }
236
237
238 /* builtin_init ****************************************************************
239
240    Initialize the global table of builtin functions.
241
242 *******************************************************************************/
243
244 bool builtin_init(void)
245 {
246         /* initialize the builtin tables */
247
248         if (!builtintable_init())
249                 return false;
250
251         /* sort builtin tables */
252
253         builtintable_sort_automatic();
254
255         return true;
256 }
257
258
259 /* builtintable_get_internal ***************************************************
260
261    Finds an entry in the builtintable for internal functions and
262    returns the a pointer to the structure.
263
264 *******************************************************************************/
265
266 builtintable_entry *builtintable_get_internal(functionptr fp)
267 {
268         builtintable_entry *bte;
269
270         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
271                 if (bte->fp == fp)
272                         return bte;
273         }
274
275         return NULL;
276 }
277
278
279 /* builtintable_get_automatic **************************************************
280
281    Finds an entry in the builtintable for functions which are replaced
282    automatically and returns the a pointer to the structure.
283
284 *******************************************************************************/
285
286 builtintable_entry *builtintable_get_automatic(s4 opcode)
287 {
288         builtintable_entry *first;
289         builtintable_entry *last;
290         builtintable_entry *middle;
291         s4                  half;
292         s4                  entries;
293
294         /* calculate table size statically (`- 1' comment see builtintable.inc) */
295
296         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
297
298         first = builtintable_automatic;
299         last = builtintable_automatic + entries;
300
301         while (entries > 0) {
302                 half = entries / 2;
303                 middle = first + half;
304
305                 if (middle->opcode < opcode) {
306                         first = middle + 1;
307                         entries -= half + 1;
308                 } else
309                         entries = half;
310         }
311
312         return (first != last ? first : NULL);
313 }
314
315
316 /* builtintable_replace_function ***********************************************
317
318    XXX
319
320 *******************************************************************************/
321
322 #if defined(ENABLE_JIT)
323 bool builtintable_replace_function(void *iptr_)
324 {
325         constant_FMIref    *mr;
326         builtintable_entry *bte;
327         instruction        *iptr;
328
329         iptr = (instruction *) iptr_; /* twisti will kill me ;) */
330
331         /* get name and descriptor of the function */
332
333         switch (iptr->opc) {
334         case ICMD_INVOKESTATIC:
335                 /* The instruction MUST be resolved, otherwise we run into
336                    lazy loading troubles.  Anyway, we should/can only replace
337                    very VM-close functions. */
338
339                 if (INSTRUCTION_IS_UNRESOLVED(iptr))
340                         return false;
341
342                 mr = iptr->sx.s23.s3.fmiref;
343                 break;  
344
345         default:
346                 return false;
347         }
348
349         /* search the function table */
350
351         for (bte = builtintable_function; bte->fp != NULL; bte++) {
352                 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
353                         (mr->name             == bte->name) &&
354                         (mr->descriptor       == bte->descriptor)) {
355
356                         /* set the values in the instruction */
357
358                         iptr->opc   = bte->opcode;
359                         iptr->sx.s23.s3.bte = bte;
360                         if (bte->checkexception)
361                                 iptr->flags.bits |= INS_FLAG_CHECK;
362                         else
363                                 iptr->flags.bits &= ~INS_FLAG_CHECK;
364
365                         return true;
366                 }
367         }
368
369         return false;
370 }
371 #endif /* defined(ENABLE_JIT) */
372
373
374 /*****************************************************************************
375                                                                 TYPE CHECKS
376 *****************************************************************************/
377
378 /* builtin_instanceof **********************************************************
379
380    Checks if an object is an instance of some given class (or subclass
381    of that class). If class is an interface, checks if the interface
382    is implemented.
383
384    Return value: 1 ... o is an instance of class or implements the interface
385                  0 ... otherwise or if o == NULL
386                          
387 *******************************************************************************/
388
389 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
390 {
391         if (o == NULL)
392                 return 0;
393
394         return class_isanysubclass(o->vftbl->class, class);
395 }
396
397
398
399 /* builtin_checkcast ***********************************************************
400
401    The same as builtin_instanceof except that 1 is returned when o ==
402    NULL.
403                           
404 *******************************************************************************/
405
406 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
407 {
408         if (o == NULL)
409                 return 1;
410
411         if (class_isanysubclass(o->vftbl->class, class))
412                 return 1;
413
414         return 0;
415 }
416
417
418 /* builtin_descriptorscompatible ***********************************************
419
420    Checks if two array type descriptors are assignment compatible
421
422    Return value: 1 ... target = desc is possible
423                  0 ... otherwise
424                         
425 *******************************************************************************/
426
427 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
428                                                                                 arraydescriptor *target)
429 {
430         if (desc == target)
431                 return 1;
432
433         if (desc->arraytype != target->arraytype)
434                 return 0;
435
436         if (desc->arraytype != ARRAYTYPE_OBJECT)
437                 return 1;
438         
439         /* {both arrays are arrays of references} */
440
441         if (desc->dimension == target->dimension) {
442                 /* an array which contains elements of interface types is
443            allowed to be casted to Object (JOWENN)*/
444
445                 if ((desc->elementvftbl->baseval < 0) &&
446                         (target->elementvftbl->baseval == 1))
447                         return 1;
448
449                 return class_isanysubclass(desc->elementvftbl->class,
450                                                                    target->elementvftbl->class);
451         }
452
453         if (desc->dimension < target->dimension)
454                 return 0;
455
456         /* {desc has higher dimension than target} */
457
458         return class_isanysubclass(pseudo_class_Arraystub,
459                                                            target->elementvftbl->class);
460 }
461
462
463 /* builtin_arraycheckcast ******************************************************
464
465    Checks if an object is really a subtype of the requested array
466    type.  The object has to be an array to begin with. For simple
467    arrays (int, short, double, etc.) the types have to match exactly.
468    For arrays of objects, the type of elements in the array has to be
469    a subtype (or the same type) of the requested element type. For
470    arrays of arrays (which in turn can again be arrays of arrays), the
471    types at the lowest level have to satisfy the corresponding sub
472    class relation.
473         
474 *******************************************************************************/
475
476 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
477 {
478         arraydescriptor *desc;
479
480         if (o == NULL)
481                 return 1;
482
483         desc = o->vftbl->arraydesc;
484
485         if (desc == NULL)
486                 return 0;
487  
488         return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
489 }
490
491
492 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
493 {
494         if (o == NULL)
495                 return 0;
496
497         return builtin_arraycheckcast(o, targetclass);
498 }
499
500
501 /* builtin_throw_exception *****************************************************
502
503    Sets the exceptionptr with the thrown exception and prints some
504    debugging information.  Called from asm_vm_call_method.
505
506 *******************************************************************************/
507
508 void *builtin_throw_exception(java_objectheader *xptr)
509 {
510 #if !defined(NDEBUG)
511     java_lang_Throwable *t;
512         char                *logtext;
513         s4                   logtextlen;
514         s4                   dumpsize;
515
516         if (opt_verbose) {
517                 t = (java_lang_Throwable *) xptr;
518
519                 /* calculate message length */
520
521                 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
522
523                 if (t) {
524                         logtextlen +=
525                                 utf_bytes(xptr->vftbl->class->name);
526                         if (t->detailMessage) {
527                                 logtextlen += strlen(": ") +
528                                         u2_utflength(t->detailMessage->value->data 
529                                                                         + t->detailMessage->offset,
530                                                          t->detailMessage->count);
531                         }
532                 } 
533                 else {
534                         logtextlen += strlen("(nil)");
535                 }
536
537                 /* allocate memory */
538
539                 dumpsize = dump_size();
540
541                 logtext = DMNEW(char, logtextlen);
542
543                 strcpy(logtext, "Builtin exception thrown: ");
544
545                 if (t) {
546                         utf_cat_classname(logtext, xptr->vftbl->class->name);
547
548                         if (t->detailMessage) {
549                                 char *buf;
550
551                                 buf = javastring_tochar((java_objectheader *) t->detailMessage);
552                                 strcat(logtext, ": ");
553                                 strcat(logtext, buf);
554                                 MFREE(buf, char, strlen(buf) + 1);
555                         }
556
557                 } else {
558                         strcat(logtext, "(nil)");
559                 }
560
561                 log_text(logtext);
562
563                 /* release memory */
564
565                 dump_release(dumpsize);
566         }
567 #endif /* !defined(NDEBUG) */
568
569         /* actually set the exception */
570
571         exceptions_set_exception(xptr);
572
573         /* Return a NULL pointer.  This is required for vm_call_method to
574            check for an exception.  This is for convenience. */
575
576         return NULL;
577 }
578
579
580 /* builtin_canstore ************************************************************
581
582    Checks, if an object can be stored in an array.
583
584    Return value: 1 ... possible
585                  0 ... otherwise (throws an ArrayStoreException)
586
587 *******************************************************************************/
588
589 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
590 {
591         arraydescriptor *desc;
592         arraydescriptor *valuedesc;
593         vftbl_t         *componentvftbl;
594         vftbl_t         *valuevftbl;
595         s4               base;
596         castinfo         classvalues;
597         s4               result;
598
599         if (o == NULL)
600                 return 1;
601
602         /* The following is guaranteed (by verifier checks):
603          *
604          *     *) oa->...vftbl->arraydesc != NULL
605          *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
606          *     *) o->vftbl is not an interface vftbl
607          */
608         
609         desc           = oa->header.objheader.vftbl->arraydesc;
610         componentvftbl = desc->componentvftbl;
611         valuevftbl     = o->vftbl;
612         valuedesc      = valuevftbl->arraydesc;
613
614         if ((desc->dimension - 1) == 0) {
615                 /* {oa is a one-dimensional array} */
616                 /* {oa is an array of references} */
617                 
618                 if (valuevftbl == componentvftbl)
619                         return 1;
620
621                 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
622
623                 base = classvalues.super_baseval;
624
625                 if (base <= 0) {
626                         /* an array of interface references */
627
628                         result = ((valuevftbl->interfacetablelength > -base) &&
629                                         (valuevftbl->interfacetable[base] != NULL));
630                 }
631                 else {
632                         result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
633                                    <= (unsigned) classvalues.super_diffval);
634                 }
635         }
636         else if (valuedesc == NULL) {
637                 /* {oa has dimension > 1} */
638                 /* {componentvftbl->arraydesc != NULL} */
639
640                 /* check if o is an array */
641
642                 return 0;
643         }
644         else {
645                 /* {o is an array} */
646
647                 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
648         }
649
650         /* if not possible, throw an exception */
651
652         if (result == 0)
653                 exceptions_throw_arraystoreexception();
654
655         /* return result */
656
657         return result;
658 }
659
660
661 /* This is an optimized version where a is guaranteed to be one-dimensional */
662 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
663 {
664         arraydescriptor *desc;
665         vftbl_t *elementvftbl;
666         vftbl_t *valuevftbl;
667         s4 res;
668         int base;
669         castinfo classvalues;
670         
671         if (!o) return 1;
672
673         /* The following is guaranteed (by verifier checks):
674          *
675          *     *) a->...vftbl->arraydesc != NULL
676          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
677          *     *) a->...vftbl->arraydesc->dimension == 1
678          *     *) o->vftbl is not an interface vftbl
679          */
680
681         desc = a->header.objheader.vftbl->arraydesc;
682     elementvftbl = desc->elementvftbl;
683         valuevftbl = o->vftbl;
684
685         /* {a is a one-dimensional array} */
686         
687         if (valuevftbl == elementvftbl)
688                 return 1;
689
690         ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
691
692         if ((base = classvalues.super_baseval) <= 0)
693                 /* an array of interface references */
694                 return (valuevftbl->interfacetablelength > -base &&
695                                 valuevftbl->interfacetable[base] != NULL);
696
697         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
698                 <= (unsigned) classvalues.super_diffval;
699
700         return res;
701 }
702
703
704 /* This is an optimized version where a is guaranteed to be a
705  * one-dimensional array of a class type */
706 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
707 {
708         vftbl_t *elementvftbl;
709         vftbl_t *valuevftbl;
710         s4 res;
711         castinfo classvalues;
712         
713         if (!o) return 1;
714
715         /* The following is guaranteed (by verifier checks):
716          *
717          *     *) a->...vftbl->arraydesc != NULL
718          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
719          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
720          *     *) a->...vftbl->arraydesc->dimension == 1
721          *     *) o->vftbl is not an interface vftbl
722          */
723
724     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
725         valuevftbl = o->vftbl;
726
727         /* {a is a one-dimensional array} */
728         
729         if (valuevftbl == elementvftbl)
730                 return 1;
731
732         ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
733
734         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
735                 <= (unsigned) classvalues.super_diffval;
736
737         return res;
738 }
739
740
741 /* builtin_new *****************************************************************
742
743    Creates a new instance of class c on the heap.
744
745    Return value: pointer to the object or NULL if no memory is
746    available
747                         
748 *******************************************************************************/
749
750 java_objectheader *builtin_new(classinfo *c)
751 {
752         java_objectheader *o;
753 #if defined(ENABLE_RT_TIMING)
754         struct timespec time_start, time_end;
755 #endif
756 #if defined(ENABLE_CYCLES_STATS)
757         u8 cycles_start, cycles_end;
758 #endif
759
760         RT_TIMING_GET_TIME(time_start);
761         CYCLES_STATS_GET(cycles_start);
762
763         /* is the class loaded */
764
765         assert(c->state & CLASS_LOADED);
766
767         /* check if we can instantiate this class */
768
769         if (c->flags & ACC_ABSTRACT) {
770                 exceptions_throw_instantiationerror(c);
771                 return NULL;
772         }
773
774         /* is the class linked */
775
776         if (!(c->state & CLASS_LINKED))
777                 if (!link_class(c))
778                         return NULL;
779
780         if (!(c->state & CLASS_INITIALIZED)) {
781 #if !defined(NDEBUG)
782                 if (initverbose)
783                         log_message_class("Initialize class (from builtin_new): ", c);
784 #endif
785
786                 if (!initialize_class(c))
787                         return NULL;
788         }
789
790         o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
791                                           c->finalizer);
792
793         if (!o)
794                 return NULL;
795
796         o->vftbl = c->vftbl;
797
798 #if defined(ENABLE_THREADS)
799         lock_init_object_lock(o);
800 #endif
801
802         CYCLES_STATS_GET(cycles_end);
803         RT_TIMING_GET_TIME(time_end);
804
805         CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
806         RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
807
808         return o;
809 }
810
811
812 /* builtin_newarray ************************************************************
813
814    Creates an array with the given vftbl on the heap. This function
815    takes as class argument an array class.
816
817    Return value: pointer to the array or NULL if no memory is available
818
819 *******************************************************************************/
820
821 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
822 {
823         arraydescriptor  *desc;
824         s4                dataoffset;
825         s4                componentsize;
826         s4                actualsize;
827         java_arrayheader *a;
828 #if defined(ENABLE_RT_TIMING)
829         struct timespec time_start, time_end;
830 #endif
831
832         RT_TIMING_GET_TIME(time_start);
833
834         desc          = arrayclass->vftbl->arraydesc;
835         dataoffset    = desc->dataoffset;
836         componentsize = desc->componentsize;
837
838         if (size < 0) {
839                 exceptions_throw_negativearraysizeexception();
840                 return NULL;
841         }
842
843         actualsize = dataoffset + size * componentsize;
844
845         /* check for overflow */
846
847         if (((u4) actualsize) < ((u4) size)) {
848                 exceptions_throw_outofmemoryerror();
849                 return NULL;
850         }
851
852         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
853
854         if (a == NULL)
855                 return NULL;
856
857         a->objheader.vftbl = arrayclass->vftbl;
858
859 #if defined(ENABLE_THREADS)
860         lock_init_object_lock(&a->objheader);
861 #endif
862
863         a->size = size;
864
865         RT_TIMING_GET_TIME(time_end);
866         RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
867
868         return a;
869 }
870
871
872 /* builtin_anewarray ***********************************************************
873
874    Creates an array of references to the given class type on the heap.
875
876    Return value: pointer to the array or NULL if no memory is
877    available
878
879 *******************************************************************************/
880
881 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
882 {
883         classinfo *arrayclass;
884         
885         /* is class loaded */
886
887         assert(componentclass->state & CLASS_LOADED);
888
889         /* is class linked */
890
891         if (!(componentclass->state & CLASS_LINKED))
892                 if (!link_class(componentclass))
893                         return NULL;
894
895         arrayclass = class_array_of(componentclass, true);
896
897         if (!arrayclass)
898                 return NULL;
899
900         return (java_objectarray *) builtin_newarray(size, arrayclass);
901 }
902
903
904 /* builtin_newarray_boolean ****************************************************
905
906    Creates an array of bytes on the heap. The array is designated as
907    an array of booleans (important for casts)
908         
909    Return value: pointer to the array or NULL if no memory is
910    available
911
912 *******************************************************************************/
913
914 java_booleanarray *builtin_newarray_boolean(s4 size)
915 {
916         return (java_booleanarray *)
917                 builtin_newarray(size,
918                                                  primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
919 }
920
921
922 /* builtin_newarray_byte *******************************************************
923
924    Creates an array of 8 bit Integers on the heap.
925
926    Return value: pointer to the array or NULL if no memory is
927    available
928
929 *******************************************************************************/
930
931 java_bytearray *builtin_newarray_byte(s4 size)
932 {
933         return (java_bytearray *)
934                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
935 }
936
937
938 /* builtin_newarray_char *******************************************************
939
940    Creates an array of characters on the heap.
941
942    Return value: pointer to the array or NULL if no memory is
943    available
944
945 *******************************************************************************/
946
947 java_chararray *builtin_newarray_char(s4 size)
948 {
949         return (java_chararray *)
950                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
951 }
952
953
954 /* builtin_newarray_short ******************************************************
955
956    Creates an array of 16 bit Integers on the heap.
957
958    Return value: pointer to the array or NULL if no memory is
959    available
960
961 *******************************************************************************/
962
963 java_shortarray *builtin_newarray_short(s4 size)
964 {
965         return (java_shortarray *)
966                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
967 }
968
969
970 /* builtin_newarray_int ********************************************************
971
972    Creates an array of 32 bit Integers on the heap.
973
974    Return value: pointer to the array or NULL if no memory is
975    available
976
977 *******************************************************************************/
978
979 java_intarray *builtin_newarray_int(s4 size)
980 {
981         return (java_intarray *)
982                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
983 }
984
985
986 /* builtin_newarray_long *******************************************************
987
988    Creates an array of 64 bit Integers on the heap.
989
990    Return value: pointer to the array or NULL if no memory is
991    available
992
993 *******************************************************************************/
994
995 java_longarray *builtin_newarray_long(s4 size)
996 {
997         return (java_longarray *)
998                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
999 }
1000
1001
1002 /* builtin_newarray_float ******************************************************
1003
1004    Creates an array of 32 bit IEEE floats on the heap.
1005
1006    Return value: pointer to the array or NULL if no memory is
1007    available
1008
1009 *******************************************************************************/
1010
1011 java_floatarray *builtin_newarray_float(s4 size)
1012 {
1013         return (java_floatarray *)
1014                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1015 }
1016
1017
1018 /* builtin_newarray_double *****************************************************
1019
1020    Creates an array of 64 bit IEEE floats on the heap.
1021
1022    Return value: pointer to the array or NULL if no memory is
1023    available
1024
1025 *******************************************************************************/
1026
1027 java_doublearray *builtin_newarray_double(s4 size)
1028 {
1029         return (java_doublearray *)
1030                 builtin_newarray(size,
1031                                                  primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1032 }
1033
1034
1035 /* builtin_multianewarray_intern ***********************************************
1036
1037    Creates a multi-dimensional array on the heap. The dimensions are
1038    passed in an array of longs.
1039
1040    Arguments:
1041        n............number of dimensions to create
1042        arrayvftbl...vftbl of the array class
1043        dims.........array containing the size of each dimension to create
1044
1045    Return value: pointer to the array or NULL if no memory is
1046    available
1047
1048 ******************************************************************************/
1049
1050 static java_arrayheader *builtin_multianewarray_intern(int n,
1051                                                                                                            classinfo *arrayclass,
1052                                                                                                            long *dims)
1053 {
1054         s4                size;
1055         java_arrayheader *a;
1056         classinfo        *componentclass;
1057         s4                i;
1058
1059         /* create this dimension */
1060
1061         size = (s4) dims[0];
1062         a = builtin_newarray(size, arrayclass);
1063
1064         if (!a)
1065                 return NULL;
1066
1067         /* if this is the last dimension return */
1068
1069         if (!--n)
1070                 return a;
1071
1072         /* get the class of the components to create */
1073
1074         componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1075
1076         /* The verifier guarantees that the dimension count is in the range. */
1077
1078         /* create the component arrays */
1079
1080         for (i = 0; i < size; i++) {
1081                 java_arrayheader *ea =
1082 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1083                         /* we save an s4 to a s8 slot, 8-byte aligned */
1084
1085                         builtin_multianewarray_intern(n, componentclass, dims + 2);
1086 #else
1087                         builtin_multianewarray_intern(n, componentclass, dims + 1);
1088 #endif
1089
1090                 if (!ea)
1091                         return NULL;
1092                 
1093                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1094         }
1095
1096         return a;
1097 }
1098
1099
1100 /* builtin_multianewarray ******************************************************
1101
1102    Wrapper for builtin_multianewarray_intern which checks all
1103    dimensions before we start allocating.
1104
1105 ******************************************************************************/
1106
1107 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1108                                                                                  long *dims)
1109 {
1110         s4 i;
1111         s4 size;
1112
1113         /* check all dimensions before doing anything */
1114
1115         for (i = 0; i < n; i++) {
1116 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1117                 /* we save an s4 to a s8 slot, 8-byte aligned */
1118                 size = (s4) dims[i * 2];
1119 #else
1120                 size = (s4) dims[i];
1121 #endif
1122
1123                 if (size < 0) {
1124                         exceptions_throw_negativearraysizeexception();
1125                         return NULL;
1126                 }
1127         }
1128
1129         /* now call the real function */
1130
1131         return builtin_multianewarray_intern(n, arrayclass, dims);
1132 }
1133
1134
1135 /*****************************************************************************
1136                                           METHOD LOGGING
1137
1138         Various functions for printing a message at method entry or exit (for
1139         debugging)
1140         
1141 *****************************************************************************/
1142
1143 #if !defined(NDEBUG)
1144 static s4 methodindent = 0;
1145 static u4 callcount = 0;
1146
1147 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1148                                                                                    methodinfo *m,
1149                                                                                    void *pos,
1150                                                                                    s4 indent)
1151 {
1152         char *logtext;
1153         s4    logtextlen;
1154         s4    dumpsize;
1155         codeinfo *code;
1156
1157 #if defined(ENABLE_DEBUG_FILTER)
1158         if (! show_filters_test_verbosecall_exit(m)) return xptr;
1159 #endif
1160
1161 #if defined(ENABLE_VMLOG)
1162         return xptr;
1163 #endif
1164
1165         if (opt_verbosecall && indent)
1166                 methodindent--;
1167
1168         /* calculate message length */
1169
1170         if (xptr) {
1171                 logtextlen =
1172                         strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1173         } 
1174         else {
1175                 logtextlen = strlen("Some Throwable");
1176         }
1177
1178         logtextlen += strlen(" thrown in ");
1179
1180         if (m) {
1181                 logtextlen +=
1182                         utf_bytes(m->class->name) +
1183                         strlen(".") +
1184                         utf_bytes(m->name) +
1185                         utf_bytes(m->descriptor) +
1186                         strlen("(NOSYNC,NATIVE");
1187
1188 #if SIZEOF_VOID_P == 8
1189                 logtextlen +=
1190                         strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1191 #else
1192                 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1193 #endif
1194
1195                 if (m->class->sourcefile == NULL)
1196                         logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1197                 else
1198                         logtextlen += utf_bytes(m->class->sourcefile);
1199
1200                 logtextlen += strlen(":65536)");
1201
1202         } 
1203         else {
1204                 logtextlen += strlen("call_java_method");
1205         }
1206
1207         logtextlen += strlen("0");
1208
1209         /* allocate memory */
1210
1211         dumpsize = dump_size();
1212
1213         logtext = DMNEW(char, logtextlen);
1214
1215         if (xptr) {
1216                 strcpy(logtext, "Exception ");
1217                 utf_cat_classname(logtext, xptr->vftbl->class->name);
1218
1219         } else {
1220                 strcpy(logtext, "Some Throwable");
1221         }
1222
1223         strcat(logtext, " thrown in ");
1224
1225         if (m) {
1226                 utf_cat_classname(logtext, m->class->name);
1227                 strcat(logtext, ".");
1228                 utf_cat(logtext, m->name);
1229                 utf_cat(logtext, m->descriptor);
1230
1231                 if (m->flags & ACC_SYNCHRONIZED)
1232                         strcat(logtext, "(SYNC");
1233                 else
1234                         strcat(logtext, "(NOSYNC");
1235
1236                 if (m->flags & ACC_NATIVE) {
1237                         strcat(logtext, ",NATIVE");
1238
1239                         code = m->code;
1240
1241 #if SIZEOF_VOID_P == 8
1242                         sprintf(logtext + strlen(logtext),
1243                                         ")(0x%016lx) at position 0x%016lx",
1244                                         (ptrint) code->entrypoint, (ptrint) pos);
1245 #else
1246                         sprintf(logtext + strlen(logtext),
1247                                         ")(0x%08x) at position 0x%08x",
1248                                         (ptrint) code->entrypoint, (ptrint) pos);
1249 #endif
1250
1251                 } else {
1252
1253                         /* XXX preliminary: This should get the actual codeinfo */
1254                         /* in which the exception happened.                     */
1255                         code = m->code;
1256                         
1257 #if SIZEOF_VOID_P == 8
1258                         sprintf(logtext + strlen(logtext),
1259                                         ")(0x%016lx) at position 0x%016lx (",
1260                                         (ptrint) code->entrypoint, (ptrint) pos);
1261 #else
1262                         sprintf(logtext + strlen(logtext),
1263                                         ")(0x%08x) at position 0x%08x (",
1264                                         (ptrint) code->entrypoint, (ptrint) pos);
1265 #endif
1266
1267                         if (m->class->sourcefile == NULL)
1268                                 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1269                         else
1270                                 utf_cat(logtext, m->class->sourcefile);
1271
1272                         sprintf(logtext + strlen(logtext), ":%d)", 0);
1273                 }
1274
1275         } else
1276                 strcat(logtext, "call_java_method");
1277
1278         log_text(logtext);
1279
1280         /* release memory */
1281
1282         dump_release(dumpsize);
1283
1284         return xptr;
1285 }
1286 #endif /* !defined(NDEBUG) */
1287
1288
1289 /* builtin_print_argument ******************************************************
1290
1291    Prints arguments and return values for the call trace.
1292
1293 *******************************************************************************/
1294
1295 #if !defined(NDEBUG)
1296 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1297                                                                         typedesc *paramtype, s8 value)
1298 {
1299         imm_union          imu;
1300         java_objectheader *o;
1301         classinfo         *c;
1302         utf               *u;
1303         u4                 len;
1304
1305         switch (paramtype->type) {
1306         case TYPE_INT:
1307                 imu.i = (s4) value;
1308                 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1309                 break;
1310
1311         case TYPE_LNG:
1312                 imu.l = value;
1313 #if SIZEOF_VOID_P == 4
1314                 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1315 #else
1316                 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1317 #endif
1318                 break;
1319
1320         case TYPE_FLT:
1321                 imu.i = (s4) value;
1322                 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1323                 break;
1324
1325         case TYPE_DBL:
1326                 imu.l = value;
1327 #if SIZEOF_VOID_P == 4
1328                 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1329 #else
1330                 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1331 #endif
1332                 break;
1333
1334         case TYPE_ADR:
1335 #if SIZEOF_VOID_P == 4
1336                 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1337 #else
1338                 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1339 #endif
1340
1341                 /* cast to java.lang.Object */
1342
1343                 o = (java_objectheader *) (ptrint) value;
1344
1345                 /* check return argument for java.lang.Class or java.lang.String */
1346
1347                 if (o != NULL) {
1348                         if (o->vftbl->class == class_java_lang_String) {
1349                                 /* get java.lang.String object and the length of the
1350                                    string */
1351
1352                                 u = javastring_toutf(o, false);
1353
1354                                 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1355
1356                                 /* realloc memory for string length */
1357
1358                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1359                                 *logtextlen += len;
1360
1361                                 /* convert to utf8 string and strcat it to the logtext */
1362
1363                                 strcat(logtext, " (String = \"");
1364                                 utf_cat(logtext, u);
1365                                 strcat(logtext, "\")");
1366                         }
1367                         else {
1368                                 if (o->vftbl->class == class_java_lang_Class) {
1369                                         /* if the object returned is a java.lang.Class
1370                                            cast it to classinfo structure and get the name
1371                                            of the class */
1372
1373                                         c = (classinfo *) o;
1374
1375                                         u = c->name;
1376                                 }
1377                                 else {
1378                                         /* if the object returned is not a java.lang.String or
1379                                            a java.lang.Class just print the name of the class */
1380
1381                                         u = o->vftbl->class->name;
1382                                 }
1383
1384                                 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1385
1386                                 /* realloc memory for string length */
1387
1388                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1389                                 *logtextlen += len;
1390
1391                                 /* strcat to the logtext */
1392
1393                                 strcat(logtext, " (Class = \"");
1394                                 utf_cat_classname(logtext, u);
1395                                 strcat(logtext, "\")");
1396                         }
1397                 }
1398         }
1399
1400         return logtext;
1401 }
1402 #endif /* !defined(NDEBUG) */
1403
1404 /* builtin_verbosecall_enter ***************************************************
1405
1406    Print method call with arguments for -verbose:call.
1407
1408 *******************************************************************************/
1409
1410 #if !defined(NDEBUG)
1411
1412 #ifdef TRACE_ARGS_NUM
1413 void builtin_verbosecall_enter(s8 a0, s8 a1,
1414 # if TRACE_ARGS_NUM >= 4
1415                                                            s8 a2, s8 a3,
1416 # endif
1417 # if TRACE_ARGS_NUM >= 6
1418                                                            s8 a4, s8 a5,
1419 # endif
1420 # if TRACE_ARGS_NUM == 8
1421                                                            s8 a6, s8 a7,
1422 # endif
1423                                                            methodinfo *m)
1424 {
1425         methoddesc *md;
1426         char       *logtext;
1427         s4          logtextlen;
1428         s4          dumpsize;
1429         s4          i;
1430         s4          pos;
1431
1432 #if defined(ENABLE_DEBUG_FILTER)
1433         if (! show_filters_test_verbosecall_enter(m)) return;
1434 #endif
1435
1436 #if defined(ENABLE_VMLOG)
1437         vmlog_cacao_enter_method(m);
1438         return;
1439 #endif
1440
1441         md = m->parseddesc;
1442
1443         /* calculate message length */
1444
1445         logtextlen =
1446                 strlen("4294967295 ") +
1447                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1448                 methodindent +
1449                 strlen("called: ") +
1450                 utf_bytes(m->class->name) +
1451                 strlen(".") +
1452                 utf_bytes(m->name) +
1453                 utf_bytes(m->descriptor);
1454
1455         /* Actually it's not possible to have all flags printed, but:
1456            safety first! */
1457
1458         logtextlen +=
1459                 strlen(" PUBLIC") +
1460                 strlen(" PRIVATE") +
1461                 strlen(" PROTECTED") +
1462                 strlen(" STATIC") +
1463                 strlen(" FINAL") +
1464                 strlen(" SYNCHRONIZED") +
1465                 strlen(" VOLATILE") +
1466                 strlen(" TRANSIENT") +
1467                 strlen(" NATIVE") +
1468                 strlen(" INTERFACE") +
1469                 strlen(" ABSTRACT");
1470
1471         /* add maximal argument length */
1472
1473         logtextlen +=
1474                 strlen("(") +
1475                 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1476                 strlen("...(255)") +
1477                 strlen(")");
1478
1479         /* allocate memory */
1480
1481         dumpsize = dump_size();
1482
1483         logtext = DMNEW(char, logtextlen);
1484
1485         callcount++;
1486
1487         sprintf(logtext, "%10d ", callcount);
1488         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1489
1490         pos = strlen(logtext);
1491
1492         for (i = 0; i < methodindent; i++)
1493                 logtext[pos++] = '\t';
1494
1495         strcpy(logtext + pos, "called: ");
1496
1497         utf_cat_classname(logtext, m->class->name);
1498         strcat(logtext, ".");
1499         utf_cat(logtext, m->name);
1500         utf_cat(logtext, m->descriptor);
1501
1502         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1503         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1504         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1505         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1506         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1507         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1508         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1509         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1510         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1511         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1512         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1513
1514         strcat(logtext, "(");
1515
1516         if (md->paramcount >= 1) {
1517                 logtext = builtin_print_argument(logtext, &logtextlen,
1518                                                                                  &md->paramtypes[0], a0);
1519         }
1520
1521         if (md->paramcount >= 2) {
1522                 strcat(logtext, ", ");
1523
1524                 logtext = builtin_print_argument(logtext, &logtextlen,
1525                                                                                  &md->paramtypes[1], a1);
1526         }
1527
1528 #if TRACE_ARGS_NUM >= 4
1529         if (md->paramcount >= 3) {
1530                 strcat(logtext, ", ");
1531
1532                 logtext = builtin_print_argument(logtext, &logtextlen,
1533                                                                                  &md->paramtypes[2], a2);
1534         }
1535
1536         if (md->paramcount >= 4) {
1537                 strcat(logtext, ", ");
1538
1539                 logtext = builtin_print_argument(logtext, &logtextlen,
1540                                                                                  &md->paramtypes[3], a3);
1541         }
1542 #endif
1543
1544 #if TRACE_ARGS_NUM >= 6
1545         if (md->paramcount >= 5) {
1546                 strcat(logtext, ", ");
1547
1548                 logtext = builtin_print_argument(logtext, &logtextlen,
1549                                                                                  &md->paramtypes[4], a4);
1550         }
1551
1552         if (md->paramcount >= 6) {
1553                 strcat(logtext, ", ");
1554
1555                 logtext = builtin_print_argument(logtext, &logtextlen,
1556                                                                                  &md->paramtypes[5], a5);
1557         }
1558 #endif
1559
1560 #if TRACE_ARGS_NUM == 8
1561         if (md->paramcount >= 7) {
1562                 strcat(logtext, ", ");
1563
1564                 logtext = builtin_print_argument(logtext, &logtextlen,
1565                                                                                  &md->paramtypes[6], a6);
1566         }
1567
1568         if (md->paramcount >= 8) {
1569                 strcat(logtext, ", ");
1570
1571                 logtext = builtin_print_argument(logtext, &logtextlen,
1572                                                                                  &md->paramtypes[7], a7);
1573         }
1574 #endif
1575
1576         if (md->paramcount > 8) {
1577                 sprintf(logtext + strlen(logtext), ", ...(%d)",
1578                                 md->paramcount - TRACE_ARGS_NUM);
1579         }
1580
1581         strcat(logtext, ")");
1582
1583         log_text(logtext);
1584
1585         /* release memory */
1586
1587         dump_release(dumpsize);
1588
1589         methodindent++;
1590
1591 }
1592 #endif
1593 #endif /* !defined(NDEBUG) */
1594
1595
1596 /* builtin_verbosecall_exit ****************************************************
1597
1598    Print method exit for -verbose:call.
1599
1600 *******************************************************************************/
1601
1602 #if !defined(NDEBUG)
1603 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1604 {
1605         methoddesc *md;
1606         char       *logtext;
1607         s4          logtextlen;
1608         s4          dumpsize;
1609         s4          i;
1610         s4          pos;
1611         imm_union   val;
1612
1613 #if defined(ENABLE_DEBUG_FILTER)
1614         if (! show_filters_test_verbosecall_exit(m)) return;
1615 #endif
1616
1617 #if defined(ENABLE_VMLOG)
1618         vmlog_cacao_leave_method(m);
1619         return;
1620 #endif
1621
1622         md = m->parseddesc;
1623
1624         /* calculate message length */
1625
1626         logtextlen =
1627                 strlen("4294967295 ") +
1628                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1629                 methodindent +
1630                 strlen("finished: ") +
1631                 utf_bytes(m->class->name) +
1632                 strlen(".") +
1633                 utf_bytes(m->name) +
1634                 utf_bytes(m->descriptor) +
1635                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1636
1637         /* add maximal argument length */
1638
1639         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1640
1641         /* allocate memory */
1642
1643         dumpsize = dump_size();
1644
1645         logtext = DMNEW(char, logtextlen);
1646
1647         /* outdent the log message */
1648
1649         if (methodindent)
1650                 methodindent--;
1651         else
1652                 log_text("WARNING: unmatched methodindent--");
1653
1654         /* generate the message */
1655
1656         sprintf(logtext, "           ");
1657         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1658
1659         pos = strlen(logtext);
1660
1661         for (i = 0; i < methodindent; i++)
1662                 logtext[pos++] = '\t';
1663
1664         strcpy(logtext + pos, "finished: ");
1665         utf_cat_classname(logtext, m->class->name);
1666         strcat(logtext, ".");
1667         utf_cat(logtext, m->name);
1668         utf_cat(logtext, m->descriptor);
1669
1670         if (!IS_VOID_TYPE(md->returntype.type)) {
1671                 strcat(logtext, "->");
1672
1673                 switch (md->returntype.type) {
1674                 case TYPE_INT:
1675                 case TYPE_LNG:
1676                 case TYPE_ADR:
1677                         val.l = l;
1678                         break;
1679
1680                 case TYPE_FLT:
1681                         val.f = f;
1682                         break;
1683
1684                 case TYPE_DBL:
1685                         val.d = d;
1686                         break;
1687                 }
1688
1689                 logtext =
1690                         builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1691         }
1692
1693         log_text(logtext);
1694
1695         /* release memory */
1696
1697         dump_release(dumpsize);
1698
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 || defined(DISABLE_GC)
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 || defined(DISABLE_GC) */
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) || defined (DISABLE_GC)
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 || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2096 s4 builtin_fcmpl(float a, float b)
2097 {
2098         if (isnanf(a))
2099                 return -1;
2100
2101         if (isnanf(b))
2102                 return -1;
2103
2104         if (!finitef(a) || !finitef(b)) {
2105                 a = finitef(a) ? 0 : copysignf(1.0,     a);
2106                 b = finitef(b) ? 0 : copysignf(1.0, b);
2107         }
2108
2109         if (a > b)
2110                 return 1;
2111
2112         if (a == b)
2113                 return 0;
2114
2115         return -1;
2116 }
2117
2118
2119 s4 builtin_fcmpg(float a, float b)
2120 {
2121         if (isnanf(a)) return 1;
2122         if (isnanf(b)) return 1;
2123         if (!finitef(a) || !finitef(b)) {
2124                 a = finitef(a) ? 0 : copysignf(1.0, a);
2125                 b = finitef(b) ? 0 : copysignf(1.0, b);
2126         }
2127         if (a > b) return 1;
2128         if (a == b) return 0;
2129         return -1;
2130 }
2131 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2132
2133
2134 float builtin_frem(float a, float b)
2135 {
2136         return fmodf(a, b);
2137 }
2138
2139
2140 /* functions for unsupported double instructions ******************************/
2141
2142 #if !SUPPORT_DOUBLE
2143 double builtin_dadd(double a, double b)
2144 {
2145         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2146         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2147         if (finite(a)) {
2148                 if (finite(b)) return a + b;
2149                 else return b;
2150         }
2151         else {
2152                 if (finite(b)) return a;
2153                 else {
2154                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
2155                         else return longBitsToDouble(DBL_NAN);
2156                 }
2157         }
2158 }
2159
2160
2161 double builtin_dsub(double a, double b)
2162 {
2163         return builtin_dadd(a, builtin_dneg(b));
2164 }
2165
2166
2167 double builtin_dmul(double a, double b)
2168 {
2169         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2170         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2171         if (finite(a)) {
2172                 if (finite(b)) return a * b;
2173                 else {
2174                         if (a == 0) return longBitsToDouble(DBL_NAN);
2175                         else return copysign(b, copysign(1.0, b) * a);
2176                 }
2177         }
2178         else {
2179                 if (finite(b)) {
2180                         if (b == 0) return longBitsToDouble(DBL_NAN);
2181                         else return copysign(a, copysign(1.0, a) * b);
2182                 }
2183                 else {
2184                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2185                 }
2186         }
2187 }
2188
2189
2190 /* builtin_ddiv ****************************************************************
2191
2192    Implementation as described in VM Spec.
2193
2194 *******************************************************************************/
2195
2196 double builtin_ddiv(double a, double b)
2197 {
2198         if (finite(a)) {
2199                 if (finite(b)) {
2200                         /* If neither value1' nor value2' is NaN, the sign of the result */
2201                         /* is positive if both values have the same sign, negative if the */
2202                         /* values have different signs. */
2203
2204                         return a / b;
2205
2206                 } else {
2207                         if (isnan(b)) {
2208                                 /* If either value1' or value2' is NaN, the result is NaN. */
2209
2210                                 return longBitsToDouble(DBL_NAN);
2211
2212                         } else {
2213                                 /* Division of a finite value by an infinity results in a */
2214                                 /* signed zero, with the sign-producing rule just given. */
2215
2216                                 /* is sign equal? */
2217
2218                                 if (copysign(1.0, a) == copysign(1.0, b))
2219                                         return 0.0;
2220                                 else
2221                                         return -0.0;
2222                         }
2223                 }
2224
2225         } else {
2226                 if (isnan(a)) {
2227                         /* If either value1' or value2' is NaN, the result is NaN. */
2228
2229                         return longBitsToDouble(DBL_NAN);
2230
2231                 } else if (finite(b)) {
2232                         /* Division of an infinity by a finite value results in a signed */
2233                         /* infinity, with the sign-producing rule just given. */
2234
2235                         /* is sign equal? */
2236
2237                         if (copysign(1.0, a) == copysign(1.0, b))
2238                                 return longBitsToDouble(DBL_POSINF);
2239                         else
2240                                 return longBitsToDouble(DBL_NEGINF);
2241
2242                 } else {
2243                         /* Division of an infinity by an infinity results in NaN. */
2244
2245                         return longBitsToDouble(DBL_NAN);
2246                 }
2247         }
2248 }
2249
2250
2251 /* builtin_dneg ****************************************************************
2252
2253    Implemented as described in VM Spec.
2254
2255 *******************************************************************************/
2256
2257 double builtin_dneg(double a)
2258 {
2259         if (isnan(a)) {
2260                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2261                 /* sign). */
2262
2263                 return a;
2264
2265         } else {
2266                 if (finite(a)) {
2267                         /* If the operand is a zero, the result is the zero of opposite */
2268                         /* sign. */
2269
2270                         return -a;
2271
2272                 } else {
2273                         /* If the operand is an infinity, the result is the infinity of */
2274                         /* opposite sign. */
2275
2276                         return copysign(a, -copysign(1.0, a));
2277                 }
2278         }
2279 }
2280 #endif /* !SUPPORT_DOUBLE */
2281
2282
2283 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2284 s4 builtin_dcmpl(double a, double b)
2285 {
2286         if (isnan(a))
2287                 return -1;
2288
2289         if (isnan(b))
2290                 return -1;
2291
2292         if (!finite(a) || !finite(b)) {
2293                 a = finite(a) ? 0 : copysign(1.0, a);
2294                 b = finite(b) ? 0 : copysign(1.0, b);
2295         }
2296
2297         if (a > b)
2298                 return 1;
2299
2300         if (a == b)
2301                 return 0;
2302
2303         return -1;
2304 }
2305
2306
2307 s4 builtin_dcmpg(double a, double b)
2308 {
2309         if (isnan(a))
2310                 return 1;
2311
2312         if (isnan(b))
2313                 return 1;
2314
2315         if (!finite(a) || !finite(b)) {
2316                 a = finite(a) ? 0 : copysign(1.0, a);
2317                 b = finite(b) ? 0 : copysign(1.0, b);
2318         }
2319
2320         if (a > b)
2321                 return 1;
2322
2323         if (a == b)
2324                 return 0;
2325
2326         return -1;
2327 }
2328 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2329
2330
2331 double builtin_drem(double a, double b)
2332 {
2333         return fmod(a, b);
2334 }
2335
2336
2337 /* conversion operations ******************************************************/
2338
2339 #if 0
2340 s8 builtin_i2l(s4 i)
2341 {
2342 #if U8_AVAILABLE
2343         return i;
2344 #else
2345         s8 v;
2346         v.high = 0;
2347         v.low = i;
2348         return v;
2349 #endif
2350 }
2351
2352 s4 builtin_l2i(s8 l)
2353 {
2354 #if U8_AVAILABLE
2355         return (s4) l;
2356 #else
2357         return l.low;
2358 #endif
2359 }
2360 #endif
2361
2362
2363 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2364 float builtin_i2f(s4 a)
2365 {
2366         float f = (float) a;
2367         return f;
2368 }
2369 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2370
2371
2372 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2373 double builtin_i2d(s4 a)
2374 {
2375         double d = (double) a;
2376         return d;
2377 }
2378 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2379
2380
2381 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2382 float builtin_l2f(s8 a)
2383 {
2384 #if U8_AVAILABLE
2385         float f = (float) a;
2386         return f;
2387 #else
2388         return 0.0;
2389 #endif
2390 }
2391 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2392
2393
2394 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2395 double builtin_l2d(s8 a)
2396 {
2397 #if U8_AVAILABLE
2398         double d = (double) a;
2399         return d;
2400 #else
2401         return 0.0;
2402 #endif
2403 }
2404 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2405
2406
2407 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2408 s4 builtin_f2i(float a) 
2409 {
2410         s4 i;
2411
2412         i = builtin_d2i((double) a);
2413
2414         return i;
2415
2416         /*      float f;
2417         
2418                 if (isnanf(a))
2419                 return 0;
2420                 if (finitef(a)) {
2421                 if (a > 2147483647)
2422                 return 2147483647;
2423                 if (a < (-2147483648))
2424                 return (-2147483648);
2425                 return (s4) a;
2426                 }
2427                 f = copysignf((float) 1.0, a);
2428                 if (f > 0)
2429                 return 2147483647;
2430                 return (-2147483648); */
2431 }
2432 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2433
2434
2435 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2436 s8 builtin_f2l(float a)
2437 {
2438         s8 l;
2439
2440         l = builtin_d2l((double) a);
2441
2442         return l;
2443
2444         /*      float f;
2445         
2446                 if (finitef(a)) {
2447                 if (a > 9223372036854775807L)
2448                 return 9223372036854775807L;
2449                 if (a < (-9223372036854775808L))
2450                 return (-9223372036854775808L);
2451                 return (s8) a;
2452                 }
2453                 if (isnanf(a))
2454                 return 0;
2455                 f = copysignf((float) 1.0, a);
2456                 if (f > 0)
2457                 return 9223372036854775807L;
2458                 return (-9223372036854775808L); */
2459 }
2460 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2461
2462
2463 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2464 s4 builtin_d2i(double a) 
2465
2466         double d;
2467         
2468         if (finite(a)) {
2469                 if (a >= 2147483647)
2470                         return 2147483647;
2471                 if (a <= (-2147483647-1))
2472                         return (-2147483647-1);
2473                 return (s4) a;
2474         }
2475         if (isnan(a))
2476                 return 0;
2477         d = copysign(1.0, a);
2478         if (d > 0)
2479                 return 2147483647;
2480         return (-2147483647-1);
2481 }
2482 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2483
2484
2485 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2486 s8 builtin_d2l(double a)
2487 {
2488         double d;
2489         
2490         if (finite(a)) {
2491                 if (a >= 9223372036854775807LL)
2492                         return 9223372036854775807LL;
2493                 if (a <= (-9223372036854775807LL-1))
2494                         return (-9223372036854775807LL-1);
2495                 return (s8) a;
2496         }
2497         if (isnan(a))
2498                 return 0;
2499         d = copysign(1.0, a);
2500         if (d > 0)
2501                 return 9223372036854775807LL;
2502         return (-9223372036854775807LL-1);
2503 }
2504 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2505
2506
2507 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2508 double builtin_f2d(float a)
2509 {
2510         if (finitef(a)) return (double) a;
2511         else {
2512                 if (isnanf(a))
2513                         return longBitsToDouble(DBL_NAN);
2514                 else
2515                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2516         }
2517 }
2518
2519 float builtin_d2f(double a)
2520 {
2521         if (finite(a))
2522                 return (float) a;
2523         else {
2524                 if (isnan(a))
2525                         return intBitsToFloat(FLT_NAN);
2526                 else
2527                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2528         }
2529 }
2530 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2531
2532
2533 /* builtin_arraycopy ***********************************************************
2534
2535    Builtin for java.lang.System.arraycopy.
2536
2537    ATTENTION: This builtin function returns a boolean value to signal
2538    the ICMD_BUILTIN if there was an exception.
2539
2540 *******************************************************************************/
2541
2542 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2543                                            java_arrayheader *dest, s4 destStart, s4 len)
2544 {
2545         arraydescriptor *sdesc;
2546         arraydescriptor *ddesc;
2547         s4               i;
2548
2549         if ((src == NULL) || (dest == NULL)) { 
2550                 exceptions_throw_nullpointerexception();
2551                 return false;
2552         }
2553
2554         sdesc = src->objheader.vftbl->arraydesc;
2555         ddesc = dest->objheader.vftbl->arraydesc;
2556
2557         if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2558                 exceptions_throw_arraystoreexception();
2559                 return false;
2560         }
2561
2562         /* we try to throw exception with the same message as SUN does */
2563
2564         if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2565                 (srcStart  + len < 0) || (srcStart  + len > src->size) ||
2566                 (destStart + len < 0) || (destStart + len > dest->size)) {
2567                 exceptions_throw_arrayindexoutofboundsexception();
2568                 return false;
2569         }
2570
2571         if (sdesc->componentvftbl == ddesc->componentvftbl) {
2572                 /* We copy primitive values or references of exactly the same type */
2573
2574                 s4 dataoffset = sdesc->dataoffset;
2575                 s4 componentsize = sdesc->componentsize;
2576
2577                 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2578                                 ((u1 *) src)  + dataoffset + componentsize * srcStart,
2579                                 (size_t) len * componentsize);
2580         }
2581         else {
2582                 /* We copy references of different type */
2583
2584                 java_objectarray *oas = (java_objectarray *) src;
2585                 java_objectarray *oad = (java_objectarray *) dest;
2586                 
2587                 if (destStart <= srcStart) {
2588                         for (i = 0; i < len; i++) {
2589                                 java_objectheader *o = oas->data[srcStart + i];
2590
2591                                 if (!builtin_canstore(oad, o))
2592                                         return false;
2593
2594                                 oad->data[destStart + i] = o;
2595                         }
2596                 }
2597                 else {
2598                         /* XXX this does not completely obey the specification!
2599                            If an exception is thrown only the elements above the
2600                            current index have been copied. The specification
2601                            requires that only the elements *below* the current
2602                            index have been copied before the throw. */
2603
2604                         for (i = len - 1; i >= 0; i--) {
2605                                 java_objectheader *o = oas->data[srcStart + i];
2606
2607                                 if (!builtin_canstore(oad, o))
2608                                         return false;
2609
2610                                 oad->data[destStart + i] = o;
2611                         }
2612                 }
2613         }
2614
2615         return true;
2616 }
2617
2618
2619 /* builtin_currenttimemillis ***************************************************
2620
2621    Return the current time in milliseconds.
2622
2623 *******************************************************************************/
2624
2625 s8 builtin_currenttimemillis(void)
2626 {
2627         struct timeval tv;
2628         s8             result;
2629
2630         if (gettimeofday(&tv, NULL) == -1)
2631                 vm_abort("gettimeofday failed: %s", strerror(errno));
2632
2633         result = (s8) tv.tv_sec;
2634         result *= 1000;
2635         result += (tv.tv_usec / 1000);
2636
2637         return result;
2638 }
2639
2640
2641 /* builtin_clone ***************************************************************
2642
2643    Function for cloning objects or arrays.
2644
2645 *******************************************************************************/
2646
2647 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2648 {
2649         arraydescriptor   *ad;
2650         java_arrayheader  *ah;
2651         u4                 size;
2652         classinfo         *c;
2653         java_objectheader *co;              /* cloned object header               */
2654
2655         /* get the array descriptor */
2656
2657         ad = o->vftbl->arraydesc;
2658
2659         /* we are cloning an array */
2660
2661         if (ad != NULL) {
2662                 ah = (java_arrayheader *) o;
2663
2664                 size = ad->dataoffset + ad->componentsize * ah->size;
2665         
2666                 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2667
2668                 if (co == NULL)
2669                         return NULL;
2670
2671                 MCOPY(co, o, u1, size);
2672
2673 #if defined(ENABLE_GC_CACAO)
2674                 heap_init_objectheader(co, size);
2675 #endif
2676
2677 #if defined(ENABLE_THREADS)
2678                 lock_init_object_lock(co);
2679 #endif
2680
2681                 return co;
2682         }
2683     
2684     /* we are cloning a non-array */
2685
2686     if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2687         exceptions_throw_clonenotsupportedexception();
2688         return NULL;
2689     }
2690
2691         /* get the class of the object */
2692
2693     c = o->vftbl->class;
2694
2695         /* create new object */
2696
2697     co = builtin_new(c);
2698
2699     if (co == NULL)
2700         return NULL;
2701
2702     MCOPY(co, o, u1, c->instancesize);
2703
2704 #if defined(ENABLE_GC_CACAO)
2705         heap_init_objectheader(co, c->instancesize);
2706 #endif
2707
2708 #if defined(ENABLE_THREADS)
2709         lock_init_object_lock(co);
2710 #endif
2711
2712     return co;
2713 }
2714
2715 #if defined(ENABLE_VMLOG)
2716 #define NDEBUG
2717 #include <vmlog_cacao.c>
2718 #endif
2719
2720
2721 /*
2722  * These are local overrides for various environment variables in Emacs.
2723  * Please do not remove this and leave it at the end of the file, where
2724  * Emacs will automagically detect them.
2725  * ---------------------------------------------------------------------
2726  * Local variables:
2727  * mode: c
2728  * indent-tabs-mode: t
2729  * c-basic-offset: 4
2730  * tab-width: 4
2731  * End:
2732  * vim:noexpandtab:sw=4:ts=4:
2733  */