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