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