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