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