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