839a47d4ecccc2058b10d5a6bdf3125ca5e13c4c
[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 7797 2007-04-23 20:12:39Z michi $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39 #include <errno.h>
40 #include <math.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/time.h>
44
45 #include "vm/types.h"
46
47 #include "arch.h"
48 #include "md-abi.h"
49
50 #include "fdlibm/fdlibm.h"
51 #if defined(__CYGWIN__) && defined(Bias)
52 # undef Bias
53 #endif
54
55 #include "mm/gc-common.h"
56 #include "mm/memory.h"
57
58 #include "native/jni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
61
62 #if defined(ENABLE_THREADS)
63 # include "threads/native/lock.h"
64 #endif
65
66 #include "toolbox/logging.h"
67 #include "toolbox/util.h"
68
69 #include "vm/builtin.h"
70 #include "vm/cycles-stats.h"
71 #include "vm/exceptions.h"
72 #include "vm/global.h"
73 #include "vm/initialize.h"
74 #include "vm/stringlocal.h"
75
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/patcher.h"
78
79 #include "vmcore/class.h"
80 #include "vmcore/loader.h"
81 #include "vmcore/options.h"
82 #include "vmcore/rt-timing.h"
83
84 #if defined(ENABLE_VMLOG)
85 #include <vmlog_cacao.h>
86 #endif
87
88
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        arrayvftbl...vftbl of 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_VMLOG)
1225         return xptr;
1226 #endif
1227
1228         if (opt_verbosecall && indent)
1229                 methodindent--;
1230
1231         /* calculate message length */
1232
1233         if (xptr) {
1234                 logtextlen =
1235                         strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1236         } 
1237         else {
1238                 logtextlen = strlen("Some Throwable");
1239         }
1240
1241         logtextlen += strlen(" thrown in ");
1242
1243         if (m) {
1244                 logtextlen +=
1245                         utf_bytes(m->class->name) +
1246                         strlen(".") +
1247                         utf_bytes(m->name) +
1248                         utf_bytes(m->descriptor) +
1249                         strlen("(NOSYNC,NATIVE");
1250
1251 #if SIZEOF_VOID_P == 8
1252                 logtextlen +=
1253                         strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1254 #else
1255                 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1256 #endif
1257
1258                 if (m->class->sourcefile == NULL)
1259                         logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1260                 else
1261                         logtextlen += utf_bytes(m->class->sourcefile);
1262
1263                 logtextlen += strlen(":65536)");
1264
1265         } 
1266         else {
1267                 logtextlen += strlen("call_java_method");
1268         }
1269
1270         logtextlen += strlen("0");
1271
1272         /* allocate memory */
1273
1274         dumpsize = dump_size();
1275
1276         logtext = DMNEW(char, logtextlen);
1277
1278         if (xptr) {
1279                 strcpy(logtext, "Exception ");
1280                 utf_cat_classname(logtext, xptr->vftbl->class->name);
1281
1282         } else {
1283                 strcpy(logtext, "Some Throwable");
1284         }
1285
1286         strcat(logtext, " thrown in ");
1287
1288         if (m) {
1289                 utf_cat_classname(logtext, m->class->name);
1290                 strcat(logtext, ".");
1291                 utf_cat(logtext, m->name);
1292                 utf_cat(logtext, m->descriptor);
1293
1294                 if (m->flags & ACC_SYNCHRONIZED)
1295                         strcat(logtext, "(SYNC");
1296                 else
1297                         strcat(logtext, "(NOSYNC");
1298
1299                 if (m->flags & ACC_NATIVE) {
1300                         strcat(logtext, ",NATIVE");
1301
1302                         code = m->code;
1303
1304 #if SIZEOF_VOID_P == 8
1305                         sprintf(logtext + strlen(logtext),
1306                                         ")(0x%016lx) at position 0x%016lx",
1307                                         (ptrint) code->entrypoint, (ptrint) pos);
1308 #else
1309                         sprintf(logtext + strlen(logtext),
1310                                         ")(0x%08x) at position 0x%08x",
1311                                         (ptrint) code->entrypoint, (ptrint) pos);
1312 #endif
1313
1314                 } else {
1315
1316                         /* XXX preliminary: This should get the actual codeinfo */
1317                         /* in which the exception happened.                     */
1318                         code = m->code;
1319                         
1320 #if SIZEOF_VOID_P == 8
1321                         sprintf(logtext + strlen(logtext),
1322                                         ")(0x%016lx) at position 0x%016lx (",
1323                                         (ptrint) code->entrypoint, (ptrint) pos);
1324 #else
1325                         sprintf(logtext + strlen(logtext),
1326                                         ")(0x%08x) at position 0x%08x (",
1327                                         (ptrint) code->entrypoint, (ptrint) pos);
1328 #endif
1329
1330                         if (m->class->sourcefile == NULL)
1331                                 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1332                         else
1333                                 utf_cat(logtext, m->class->sourcefile);
1334
1335                         sprintf(logtext + strlen(logtext), ":%d)", 0);
1336                 }
1337
1338         } else
1339                 strcat(logtext, "call_java_method");
1340
1341         log_text(logtext);
1342
1343         /* release memory */
1344
1345         dump_release(dumpsize);
1346
1347         return xptr;
1348 }
1349 #endif /* !defined(NDEBUG) */
1350
1351
1352 /* builtin_print_argument ******************************************************
1353
1354    Prints arguments and return values for the call trace.
1355
1356 *******************************************************************************/
1357
1358 #if !defined(NDEBUG)
1359 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1360                                                                         typedesc *paramtype, s8 value)
1361 {
1362         imm_union          imu;
1363         java_objectheader *o;
1364         classinfo         *c;
1365         utf               *u;
1366         u4                 len;
1367
1368         switch (paramtype->type) {
1369         case TYPE_INT:
1370                 imu.i = (s4) value;
1371                 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1372                 break;
1373
1374         case TYPE_LNG:
1375                 imu.l = value;
1376 #if SIZEOF_VOID_P == 4
1377                 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1378 #else
1379                 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1380 #endif
1381                 break;
1382
1383         case TYPE_FLT:
1384                 imu.i = (s4) value;
1385                 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1386                 break;
1387
1388         case TYPE_DBL:
1389                 imu.l = value;
1390 #if SIZEOF_VOID_P == 4
1391                 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1392 #else
1393                 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1394 #endif
1395                 break;
1396
1397         case TYPE_ADR:
1398 #if SIZEOF_VOID_P == 4
1399                 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1400 #else
1401                 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1402 #endif
1403
1404                 /* cast to java.lang.Object */
1405
1406                 o = (java_objectheader *) (ptrint) value;
1407
1408                 /* check return argument for java.lang.Class or java.lang.String */
1409
1410                 if (o != NULL) {
1411                         if (o->vftbl->class == class_java_lang_String) {
1412                                 /* get java.lang.String object and the length of the
1413                                    string */
1414
1415                                 u = javastring_toutf(o, false);
1416
1417                                 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1418
1419                                 /* realloc memory for string length */
1420
1421                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1422                                 *logtextlen += len;
1423
1424                                 /* convert to utf8 string and strcat it to the logtext */
1425
1426                                 strcat(logtext, " (String = \"");
1427                                 utf_cat(logtext, u);
1428                                 strcat(logtext, "\")");
1429                         }
1430                         else {
1431                                 if (o->vftbl->class == class_java_lang_Class) {
1432                                         /* if the object returned is a java.lang.Class
1433                                            cast it to classinfo structure and get the name
1434                                            of the class */
1435
1436                                         c = (classinfo *) o;
1437
1438                                         u = c->name;
1439                                 }
1440                                 else {
1441                                         /* if the object returned is not a java.lang.String or
1442                                            a java.lang.Class just print the name of the class */
1443
1444                                         u = o->vftbl->class->name;
1445                                 }
1446
1447                                 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1448
1449                                 /* realloc memory for string length */
1450
1451                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1452                                 *logtextlen += len;
1453
1454                                 /* strcat to the logtext */
1455
1456                                 strcat(logtext, " (Class = \"");
1457                                 utf_cat_classname(logtext, u);
1458                                 strcat(logtext, "\")");
1459                         }
1460                 }
1461         }
1462
1463         return logtext;
1464 }
1465 #endif /* !defined(NDEBUG) */
1466
1467
1468 /* builtin_verbosecall_enter ***************************************************
1469
1470    Print method call with arguments for -verbose:call.
1471
1472 *******************************************************************************/
1473
1474 #if !defined(NDEBUG)
1475
1476 #ifdef TRACE_ARGS_NUM
1477 void builtin_verbosecall_enter(s8 a0, s8 a1,
1478 # if TRACE_ARGS_NUM >= 4
1479                                                            s8 a2, s8 a3,
1480 # endif
1481 # if TRACE_ARGS_NUM >= 6
1482                                                            s8 a4, s8 a5,
1483 # endif
1484 # if TRACE_ARGS_NUM == 8
1485                                                            s8 a6, s8 a7,
1486 # endif
1487                                                            methodinfo *m)
1488 {
1489         methoddesc *md;
1490         char       *logtext;
1491         s4          logtextlen;
1492         s4          dumpsize;
1493         s4          i;
1494         s4          pos;
1495
1496 #if defined(ENABLE_VMLOG)
1497         vmlog_cacao_enter_method(m);
1498         return;
1499 #endif
1500
1501         md = m->parseddesc;
1502
1503         /* calculate message length */
1504
1505         logtextlen =
1506                 strlen("4294967295 ") +
1507                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1508                 methodindent +
1509                 strlen("called: ") +
1510                 utf_bytes(m->class->name) +
1511                 strlen(".") +
1512                 utf_bytes(m->name) +
1513                 utf_bytes(m->descriptor);
1514
1515         /* Actually it's not possible to have all flags printed, but:
1516            safety first! */
1517
1518         logtextlen +=
1519                 strlen(" PUBLIC") +
1520                 strlen(" PRIVATE") +
1521                 strlen(" PROTECTED") +
1522                 strlen(" STATIC") +
1523                 strlen(" FINAL") +
1524                 strlen(" SYNCHRONIZED") +
1525                 strlen(" VOLATILE") +
1526                 strlen(" TRANSIENT") +
1527                 strlen(" NATIVE") +
1528                 strlen(" INTERFACE") +
1529                 strlen(" ABSTRACT");
1530
1531         /* add maximal argument length */
1532
1533         logtextlen +=
1534                 strlen("(") +
1535                 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1536                 strlen("...(255)") +
1537                 strlen(")");
1538
1539         /* allocate memory */
1540
1541         dumpsize = dump_size();
1542
1543         logtext = DMNEW(char, logtextlen);
1544
1545         callcount++;
1546
1547         sprintf(logtext, "%10d ", callcount);
1548         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1549
1550         pos = strlen(logtext);
1551
1552         for (i = 0; i < methodindent; i++)
1553                 logtext[pos++] = '\t';
1554
1555         strcpy(logtext + pos, "called: ");
1556
1557         utf_cat_classname(logtext, m->class->name);
1558         strcat(logtext, ".");
1559         utf_cat(logtext, m->name);
1560         utf_cat(logtext, m->descriptor);
1561
1562         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1563         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1564         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1565         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1566         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1567         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1568         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1569         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1570         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1571         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1572         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1573
1574         strcat(logtext, "(");
1575
1576         if (md->paramcount >= 1) {
1577                 logtext = builtin_print_argument(logtext, &logtextlen,
1578                                                                                  &md->paramtypes[0], a0);
1579         }
1580
1581         if (md->paramcount >= 2) {
1582                 strcat(logtext, ", ");
1583
1584                 logtext = builtin_print_argument(logtext, &logtextlen,
1585                                                                                  &md->paramtypes[1], a1);
1586         }
1587
1588 #if TRACE_ARGS_NUM >= 4
1589         if (md->paramcount >= 3) {
1590                 strcat(logtext, ", ");
1591
1592                 logtext = builtin_print_argument(logtext, &logtextlen,
1593                                                                                  &md->paramtypes[2], a2);
1594         }
1595
1596         if (md->paramcount >= 4) {
1597                 strcat(logtext, ", ");
1598
1599                 logtext = builtin_print_argument(logtext, &logtextlen,
1600                                                                                  &md->paramtypes[3], a3);
1601         }
1602 #endif
1603
1604 #if TRACE_ARGS_NUM >= 6
1605         if (md->paramcount >= 5) {
1606                 strcat(logtext, ", ");
1607
1608                 logtext = builtin_print_argument(logtext, &logtextlen,
1609                                                                                  &md->paramtypes[4], a4);
1610         }
1611
1612         if (md->paramcount >= 6) {
1613                 strcat(logtext, ", ");
1614
1615                 logtext = builtin_print_argument(logtext, &logtextlen,
1616                                                                                  &md->paramtypes[5], a5);
1617         }
1618 #endif
1619
1620 #if TRACE_ARGS_NUM == 8
1621         if (md->paramcount >= 7) {
1622                 strcat(logtext, ", ");
1623
1624                 logtext = builtin_print_argument(logtext, &logtextlen,
1625                                                                                  &md->paramtypes[6], a6);
1626         }
1627
1628         if (md->paramcount >= 8) {
1629                 strcat(logtext, ", ");
1630
1631                 logtext = builtin_print_argument(logtext, &logtextlen,
1632                                                                                  &md->paramtypes[7], a7);
1633         }
1634 #endif
1635
1636         if (md->paramcount > 8) {
1637                 sprintf(logtext + strlen(logtext), ", ...(%d)",
1638                                 md->paramcount - TRACE_ARGS_NUM);
1639         }
1640
1641         strcat(logtext, ")");
1642
1643         log_text(logtext);
1644
1645         /* release memory */
1646
1647         dump_release(dumpsize);
1648
1649         methodindent++;
1650 }
1651 #endif
1652 #endif /* !defined(NDEBUG) */
1653
1654
1655 /* builtin_verbosecall_exit ****************************************************
1656
1657    Print method exit for -verbose:call.
1658
1659 *******************************************************************************/
1660
1661 #if !defined(NDEBUG)
1662 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1663 {
1664         methoddesc *md;
1665         char       *logtext;
1666         s4          logtextlen;
1667         s4          dumpsize;
1668         s4          i;
1669         s4          pos;
1670         imm_union   val;
1671
1672 #if defined(ENABLE_VMLOG)
1673         vmlog_cacao_leave_method(m);
1674         return;
1675 #endif
1676
1677         md = m->parseddesc;
1678
1679         /* calculate message length */
1680
1681         logtextlen =
1682                 strlen("4294967295 ") +
1683                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1684                 methodindent +
1685                 strlen("finished: ") +
1686                 utf_bytes(m->class->name) +
1687                 strlen(".") +
1688                 utf_bytes(m->name) +
1689                 utf_bytes(m->descriptor) +
1690                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1691
1692         /* add maximal argument length */
1693
1694         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1695
1696         /* allocate memory */
1697
1698         dumpsize = dump_size();
1699
1700         logtext = DMNEW(char, logtextlen);
1701
1702         /* outdent the log message */
1703
1704         if (methodindent)
1705                 methodindent--;
1706         else
1707                 log_text("WARNING: unmatched methodindent--");
1708
1709         /* generate the message */
1710
1711         sprintf(logtext, "           ");
1712         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1713
1714         pos = strlen(logtext);
1715
1716         for (i = 0; i < methodindent; i++)
1717                 logtext[pos++] = '\t';
1718
1719         strcpy(logtext + pos, "finished: ");
1720         utf_cat_classname(logtext, m->class->name);
1721         strcat(logtext, ".");
1722         utf_cat(logtext, m->name);
1723         utf_cat(logtext, m->descriptor);
1724
1725         if (!IS_VOID_TYPE(md->returntype.type)) {
1726                 strcat(logtext, "->");
1727
1728                 switch (md->returntype.type) {
1729                 case TYPE_INT:
1730                 case TYPE_LNG:
1731                 case TYPE_ADR:
1732                         val.l = l;
1733                         break;
1734
1735                 case TYPE_FLT:
1736                         val.f = f;
1737                         break;
1738
1739                 case TYPE_DBL:
1740                         val.d = d;
1741                         break;
1742                 }
1743
1744                 logtext =
1745                         builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1746         }
1747
1748         log_text(logtext);
1749
1750         /* release memory */
1751
1752         dump_release(dumpsize);
1753 }
1754 #endif /* !defined(NDEBUG) */
1755
1756
1757 #if defined(ENABLE_CYCLES_STATS)
1758 void builtin_print_cycles_stats(FILE *file)
1759 {
1760         fprintf(file,"builtin cylce count statistics:\n");
1761
1762         CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1763         CYCLES_STATS_PRINT(builtin_new         ,file);
1764
1765         fprintf(file,"\n");
1766 }
1767 #endif /* defined(ENABLE_CYCLES_STATS) */
1768
1769
1770 /*****************************************************************************
1771                           MISCELLANEOUS HELPER FUNCTIONS
1772 *****************************************************************************/
1773
1774
1775
1776 /*********** Functions for integer divisions *****************************
1777  
1778         On some systems (eg. DEC ALPHA), integer division is not supported by the
1779         CPU. These helper functions implement the missing functionality.
1780
1781 ******************************************************************************/
1782
1783 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1784 s4 builtin_idiv(s4 a, s4 b)
1785 {
1786         s4 c;
1787
1788         c = a / b;
1789
1790         return c;
1791 }
1792
1793 s4 builtin_irem(s4 a, s4 b)
1794 {
1795         s4 c;
1796
1797         c = a % b;
1798
1799         return c;
1800 }
1801 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1802
1803
1804 /* functions for long arithmetics **********************************************
1805
1806    On systems where 64 bit Integers are not supported by the CPU,
1807    these functions are needed.
1808
1809 ******************************************************************************/
1810
1811 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1812 s8 builtin_ladd(s8 a, s8 b)
1813 {
1814         s8 c;
1815
1816 #if U8_AVAILABLE
1817         c = a + b; 
1818 #else
1819         c = builtin_i2l(0);
1820 #endif
1821
1822         return c;
1823 }
1824
1825 s8 builtin_lsub(s8 a, s8 b)
1826 {
1827         s8 c;
1828
1829 #if U8_AVAILABLE
1830         c = a - b; 
1831 #else
1832         c = builtin_i2l(0);
1833 #endif
1834
1835         return c;
1836 }
1837
1838 s8 builtin_lneg(s8 a)
1839 {
1840         s8 c;
1841
1842 #if U8_AVAILABLE
1843         c = -a;
1844 #else
1845         c = builtin_i2l(0);
1846 #endif
1847
1848         return c;
1849 }
1850 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1851
1852
1853 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1854 s8 builtin_lmul(s8 a, s8 b)
1855 {
1856         s8 c;
1857
1858 #if U8_AVAILABLE
1859         c = a * b; 
1860 #else
1861         c = builtin_i2l(0);
1862 #endif
1863
1864         return c;
1865 }
1866 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1867
1868
1869 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1870 s8 builtin_ldiv(s8 a, s8 b)
1871 {
1872         s8 c;
1873
1874 #if U8_AVAILABLE
1875         c = a / b; 
1876 #else
1877         c = builtin_i2l(0);
1878 #endif
1879
1880         return c;
1881 }
1882
1883 s8 builtin_lrem(s8 a, s8 b)
1884 {
1885         s8 c;
1886
1887 #if U8_AVAILABLE
1888         c = a % b; 
1889 #else
1890         c = builtin_i2l(0);
1891 #endif
1892
1893         return c;
1894 }
1895 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1896
1897
1898 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1899 s8 builtin_lshl(s8 a, s4 b)
1900 {
1901         s8 c;
1902
1903 #if U8_AVAILABLE
1904         c = a << (b & 63);
1905 #else
1906         c = builtin_i2l(0);
1907 #endif
1908
1909         return c;
1910 }
1911
1912 s8 builtin_lshr(s8 a, s4 b)
1913 {
1914         s8 c;
1915
1916 #if U8_AVAILABLE
1917         c = a >> (b & 63);
1918 #else
1919         c = builtin_i2l(0);
1920 #endif
1921
1922         return c;
1923 }
1924
1925 s8 builtin_lushr(s8 a, s4 b)
1926 {
1927         s8 c;
1928
1929 #if U8_AVAILABLE
1930         c = ((u8) a) >> (b & 63);
1931 #else
1932         c = builtin_i2l(0);
1933 #endif
1934
1935         return c;
1936 }
1937 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1938
1939
1940 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1941 s8 builtin_land(s8 a, s8 b)
1942 {
1943         s8 c;
1944
1945 #if U8_AVAILABLE
1946         c = a & b; 
1947 #else
1948         c = builtin_i2l(0);
1949 #endif
1950
1951         return c;
1952 }
1953
1954 s8 builtin_lor(s8 a, s8 b)
1955 {
1956         s8 c;
1957
1958 #if U8_AVAILABLE
1959         c = a | b; 
1960 #else
1961         c = builtin_i2l(0);
1962 #endif
1963
1964         return c;
1965 }
1966
1967 s8 builtin_lxor(s8 a, s8 b) 
1968 {
1969         s8 c;
1970
1971 #if U8_AVAILABLE
1972         c = a ^ b; 
1973 #else
1974         c = builtin_i2l(0);
1975 #endif
1976
1977         return c;
1978 }
1979 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1980
1981
1982 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1983 s4 builtin_lcmp(s8 a, s8 b)
1984
1985 #if U8_AVAILABLE
1986         if (a < b)
1987                 return -1;
1988
1989         if (a > b)
1990                 return 1;
1991
1992         return 0;
1993 #else
1994         return 0;
1995 #endif
1996 }
1997 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1998
1999
2000 /* functions for unsupported floating instructions ****************************/
2001
2002 /* used to convert FLT_xxx defines into float values */
2003
2004 static inline float intBitsToFloat(s4 i)
2005 {
2006         imm_union imb;
2007
2008         imb.i = i;
2009         return imb.f;
2010 }
2011
2012
2013 /* used to convert DBL_xxx defines into double values */
2014
2015 static inline float longBitsToDouble(s8 l)
2016 {
2017         imm_union imb;
2018
2019         imb.l = l;
2020         return imb.d;
2021 }
2022
2023
2024 #if !SUPPORT_FLOAT
2025 float builtin_fadd(float a, float b)
2026 {
2027         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2028         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2029         if (finitef(a)) {
2030                 if (finitef(b))
2031                         return a + b;
2032                 else
2033                         return b;
2034         }
2035         else {
2036                 if (finitef(b))
2037                         return a;
2038                 else {
2039                         if (copysignf(1.0, a) == copysignf(1.0, b))
2040                                 return a;
2041                         else
2042                                 return intBitsToFloat(FLT_NAN);
2043                 }
2044         }
2045 }
2046
2047
2048 float builtin_fsub(float a, float b)
2049 {
2050         return builtin_fadd(a, builtin_fneg(b));
2051 }
2052
2053
2054 float builtin_fmul(float a, float b)
2055 {
2056         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2057         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2058         if (finitef(a)) {
2059                 if (finitef(b)) return a * b;
2060                 else {
2061                         if (a == 0) return intBitsToFloat(FLT_NAN);
2062                         else return copysignf(b, copysignf(1.0, b)*a);
2063                 }
2064         }
2065         else {
2066                 if (finitef(b)) {
2067                         if (b == 0) return intBitsToFloat(FLT_NAN);
2068                         else return copysignf(a, copysignf(1.0, a)*b);
2069                 }
2070                 else {
2071                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2072                 }
2073         }
2074 }
2075
2076
2077 /* builtin_ddiv ****************************************************************
2078
2079    Implementation as described in VM Spec.
2080
2081 *******************************************************************************/
2082
2083 float builtin_fdiv(float a, float b)
2084 {
2085         if (finitef(a)) {
2086                 if (finitef(b)) {
2087                         /* If neither value1' nor value2' is NaN, the sign of the result */
2088                         /* is positive if both values have the same sign, negative if the */
2089                         /* values have different signs. */
2090
2091                         return a / b;
2092
2093                 } else {
2094                         if (isnanf(b)) {
2095                                 /* If either value1' or value2' is NaN, the result is NaN. */
2096
2097                                 return intBitsToFloat(FLT_NAN);
2098
2099                         } else {
2100                                 /* Division of a finite value by an infinity results in a */
2101                                 /* signed zero, with the sign-producing rule just given. */
2102
2103                                 /* is sign equal? */
2104
2105                                 if (copysignf(1.0, a) == copysignf(1.0, b))
2106                                         return 0.0;
2107                                 else
2108                                         return -0.0;
2109                         }
2110                 }
2111
2112         } else {
2113                 if (isnanf(a)) {
2114                         /* If either value1' or value2' is NaN, the result is NaN. */
2115
2116                         return intBitsToFloat(FLT_NAN);
2117
2118                 } else if (finitef(b)) {
2119                         /* Division of an infinity by a finite value results in a signed */
2120                         /* infinity, with the sign-producing rule just given. */
2121
2122                         /* is sign equal? */
2123
2124                         if (copysignf(1.0, a) == copysignf(1.0, b))
2125                                 return intBitsToFloat(FLT_POSINF);
2126                         else
2127                                 return intBitsToFloat(FLT_NEGINF);
2128
2129                 } else {
2130                         /* Division of an infinity by an infinity results in NaN. */
2131
2132                         return intBitsToFloat(FLT_NAN);
2133                 }
2134         }
2135 }
2136
2137
2138 float builtin_fneg(float a)
2139 {
2140         if (isnanf(a)) return a;
2141         else {
2142                 if (finitef(a)) return -a;
2143                 else return copysignf(a, -copysignf(1.0, a));
2144         }
2145 }
2146 #endif /* !SUPPORT_FLOAT */
2147
2148
2149 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2150 s4 builtin_fcmpl(float a, float b)
2151 {
2152         if (isnanf(a))
2153                 return -1;
2154
2155         if (isnanf(b))
2156                 return -1;
2157
2158         if (!finitef(a) || !finitef(b)) {
2159                 a = finitef(a) ? 0 : copysignf(1.0,     a);
2160                 b = finitef(b) ? 0 : copysignf(1.0, b);
2161         }
2162
2163         if (a > b)
2164                 return 1;
2165
2166         if (a == b)
2167                 return 0;
2168
2169         return -1;
2170 }
2171
2172
2173 s4 builtin_fcmpg(float a, float b)
2174 {
2175         if (isnanf(a)) return 1;
2176         if (isnanf(b)) return 1;
2177         if (!finitef(a) || !finitef(b)) {
2178                 a = finitef(a) ? 0 : copysignf(1.0, a);
2179                 b = finitef(b) ? 0 : copysignf(1.0, b);
2180         }
2181         if (a > b) return 1;
2182         if (a == b) return 0;
2183         return -1;
2184 }
2185 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2186
2187
2188 float builtin_frem(float a, float b)
2189 {
2190         return fmodf(a, b);
2191 }
2192
2193
2194 /* functions for unsupported double instructions ******************************/
2195
2196 #if !SUPPORT_DOUBLE
2197 double builtin_dadd(double a, double b)
2198 {
2199         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2200         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2201         if (finite(a)) {
2202                 if (finite(b)) return a + b;
2203                 else return b;
2204         }
2205         else {
2206                 if (finite(b)) return a;
2207                 else {
2208                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
2209                         else return longBitsToDouble(DBL_NAN);
2210                 }
2211         }
2212 }
2213
2214
2215 double builtin_dsub(double a, double b)
2216 {
2217         return builtin_dadd(a, builtin_dneg(b));
2218 }
2219
2220
2221 double builtin_dmul(double a, double b)
2222 {
2223         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2224         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2225         if (finite(a)) {
2226                 if (finite(b)) return a * b;
2227                 else {
2228                         if (a == 0) return longBitsToDouble(DBL_NAN);
2229                         else return copysign(b, copysign(1.0, b) * a);
2230                 }
2231         }
2232         else {
2233                 if (finite(b)) {
2234                         if (b == 0) return longBitsToDouble(DBL_NAN);
2235                         else return copysign(a, copysign(1.0, a) * b);
2236                 }
2237                 else {
2238                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2239                 }
2240         }
2241 }
2242
2243
2244 /* builtin_ddiv ****************************************************************
2245
2246    Implementation as described in VM Spec.
2247
2248 *******************************************************************************/
2249
2250 double builtin_ddiv(double a, double b)
2251 {
2252         if (finite(a)) {
2253                 if (finite(b)) {
2254                         /* If neither value1' nor value2' is NaN, the sign of the result */
2255                         /* is positive if both values have the same sign, negative if the */
2256                         /* values have different signs. */
2257
2258                         return a / b;
2259
2260                 } else {
2261                         if (isnan(b)) {
2262                                 /* If either value1' or value2' is NaN, the result is NaN. */
2263
2264                                 return longBitsToDouble(DBL_NAN);
2265
2266                         } else {
2267                                 /* Division of a finite value by an infinity results in a */
2268                                 /* signed zero, with the sign-producing rule just given. */
2269
2270                                 /* is sign equal? */
2271
2272                                 if (copysign(1.0, a) == copysign(1.0, b))
2273                                         return 0.0;
2274                                 else
2275                                         return -0.0;
2276                         }
2277                 }
2278
2279         } else {
2280                 if (isnan(a)) {
2281                         /* If either value1' or value2' is NaN, the result is NaN. */
2282
2283                         return longBitsToDouble(DBL_NAN);
2284
2285                 } else if (finite(b)) {
2286                         /* Division of an infinity by a finite value results in a signed */
2287                         /* infinity, with the sign-producing rule just given. */
2288
2289                         /* is sign equal? */
2290
2291                         if (copysign(1.0, a) == copysign(1.0, b))
2292                                 return longBitsToDouble(DBL_POSINF);
2293                         else
2294                                 return longBitsToDouble(DBL_NEGINF);
2295
2296                 } else {
2297                         /* Division of an infinity by an infinity results in NaN. */
2298
2299                         return longBitsToDouble(DBL_NAN);
2300                 }
2301         }
2302 }
2303
2304
2305 /* builtin_dneg ****************************************************************
2306
2307    Implemented as described in VM Spec.
2308
2309 *******************************************************************************/
2310
2311 double builtin_dneg(double a)
2312 {
2313         if (isnan(a)) {
2314                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2315                 /* sign). */
2316
2317                 return a;
2318
2319         } else {
2320                 if (finite(a)) {
2321                         /* If the operand is a zero, the result is the zero of opposite */
2322                         /* sign. */
2323
2324                         return -a;
2325
2326                 } else {
2327                         /* If the operand is an infinity, the result is the infinity of */
2328                         /* opposite sign. */
2329
2330                         return copysign(a, -copysign(1.0, a));
2331                 }
2332         }
2333 }
2334 #endif /* !SUPPORT_DOUBLE */
2335
2336
2337 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2338 s4 builtin_dcmpl(double a, double b)
2339 {
2340         if (isnan(a))
2341                 return -1;
2342
2343         if (isnan(b))
2344                 return -1;
2345
2346         if (!finite(a) || !finite(b)) {
2347                 a = finite(a) ? 0 : copysign(1.0, a);
2348                 b = finite(b) ? 0 : copysign(1.0, b);
2349         }
2350
2351         if (a > b)
2352                 return 1;
2353
2354         if (a == b)
2355                 return 0;
2356
2357         return -1;
2358 }
2359
2360
2361 s4 builtin_dcmpg(double a, double b)
2362 {
2363         if (isnan(a))
2364                 return 1;
2365
2366         if (isnan(b))
2367                 return 1;
2368
2369         if (!finite(a) || !finite(b)) {
2370                 a = finite(a) ? 0 : copysign(1.0, a);
2371                 b = finite(b) ? 0 : copysign(1.0, b);
2372         }
2373
2374         if (a > b)
2375                 return 1;
2376
2377         if (a == b)
2378                 return 0;
2379
2380         return -1;
2381 }
2382 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2383
2384
2385 double builtin_drem(double a, double b)
2386 {
2387         return fmod(a, b);
2388 }
2389
2390
2391 /* conversion operations ******************************************************/
2392
2393 #if 0
2394 s8 builtin_i2l(s4 i)
2395 {
2396 #if U8_AVAILABLE
2397         return i;
2398 #else
2399         s8 v;
2400         v.high = 0;
2401         v.low = i;
2402         return v;
2403 #endif
2404 }
2405
2406 s4 builtin_l2i(s8 l)
2407 {
2408 #if U8_AVAILABLE
2409         return (s4) l;
2410 #else
2411         return l.low;
2412 #endif
2413 }
2414 #endif
2415
2416
2417 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2418 float builtin_i2f(s4 a)
2419 {
2420         float f = (float) a;
2421         return f;
2422 }
2423 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2424
2425
2426 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2427 double builtin_i2d(s4 a)
2428 {
2429         double d = (double) a;
2430         return d;
2431 }
2432 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2433
2434
2435 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2436 float builtin_l2f(s8 a)
2437 {
2438 #if U8_AVAILABLE
2439         float f = (float) a;
2440         return f;
2441 #else
2442         return 0.0;
2443 #endif
2444 }
2445 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2446
2447
2448 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2449 double builtin_l2d(s8 a)
2450 {
2451 #if U8_AVAILABLE
2452         double d = (double) a;
2453         return d;
2454 #else
2455         return 0.0;
2456 #endif
2457 }
2458 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2459
2460
2461 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2462 s4 builtin_f2i(float a) 
2463 {
2464         s4 i;
2465
2466         i = builtin_d2i((double) a);
2467
2468         return i;
2469
2470         /*      float f;
2471         
2472                 if (isnanf(a))
2473                 return 0;
2474                 if (finitef(a)) {
2475                 if (a > 2147483647)
2476                 return 2147483647;
2477                 if (a < (-2147483648))
2478                 return (-2147483648);
2479                 return (s4) a;
2480                 }
2481                 f = copysignf((float) 1.0, a);
2482                 if (f > 0)
2483                 return 2147483647;
2484                 return (-2147483648); */
2485 }
2486 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2487
2488
2489 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2490 s8 builtin_f2l(float a)
2491 {
2492         s8 l;
2493
2494         l = builtin_d2l((double) a);
2495
2496         return l;
2497
2498         /*      float f;
2499         
2500                 if (finitef(a)) {
2501                 if (a > 9223372036854775807L)
2502                 return 9223372036854775807L;
2503                 if (a < (-9223372036854775808L))
2504                 return (-9223372036854775808L);
2505                 return (s8) a;
2506                 }
2507                 if (isnanf(a))
2508                 return 0;
2509                 f = copysignf((float) 1.0, a);
2510                 if (f > 0)
2511                 return 9223372036854775807L;
2512                 return (-9223372036854775808L); */
2513 }
2514 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2515
2516
2517 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2518 s4 builtin_d2i(double a) 
2519
2520         double d;
2521         
2522         if (finite(a)) {
2523                 if (a >= 2147483647)
2524                         return 2147483647;
2525                 if (a <= (-2147483647-1))
2526                         return (-2147483647-1);
2527                 return (s4) a;
2528         }
2529         if (isnan(a))
2530                 return 0;
2531         d = copysign(1.0, a);
2532         if (d > 0)
2533                 return 2147483647;
2534         return (-2147483647-1);
2535 }
2536 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2537
2538
2539 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2540 s8 builtin_d2l(double a)
2541 {
2542         double d;
2543         
2544         if (finite(a)) {
2545                 if (a >= 9223372036854775807LL)
2546                         return 9223372036854775807LL;
2547                 if (a <= (-9223372036854775807LL-1))
2548                         return (-9223372036854775807LL-1);
2549                 return (s8) a;
2550         }
2551         if (isnan(a))
2552                 return 0;
2553         d = copysign(1.0, a);
2554         if (d > 0)
2555                 return 9223372036854775807LL;
2556         return (-9223372036854775807LL-1);
2557 }
2558 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2559
2560
2561 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2562 double builtin_f2d(float a)
2563 {
2564         if (finitef(a)) return (double) a;
2565         else {
2566                 if (isnanf(a))
2567                         return longBitsToDouble(DBL_NAN);
2568                 else
2569                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2570         }
2571 }
2572
2573 float builtin_d2f(double a)
2574 {
2575         if (finite(a))
2576                 return (float) a;
2577         else {
2578                 if (isnan(a))
2579                         return intBitsToFloat(FLT_NAN);
2580                 else
2581                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2582         }
2583 }
2584 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2585
2586
2587 /* builtin_arraycopy ***********************************************************
2588
2589    Builtin for java.lang.System.arraycopy.
2590
2591    ATTENTION: This builtin function returns a boolean value to signal
2592    the ICMD_BUILTIN if there was an exception.
2593
2594 *******************************************************************************/
2595
2596 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2597                                            java_arrayheader *dest, s4 destStart, s4 len)
2598 {
2599         arraydescriptor *sdesc;
2600         arraydescriptor *ddesc;
2601         s4               i;
2602
2603         if ((src == NULL) || (dest == NULL)) { 
2604                 exceptions_throw_nullpointerexception();
2605                 return false;
2606         }
2607
2608         sdesc = src->objheader.vftbl->arraydesc;
2609         ddesc = dest->objheader.vftbl->arraydesc;
2610
2611         if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2612                 exceptions_throw_arraystoreexception();
2613                 return false;
2614         }
2615
2616         /* we try to throw exception with the same message as SUN does */
2617
2618         if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2619                 (srcStart  + len < 0) || (srcStart  + len > src->size) ||
2620                 (destStart + len < 0) || (destStart + len > dest->size)) {
2621                 exceptions_throw_arrayindexoutofboundsexception();
2622                 return false;
2623         }
2624
2625         if (sdesc->componentvftbl == ddesc->componentvftbl) {
2626                 /* We copy primitive values or references of exactly the same type */
2627
2628                 s4 dataoffset = sdesc->dataoffset;
2629                 s4 componentsize = sdesc->componentsize;
2630
2631                 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2632                                 ((u1 *) src)  + dataoffset + componentsize * srcStart,
2633                                 (size_t) len * componentsize);
2634         }
2635         else {
2636                 /* We copy references of different type */
2637
2638                 java_objectarray *oas = (java_objectarray *) src;
2639                 java_objectarray *oad = (java_objectarray *) dest;
2640                 
2641                 if (destStart <= srcStart) {
2642                         for (i = 0; i < len; i++) {
2643                                 java_objectheader *o = oas->data[srcStart + i];
2644
2645                                 if (!builtin_canstore(oad, o))
2646                                         return false;
2647
2648                                 oad->data[destStart + i] = o;
2649                         }
2650                 }
2651                 else {
2652                         /* XXX this does not completely obey the specification!
2653                            If an exception is thrown only the elements above the
2654                            current index have been copied. The specification
2655                            requires that only the elements *below* the current
2656                            index have been copied before the throw. */
2657
2658                         for (i = len - 1; i >= 0; i--) {
2659                                 java_objectheader *o = oas->data[srcStart + i];
2660
2661                                 if (!builtin_canstore(oad, o))
2662                                         return false;
2663
2664                                 oad->data[destStart + i] = o;
2665                         }
2666                 }
2667         }
2668
2669         return true;
2670 }
2671
2672
2673 /* builtin_currenttimemillis ***************************************************
2674
2675    Return the current time in milliseconds.
2676
2677 *******************************************************************************/
2678
2679 s8 builtin_currenttimemillis(void)
2680 {
2681         struct timeval tv;
2682         s8             result;
2683
2684         if (gettimeofday(&tv, NULL) == -1)
2685                 vm_abort("gettimeofday failed: %s", strerror(errno));
2686
2687         result = (s8) tv.tv_sec;
2688         result *= 1000;
2689         result += (tv.tv_usec / 1000);
2690
2691         return result;
2692 }
2693
2694
2695 /* builtin_clone ***************************************************************
2696
2697    Function for cloning objects or arrays.
2698
2699 *******************************************************************************/
2700
2701 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2702 {
2703         arraydescriptor   *ad;
2704         java_arrayheader  *ah;
2705         u4                 size;
2706         classinfo         *c;
2707         java_objectheader *co;              /* cloned object header               */
2708
2709         /* get the array descriptor */
2710
2711         ad = o->vftbl->arraydesc;
2712
2713         /* we are cloning an array */
2714
2715         if (ad != NULL) {
2716                 ah = (java_arrayheader *) o;
2717
2718                 size = ad->dataoffset + ad->componentsize * ah->size;
2719         
2720                 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2721
2722                 if (co == NULL)
2723                         return NULL;
2724
2725                 MCOPY(co, o, u1, size);
2726
2727 #if defined(ENABLE_GC_CACAO)
2728                 heap_init_objectheader(co, size);
2729 #endif
2730
2731 #if defined(ENABLE_THREADS)
2732                 lock_init_object_lock(co);
2733 #endif
2734
2735                 return co;
2736         }
2737     
2738     /* we are cloning a non-array */
2739
2740     if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2741         exceptions_throw_clonenotsupportedexception();
2742         return NULL;
2743     }
2744
2745         /* get the class of the object */
2746
2747     c = o->vftbl->class;
2748
2749         /* create new object */
2750
2751     co = builtin_new(c);
2752
2753     if (co == NULL)
2754         return NULL;
2755
2756     MCOPY(co, o, u1, c->instancesize);
2757
2758 #if defined(ENABLE_GC_CACAO)
2759         heap_init_objectheader(co, c->instancesize);
2760 #endif
2761
2762 #if defined(ENABLE_THREADS)
2763         lock_init_object_lock(co);
2764 #endif
2765
2766     return co;
2767 }
2768
2769 #if defined(ENABLE_VMLOG)
2770 #define NDEBUG
2771 #include <vmlog_cacao.c>
2772 #endif
2773
2774
2775 /*
2776  * These are local overrides for various environment variables in Emacs.
2777  * Please do not remove this and leave it at the end of the file, where
2778  * Emacs will automagically detect them.
2779  * ---------------------------------------------------------------------
2780  * Local variables:
2781  * mode: c
2782  * indent-tabs-mode: t
2783  * c-basic-offset: 4
2784  * tab-width: 4
2785  * End:
2786  * vim:noexpandtab:sw=4:ts=4:
2787  */