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