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