75a55f6bce360f3c288bb63fd83c6be655a64d25
[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 7483 2007-03-08 13:17:40Z michi $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39 #include <errno.h>
40 #include <math.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/time.h>
44
45 #include "vm/types.h"
46
47 #include "arch.h"
48 #include "md-abi.h"
49
50 #include "fdlibm/fdlibm.h"
51 #if defined(__CYGWIN__) && defined(Bias)
52 # undef Bias
53 #endif
54
55 #include "mm/gc-common.h"
56 #include "mm/memory.h"
57
58 #include "native/jni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
61
62 #if defined(ENABLE_THREADS)
63 # include "threads/native/lock.h"
64 #endif
65
66 #include "toolbox/logging.h"
67 #include "toolbox/util.h"
68
69 #include "vm/builtin.h"
70 #include "vm/cycles-stats.h"
71 #include "vm/exceptions.h"
72 #include "vm/global.h"
73 #include "vm/initialize.h"
74 #include "vm/stringlocal.h"
75
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/patcher.h"
78
79 #include "vmcore/class.h"
80 #include "vmcore/loader.h"
81 #include "vmcore/options.h"
82 #include "vmcore/rt-timing.h"
83
84
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
374
375 /*************** internal function: builtin_isanysubclass *********************
376
377         Checks a subclass relation between two classes. Implemented interfaces
378         are interpreted as super classes.
379         Return value:  1 ... sub is subclass of super
380                                    0 ... otherwise
381
382 ******************************************************************************/
383
384 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
385 {
386         s4 res;
387         castinfo classvalues;
388
389         if (sub == super)
390                 return 1;
391
392         if (super->flags & ACC_INTERFACE) {
393                 res = (sub->vftbl->interfacetablelength > super->index) &&
394                         (sub->vftbl->interfacetable[-super->index] != NULL);
395
396         } else {
397                 /* java.lang.Object is the only super_class_ of any interface */
398                 if (sub->flags & ACC_INTERFACE)
399                         return (super == class_java_lang_Object);
400
401                 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
402
403                 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
404                         (u4) classvalues.super_diffval;
405         }
406
407         return res;
408 }
409
410
411 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
412 {
413         s4 res;
414         s4 base;
415         castinfo classvalues;
416
417         if (sub == super)
418                 return 1;
419
420         ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
421
422         if ((base = classvalues.super_baseval) <= 0) {
423                 /* super is an interface */
424                 res = (sub->interfacetablelength > -base) &&
425                         (sub->interfacetable[base] != NULL);
426         } 
427         else {
428                 /* java.lang.Object is the only super_class_ of any interface */
429                 if (classvalues.sub_baseval <= 0)
430                         return classvalues.super_baseval == 1;
431
432             res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
433                         <= (u4) classvalues.super_diffval;
434         }
435
436         return res;
437 }
438
439
440 /****************** function: builtin_instanceof *****************************
441
442         Checks if an object is an instance of some given class (or subclass of
443         that class). If class is an interface, checks if the interface is
444         implemented.
445         Return value:  1 ... obj is an instance of class or implements the interface
446                                    0 ... otherwise or if obj == NULL
447                          
448 *****************************************************************************/
449
450 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
451 {
452         if (!obj)
453                 return 0;
454
455         return builtin_isanysubclass(obj->vftbl->class, class);
456 }
457
458
459
460 /**************** function: builtin_checkcast *******************************
461
462         The same as builtin_instanceof except that 1 is returned when
463         obj == NULL
464                           
465 ****************************************************************************/
466
467 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
468 {
469         if (obj == NULL)
470                 return 1;
471
472         if (builtin_isanysubclass(obj->vftbl->class, class))
473                 return 1;
474
475         return 0;
476 }
477
478
479 /* builtin_descriptorscompatible ***********************************************
480
481    Checks if two array type descriptors are assignment compatible
482
483    Return value: 1 ... target = desc is possible
484                  0 ... otherwise
485                         
486 *******************************************************************************/
487
488 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
489                                                                                 arraydescriptor *target)
490 {
491         if (desc == target)
492                 return 1;
493
494         if (desc->arraytype != target->arraytype)
495                 return 0;
496
497         if (desc->arraytype != ARRAYTYPE_OBJECT)
498                 return 1;
499         
500         /* {both arrays are arrays of references} */
501
502         if (desc->dimension == target->dimension) {
503                 /* an array which contains elements of interface types is
504            allowed to be casted to Object (JOWENN)*/
505
506                 if ((desc->elementvftbl->baseval < 0) &&
507                         (target->elementvftbl->baseval == 1))
508                         return 1;
509
510                 return builtin_isanysubclass_vftbl(desc->elementvftbl,
511                                                                                    target->elementvftbl);
512         }
513
514         if (desc->dimension < target->dimension)
515                 return 0;
516
517         /* {desc has higher dimension than target} */
518
519         return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
520                                                                            target->elementvftbl);
521 }
522
523
524 /* builtin_arraycheckcast ******************************************************
525
526    Checks if an object is really a subtype of the requested array
527    type.  The object has to be an array to begin with. For simple
528    arrays (int, short, double, etc.) the types have to match exactly.
529    For arrays of objects, the type of elements in the array has to be
530    a subtype (or the same type) of the requested element type. For
531    arrays of arrays (which in turn can again be arrays of arrays), the
532    types at the lowest level have to satisfy the corresponding sub
533    class relation.
534         
535 *******************************************************************************/
536
537 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
538 {
539         arraydescriptor *desc;
540
541         if (!o)
542                 return 1;
543
544         if ((desc = o->vftbl->arraydesc) == NULL)
545                 return 0;
546  
547         return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
548 }
549
550
551 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
552 {
553         if (!o)
554                 return 0;
555
556         return builtin_arraycheckcast(o, targetclass);
557 }
558
559
560 /* builtin_throw_exception *****************************************************
561
562    Sets the exceptionptr with the thrown exception and prints some
563    debugging information.  Called from asm_vm_call_method.
564
565 *******************************************************************************/
566
567 void *builtin_throw_exception(java_objectheader *xptr)
568 {
569 #if !defined(NDEBUG)
570     java_lang_Throwable *t;
571         char                *logtext;
572         s4                   logtextlen;
573         s4                   dumpsize;
574
575         if (opt_verbose) {
576                 t = (java_lang_Throwable *) xptr;
577
578                 /* calculate message length */
579
580                 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
581
582                 if (t) {
583                         logtextlen +=
584                                 utf_bytes(xptr->vftbl->class->name);
585                         if (t->detailMessage) {
586                                 logtextlen += strlen(": ") +
587                                         u2_utflength(t->detailMessage->value->data 
588                                                                         + t->detailMessage->offset,
589                                                          t->detailMessage->count);
590                         }
591                 } 
592                 else {
593                         logtextlen += strlen("(nil)");
594                 }
595
596                 /* allocate memory */
597
598                 dumpsize = dump_size();
599
600                 logtext = DMNEW(char, logtextlen);
601
602                 strcpy(logtext, "Builtin exception thrown: ");
603
604                 if (t) {
605                         utf_cat_classname(logtext, xptr->vftbl->class->name);
606
607                         if (t->detailMessage) {
608                                 char *buf;
609
610                                 buf = javastring_tochar((java_objectheader *) t->detailMessage);
611                                 strcat(logtext, ": ");
612                                 strcat(logtext, buf);
613                                 MFREE(buf, char, strlen(buf) + 1);
614                         }
615
616                 } else {
617                         strcat(logtext, "(nil)");
618                 }
619
620                 log_text(logtext);
621
622                 /* release memory */
623
624                 dump_release(dumpsize);
625         }
626 #endif /* !defined(NDEBUG) */
627
628         /* actually set the exception */
629
630         exceptions_set_exception(xptr);
631
632         /* Return a NULL pointer.  This is required for vm_call_method to
633            check for an exception.  This is for convenience. */
634
635         return NULL;
636 }
637
638
639 /* builtin_canstore ************************************************************
640
641    Checks, if an object can be stored in an array.
642
643    Return value: 1 ... possible
644                  0 ... otherwise
645
646 *******************************************************************************/
647
648 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
649 {
650         arraydescriptor *desc;
651         arraydescriptor *valuedesc;
652         vftbl_t         *componentvftbl;
653         vftbl_t         *valuevftbl;
654         s4               base;
655         castinfo         classvalues;
656
657         if (!o)
658                 return 1;
659
660         /* The following is guaranteed (by verifier checks):
661          *
662          *     *) oa->...vftbl->arraydesc != NULL
663          *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
664          *     *) o->vftbl is not an interface vftbl
665          */
666         
667         desc           = oa->header.objheader.vftbl->arraydesc;
668         componentvftbl = desc->componentvftbl;
669         valuevftbl     = o->vftbl;
670
671         if ((desc->dimension - 1) == 0) {
672                 s4 res;
673
674                 /* {oa is a one-dimensional array} */
675                 /* {oa is an array of references} */
676                 
677                 if (valuevftbl == componentvftbl)
678                         return 1;
679
680                 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
681
682                 if ((base = classvalues.super_baseval) <= 0)
683                         /* an array of interface references */
684                         return (valuevftbl->interfacetablelength > -base &&
685                                         valuevftbl->interfacetable[base] != NULL);
686                 
687                 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
688                            <= (unsigned) classvalues.super_diffval);
689
690                 return res;
691         }
692
693         /* {oa has dimension > 1} */
694         /* {componentvftbl->arraydesc != NULL} */
695
696         /* check if o is an array */
697
698         if ((valuedesc = valuevftbl->arraydesc) == NULL)
699                 return 0;
700
701         /* {o is an array} */
702
703         return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
704 }
705
706
707 /* This is an optimized version where a is guaranteed to be one-dimensional */
708 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
709 {
710         arraydescriptor *desc;
711         vftbl_t *elementvftbl;
712         vftbl_t *valuevftbl;
713         s4 res;
714         int base;
715         castinfo classvalues;
716         
717         if (!o) return 1;
718
719         /* The following is guaranteed (by verifier checks):
720          *
721          *     *) a->...vftbl->arraydesc != NULL
722          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
723          *     *) a->...vftbl->arraydesc->dimension == 1
724          *     *) o->vftbl is not an interface vftbl
725          */
726
727         desc = a->header.objheader.vftbl->arraydesc;
728     elementvftbl = desc->elementvftbl;
729         valuevftbl = o->vftbl;
730
731         /* {a is a one-dimensional array} */
732         
733         if (valuevftbl == elementvftbl)
734                 return 1;
735
736         ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
737
738         if ((base = classvalues.super_baseval) <= 0)
739                 /* an array of interface references */
740                 return (valuevftbl->interfacetablelength > -base &&
741                                 valuevftbl->interfacetable[base] != NULL);
742
743         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
744                 <= (unsigned) classvalues.super_diffval;
745
746         return res;
747 }
748
749
750 /* This is an optimized version where a is guaranteed to be a
751  * one-dimensional array of a class type */
752 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
753 {
754         vftbl_t *elementvftbl;
755         vftbl_t *valuevftbl;
756         s4 res;
757         castinfo classvalues;
758         
759         if (!o) return 1;
760
761         /* The following is guaranteed (by verifier checks):
762          *
763          *     *) a->...vftbl->arraydesc != NULL
764          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
765          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
766          *     *) a->...vftbl->arraydesc->dimension == 1
767          *     *) o->vftbl is not an interface vftbl
768          */
769
770     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
771         valuevftbl = o->vftbl;
772
773         /* {a is a one-dimensional array} */
774         
775         if (valuevftbl == elementvftbl)
776                 return 1;
777
778         ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
779
780         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
781                 <= (unsigned) classvalues.super_diffval;
782
783         return res;
784 }
785
786
787 /* builtin_new *****************************************************************
788
789    Creates a new instance of class c on the heap.
790
791    Return value: pointer to the object or NULL if no memory is
792    available
793                         
794 *******************************************************************************/
795
796 java_objectheader *builtin_new(classinfo *c)
797 {
798         java_objectheader *o;
799 #if defined(ENABLE_RT_TIMING)
800         struct timespec time_start, time_end;
801 #endif
802 #if defined(ENABLE_CYCLES_STATS)
803         u8 cycles_start, cycles_end;
804 #endif
805
806         RT_TIMING_GET_TIME(time_start);
807         CYCLES_STATS_GET(cycles_start);
808
809         /* is the class loaded */
810
811         assert(c->state & CLASS_LOADED);
812
813         /* check if we can instantiate this class */
814
815         if (c->flags & ACC_ABSTRACT) {
816                 exceptions_throw_instantiationerror(c);
817                 return NULL;
818         }
819
820         /* is the class linked */
821
822         if (!(c->state & CLASS_LINKED))
823                 if (!link_class(c))
824                         return NULL;
825
826         if (!(c->state & CLASS_INITIALIZED)) {
827 #if !defined(NDEBUG)
828                 if (initverbose)
829                         log_message_class("Initialize class (from builtin_new): ", c);
830 #endif
831
832                 if (!initialize_class(c))
833                         return NULL;
834         }
835
836         o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
837                                           c->finalizer);
838
839         if (!o)
840                 return NULL;
841
842         o->vftbl = c->vftbl;
843
844 #if defined(ENABLE_THREADS)
845         lock_init_object_lock(o);
846 #endif
847
848         CYCLES_STATS_GET(cycles_end);
849         RT_TIMING_GET_TIME(time_end);
850
851         CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
852         RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
853
854         return o;
855 }
856
857
858 /* builtin_newarray ************************************************************
859
860    Creates an array with the given vftbl on the heap. This function
861    takes as class argument an array class.
862
863    Return value: pointer to the array or NULL if no memory is available
864
865 *******************************************************************************/
866
867 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
868 {
869         arraydescriptor  *desc;
870         s4                dataoffset;
871         s4                componentsize;
872         s4                actualsize;
873         java_arrayheader *a;
874 #if defined(ENABLE_RT_TIMING)
875         struct timespec time_start, time_end;
876 #endif
877
878         RT_TIMING_GET_TIME(time_start);
879
880         desc          = arrayclass->vftbl->arraydesc;
881         dataoffset    = desc->dataoffset;
882         componentsize = desc->componentsize;
883
884         if (size < 0) {
885                 exceptions_throw_negativearraysizeexception();
886                 return NULL;
887         }
888
889         actualsize = dataoffset + size * componentsize;
890
891         /* check for overflow */
892
893         if (((u4) actualsize) < ((u4) size)) {
894                 exceptions_throw_outofmemoryerror();
895                 return NULL;
896         }
897
898         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
899
900         if (a == NULL)
901                 return NULL;
902
903         a->objheader.vftbl = arrayclass->vftbl;
904
905 #if defined(ENABLE_THREADS)
906         lock_init_object_lock(&a->objheader);
907 #endif
908
909         a->size = size;
910
911         RT_TIMING_GET_TIME(time_end);
912         RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
913
914         return a;
915 }
916
917
918 /* builtin_anewarray ***********************************************************
919
920    Creates an array of references to the given class type on the heap.
921
922    Return value: pointer to the array or NULL if no memory is
923    available
924
925 *******************************************************************************/
926
927 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
928 {
929         classinfo *arrayclass;
930         
931         /* is class loaded */
932
933         assert(componentclass->state & CLASS_LOADED);
934
935         /* is class linked */
936
937         if (!(componentclass->state & CLASS_LINKED))
938                 if (!link_class(componentclass))
939                         return NULL;
940
941         arrayclass = class_array_of(componentclass, true);
942
943         if (!arrayclass)
944                 return NULL;
945
946         return (java_objectarray *) builtin_newarray(size, arrayclass);
947 }
948
949
950 /* builtin_newarray_boolean ****************************************************
951
952    Creates an array of bytes on the heap. The array is designated as
953    an array of booleans (important for casts)
954         
955    Return value: pointer to the array or NULL if no memory is
956    available
957
958 *******************************************************************************/
959
960 java_booleanarray *builtin_newarray_boolean(s4 size)
961 {
962         return (java_booleanarray *)
963                 builtin_newarray(size,
964                                                  primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
965 }
966
967
968 /* builtin_newarray_byte *******************************************************
969
970    Creates an array of 8 bit Integers on the heap.
971
972    Return value: pointer to the array or NULL if no memory is
973    available
974
975 *******************************************************************************/
976
977 java_bytearray *builtin_newarray_byte(s4 size)
978 {
979         return (java_bytearray *)
980                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
981 }
982
983
984 /* builtin_newarray_char *******************************************************
985
986    Creates an array of characters on the heap.
987
988    Return value: pointer to the array or NULL if no memory is
989    available
990
991 *******************************************************************************/
992
993 java_chararray *builtin_newarray_char(s4 size)
994 {
995         return (java_chararray *)
996                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
997 }
998
999
1000 /* builtin_newarray_short ******************************************************
1001
1002    Creates an array of 16 bit Integers on the heap.
1003
1004    Return value: pointer to the array or NULL if no memory is
1005    available
1006
1007 *******************************************************************************/
1008
1009 java_shortarray *builtin_newarray_short(s4 size)
1010 {
1011         return (java_shortarray *)
1012                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1013 }
1014
1015
1016 /* builtin_newarray_int ********************************************************
1017
1018    Creates an array of 32 bit Integers on the heap.
1019
1020    Return value: pointer to the array or NULL if no memory is
1021    available
1022
1023 *******************************************************************************/
1024
1025 java_intarray *builtin_newarray_int(s4 size)
1026 {
1027         return (java_intarray *)
1028                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1029 }
1030
1031
1032 /* builtin_newarray_long *******************************************************
1033
1034    Creates an array of 64 bit Integers on the heap.
1035
1036    Return value: pointer to the array or NULL if no memory is
1037    available
1038
1039 *******************************************************************************/
1040
1041 java_longarray *builtin_newarray_long(s4 size)
1042 {
1043         return (java_longarray *)
1044                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1045 }
1046
1047
1048 /* builtin_newarray_float ******************************************************
1049
1050    Creates an array of 32 bit IEEE floats on the heap.
1051
1052    Return value: pointer to the array or NULL if no memory is
1053    available
1054
1055 *******************************************************************************/
1056
1057 java_floatarray *builtin_newarray_float(s4 size)
1058 {
1059         return (java_floatarray *)
1060                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1061 }
1062
1063
1064 /* builtin_newarray_double *****************************************************
1065
1066    Creates an array of 64 bit IEEE floats on the heap.
1067
1068    Return value: pointer to the array or NULL if no memory is
1069    available
1070
1071 *******************************************************************************/
1072
1073 java_doublearray *builtin_newarray_double(s4 size)
1074 {
1075         return (java_doublearray *)
1076                 builtin_newarray(size,
1077                                                  primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1078 }
1079
1080
1081 /* builtin_multianewarray_intern ***********************************************
1082
1083    Creates a multi-dimensional array on the heap. The dimensions are
1084    passed in an array of longs.
1085
1086    Arguments:
1087        n............number of dimensions to create
1088        arrayvftbl...vftbl of the array class
1089        dims.........array containing the size of each dimension to create
1090
1091    Return value: pointer to the array or NULL if no memory is
1092    available
1093
1094 ******************************************************************************/
1095
1096 static java_arrayheader *builtin_multianewarray_intern(int n,
1097                                                                                                            classinfo *arrayclass,
1098                                                                                                            long *dims)
1099 {
1100         s4                size;
1101         java_arrayheader *a;
1102         classinfo        *componentclass;
1103         s4                i;
1104
1105         /* create this dimension */
1106
1107         size = (s4) dims[0];
1108         a = builtin_newarray(size, arrayclass);
1109
1110         if (!a)
1111                 return NULL;
1112
1113         /* if this is the last dimension return */
1114
1115         if (!--n)
1116                 return a;
1117
1118         /* get the class of the components to create */
1119
1120         componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1121
1122         /* The verifier guarantees that the dimension count is in the range. */
1123
1124         /* create the component arrays */
1125
1126         for (i = 0; i < size; i++) {
1127                 java_arrayheader *ea =
1128 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1129                         /* we save an s4 to a s8 slot, 8-byte aligned */
1130
1131                         builtin_multianewarray_intern(n, componentclass, dims + 2);
1132 #else
1133                         builtin_multianewarray_intern(n, componentclass, dims + 1);
1134 #endif
1135
1136                 if (!ea)
1137                         return NULL;
1138                 
1139                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1140         }
1141
1142         return a;
1143 }
1144
1145
1146 /* builtin_multianewarray ******************************************************
1147
1148    Wrapper for builtin_multianewarray_intern which checks all
1149    dimensions before we start allocating.
1150
1151 ******************************************************************************/
1152
1153 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1154                                                                                  long *dims)
1155 {
1156         s4 i;
1157         s4 size;
1158
1159         /* check all dimensions before doing anything */
1160
1161         for (i = 0; i < n; i++) {
1162 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1163                 /* we save an s4 to a s8 slot, 8-byte aligned */
1164                 size = (s4) dims[i * 2];
1165 #else
1166                 size = (s4) dims[i];
1167 #endif
1168
1169                 if (size < 0) {
1170                         exceptions_throw_negativearraysizeexception();
1171                         return NULL;
1172                 }
1173         }
1174
1175         /* now call the real function */
1176
1177         return builtin_multianewarray_intern(n, arrayclass, dims);
1178 }
1179
1180
1181 /*****************************************************************************
1182                                           METHOD LOGGING
1183
1184         Various functions for printing a message at method entry or exit (for
1185         debugging)
1186         
1187 *****************************************************************************/
1188
1189 #if !defined(NDEBUG)
1190 static s4 methodindent = 0;
1191 static u4 callcount = 0;
1192
1193 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1194                                                                                    methodinfo *m,
1195                                                                                    void *pos,
1196                                                                                    s4 indent)
1197 {
1198         char *logtext;
1199         s4    logtextlen;
1200         s4    dumpsize;
1201         codeinfo *code;
1202
1203         if (opt_verbosecall && indent)
1204                 methodindent--;
1205
1206         /* calculate message length */
1207
1208         if (xptr) {
1209                 logtextlen =
1210                         strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1211         } 
1212         else {
1213                 logtextlen = strlen("Some Throwable");
1214         }
1215
1216         logtextlen += strlen(" thrown in ");
1217
1218         if (m) {
1219                 logtextlen +=
1220                         utf_bytes(m->class->name) +
1221                         strlen(".") +
1222                         utf_bytes(m->name) +
1223                         utf_bytes(m->descriptor) +
1224                         strlen("(NOSYNC,NATIVE");
1225
1226 #if SIZEOF_VOID_P == 8
1227                 logtextlen +=
1228                         strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1229 #else
1230                 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1231 #endif
1232
1233                 if (m->class->sourcefile == NULL)
1234                         logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1235                 else
1236                         logtextlen += utf_bytes(m->class->sourcefile);
1237
1238                 logtextlen += strlen(":65536)");
1239
1240         } 
1241         else {
1242                 logtextlen += strlen("call_java_method");
1243         }
1244
1245         logtextlen += strlen("0");
1246
1247         /* allocate memory */
1248
1249         dumpsize = dump_size();
1250
1251         logtext = DMNEW(char, logtextlen);
1252
1253         if (xptr) {
1254                 strcpy(logtext, "Exception ");
1255                 utf_cat_classname(logtext, xptr->vftbl->class->name);
1256
1257         } else {
1258                 strcpy(logtext, "Some Throwable");
1259         }
1260
1261         strcat(logtext, " thrown in ");
1262
1263         if (m) {
1264                 utf_cat_classname(logtext, m->class->name);
1265                 strcat(logtext, ".");
1266                 utf_cat(logtext, m->name);
1267                 utf_cat(logtext, m->descriptor);
1268
1269                 if (m->flags & ACC_SYNCHRONIZED)
1270                         strcat(logtext, "(SYNC");
1271                 else
1272                         strcat(logtext, "(NOSYNC");
1273
1274                 if (m->flags & ACC_NATIVE) {
1275                         strcat(logtext, ",NATIVE");
1276
1277                         code = m->code;
1278
1279 #if SIZEOF_VOID_P == 8
1280                         sprintf(logtext + strlen(logtext),
1281                                         ")(0x%016lx) at position 0x%016lx",
1282                                         (ptrint) code->entrypoint, (ptrint) pos);
1283 #else
1284                         sprintf(logtext + strlen(logtext),
1285                                         ")(0x%08x) at position 0x%08x",
1286                                         (ptrint) code->entrypoint, (ptrint) pos);
1287 #endif
1288
1289                 } else {
1290
1291                         /* XXX preliminary: This should get the actual codeinfo */
1292                         /* in which the exception happened.                     */
1293                         code = m->code;
1294                         
1295 #if SIZEOF_VOID_P == 8
1296                         sprintf(logtext + strlen(logtext),
1297                                         ")(0x%016lx) at position 0x%016lx (",
1298                                         (ptrint) code->entrypoint, (ptrint) pos);
1299 #else
1300                         sprintf(logtext + strlen(logtext),
1301                                         ")(0x%08x) at position 0x%08x (",
1302                                         (ptrint) code->entrypoint, (ptrint) pos);
1303 #endif
1304
1305                         if (m->class->sourcefile == NULL)
1306                                 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1307                         else
1308                                 utf_cat(logtext, m->class->sourcefile);
1309
1310                         sprintf(logtext + strlen(logtext), ":%d)", 0);
1311                 }
1312
1313         } else
1314                 strcat(logtext, "call_java_method");
1315
1316         log_text(logtext);
1317
1318         /* release memory */
1319
1320         dump_release(dumpsize);
1321
1322         return xptr;
1323 }
1324 #endif /* !defined(NDEBUG) */
1325
1326
1327 /* builtin_print_argument ******************************************************
1328
1329    Prints arguments and return values for the call trace.
1330
1331 *******************************************************************************/
1332
1333 #if !defined(NDEBUG)
1334 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1335                                                                         typedesc *paramtype, s8 value)
1336 {
1337         imm_union          imu;
1338         java_objectheader *o;
1339         java_lang_String  *s;
1340         classinfo         *c;
1341         utf               *u;
1342         u4                 len;
1343
1344         switch (paramtype->type) {
1345         case TYPE_INT:
1346                 imu.i = (s4) value;
1347                 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1348                 break;
1349
1350         case TYPE_LNG:
1351                 imu.l = value;
1352 #if SIZEOF_VOID_P == 4
1353                 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1354 #else
1355                 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1356 #endif
1357                 break;
1358
1359         case TYPE_FLT:
1360                 imu.i = (s4) value;
1361                 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1362                 break;
1363
1364         case TYPE_DBL:
1365                 imu.l = value;
1366 #if SIZEOF_VOID_P == 4
1367                 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1368 #else
1369                 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1370 #endif
1371                 break;
1372
1373         case TYPE_ADR:
1374 #if SIZEOF_VOID_P == 4
1375                 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1376 #else
1377                 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1378 #endif
1379
1380                 /* cast to java.lang.Object */
1381
1382                 o = (java_objectheader *) (ptrint) value;
1383
1384                 /* check return argument for java.lang.Class or java.lang.String */
1385
1386                 if (o != NULL) {
1387                         if (o->vftbl->class == class_java_lang_String) {
1388                                 /* get java.lang.String object and the length of the
1389                                    string */
1390
1391                                 s = (java_lang_String *) o;
1392
1393                                 u = javastring_toutf(s, false);
1394
1395                                 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1396
1397                                 /* realloc memory for string length */
1398
1399                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1400                                 *logtextlen += len;
1401
1402                                 /* convert to utf8 string and strcat it to the logtext */
1403
1404                                 strcat(logtext, " (String = \"");
1405                                 utf_cat(logtext, u);
1406                                 strcat(logtext, "\")");
1407                         }
1408                         else {
1409                                 if (o->vftbl->class == class_java_lang_Class) {
1410                                         /* if the object returned is a java.lang.Class
1411                                            cast it to classinfo structure and get the name
1412                                            of the class */
1413
1414                                         c = (classinfo *) o;
1415
1416                                         u = c->name;
1417                                 }
1418                                 else {
1419                                         /* if the object returned is not a java.lang.String or
1420                                            a java.lang.Class just print the name of the class */
1421
1422                                         u = o->vftbl->class->name;
1423                                 }
1424
1425                                 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1426
1427                                 /* realloc memory for string length */
1428
1429                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1430                                 *logtextlen += len;
1431
1432                                 /* strcat to the logtext */
1433
1434                                 strcat(logtext, " (Class = \"");
1435                                 utf_cat_classname(logtext, u);
1436                                 strcat(logtext, "\")");
1437                         }
1438                 }
1439         }
1440
1441         return logtext;
1442 }
1443 #endif /* !defined(NDEBUG) */
1444
1445
1446 /* builtin_verbosecall_enter ***************************************************
1447
1448    Print method call with arguments for -verbose:call.
1449
1450 *******************************************************************************/
1451
1452 #if !defined(NDEBUG)
1453
1454 #ifdef TRACE_ARGS_NUM
1455 void builtin_verbosecall_enter(s8 a0, s8 a1,
1456 # if TRACE_ARGS_NUM >= 4
1457                                                            s8 a2, s8 a3,
1458 # endif
1459 # if TRACE_ARGS_NUM >= 6
1460                                                            s8 a4, s8 a5,
1461 # endif
1462 # if TRACE_ARGS_NUM == 8
1463                                                            s8 a6, s8 a7,
1464 # endif
1465                                                            methodinfo *m)
1466 {
1467         methoddesc *md;
1468         char       *logtext;
1469         s4          logtextlen;
1470         s4          dumpsize;
1471         s4          i;
1472         s4          pos;
1473
1474         md = m->parseddesc;
1475
1476         /* calculate message length */
1477
1478         logtextlen =
1479                 strlen("4294967295 ") +
1480                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1481                 methodindent +
1482                 strlen("called: ") +
1483                 utf_bytes(m->class->name) +
1484                 strlen(".") +
1485                 utf_bytes(m->name) +
1486                 utf_bytes(m->descriptor);
1487
1488         /* Actually it's not possible to have all flags printed, but:
1489            safety first! */
1490
1491         logtextlen +=
1492                 strlen(" PUBLIC") +
1493                 strlen(" PRIVATE") +
1494                 strlen(" PROTECTED") +
1495                 strlen(" STATIC") +
1496                 strlen(" FINAL") +
1497                 strlen(" SYNCHRONIZED") +
1498                 strlen(" VOLATILE") +
1499                 strlen(" TRANSIENT") +
1500                 strlen(" NATIVE") +
1501                 strlen(" INTERFACE") +
1502                 strlen(" ABSTRACT");
1503
1504         /* add maximal argument length */
1505
1506         logtextlen +=
1507                 strlen("(") +
1508                 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1509                 strlen("...(255)") +
1510                 strlen(")");
1511
1512         /* allocate memory */
1513
1514         dumpsize = dump_size();
1515
1516         logtext = DMNEW(char, logtextlen);
1517
1518         callcount++;
1519
1520         sprintf(logtext, "%10d ", callcount);
1521         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1522
1523         pos = strlen(logtext);
1524
1525         for (i = 0; i < methodindent; i++)
1526                 logtext[pos++] = '\t';
1527
1528         strcpy(logtext + pos, "called: ");
1529
1530         utf_cat_classname(logtext, m->class->name);
1531         strcat(logtext, ".");
1532         utf_cat(logtext, m->name);
1533         utf_cat(logtext, m->descriptor);
1534
1535         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1536         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1537         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1538         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1539         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1540         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1541         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1542         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1543         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1544         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1545         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1546
1547         strcat(logtext, "(");
1548
1549         if (md->paramcount >= 1) {
1550                 logtext = builtin_print_argument(logtext, &logtextlen,
1551                                                                                  &md->paramtypes[0], a0);
1552         }
1553
1554         if (md->paramcount >= 2) {
1555                 strcat(logtext, ", ");
1556
1557                 logtext = builtin_print_argument(logtext, &logtextlen,
1558                                                                                  &md->paramtypes[1], a1);
1559         }
1560
1561 #if TRACE_ARGS_NUM >= 4
1562         if (md->paramcount >= 3) {
1563                 strcat(logtext, ", ");
1564
1565                 logtext = builtin_print_argument(logtext, &logtextlen,
1566                                                                                  &md->paramtypes[2], a2);
1567         }
1568
1569         if (md->paramcount >= 4) {
1570                 strcat(logtext, ", ");
1571
1572                 logtext = builtin_print_argument(logtext, &logtextlen,
1573                                                                                  &md->paramtypes[3], a3);
1574         }
1575 #endif
1576
1577 #if TRACE_ARGS_NUM >= 6
1578         if (md->paramcount >= 5) {
1579                 strcat(logtext, ", ");
1580
1581                 logtext = builtin_print_argument(logtext, &logtextlen,
1582                                                                                  &md->paramtypes[4], a4);
1583         }
1584
1585         if (md->paramcount >= 6) {
1586                 strcat(logtext, ", ");
1587
1588                 logtext = builtin_print_argument(logtext, &logtextlen,
1589                                                                                  &md->paramtypes[5], a5);
1590         }
1591 #endif
1592
1593 #if TRACE_ARGS_NUM == 8
1594         if (md->paramcount >= 7) {
1595                 strcat(logtext, ", ");
1596
1597                 logtext = builtin_print_argument(logtext, &logtextlen,
1598                                                                                  &md->paramtypes[6], a6);
1599         }
1600
1601         if (md->paramcount >= 8) {
1602                 strcat(logtext, ", ");
1603
1604                 logtext = builtin_print_argument(logtext, &logtextlen,
1605                                                                                  &md->paramtypes[7], a7);
1606         }
1607 #endif
1608
1609         if (md->paramcount > 8) {
1610                 sprintf(logtext + strlen(logtext), ", ...(%d)",
1611                                 md->paramcount - TRACE_ARGS_NUM);
1612         }
1613
1614         strcat(logtext, ")");
1615
1616         log_text(logtext);
1617
1618         /* release memory */
1619
1620         dump_release(dumpsize);
1621
1622         methodindent++;
1623 }
1624 #endif
1625 #endif /* !defined(NDEBUG) */
1626
1627
1628 /* builtin_verbosecall_exit ****************************************************
1629
1630    Print method exit for -verbose:call.
1631
1632 *******************************************************************************/
1633
1634 #if !defined(NDEBUG)
1635 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1636 {
1637         methoddesc *md;
1638         char       *logtext;
1639         s4          logtextlen;
1640         s4          dumpsize;
1641         s4          i;
1642         s4          pos;
1643         imm_union   val;
1644
1645         md = m->parseddesc;
1646
1647         /* calculate message length */
1648
1649         logtextlen =
1650                 strlen("4294967295 ") +
1651                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1652                 methodindent +
1653                 strlen("finished: ") +
1654                 utf_bytes(m->class->name) +
1655                 strlen(".") +
1656                 utf_bytes(m->name) +
1657                 utf_bytes(m->descriptor) +
1658                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1659
1660         /* add maximal argument length */
1661
1662         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1663
1664         /* allocate memory */
1665
1666         dumpsize = dump_size();
1667
1668         logtext = DMNEW(char, logtextlen);
1669
1670         /* outdent the log message */
1671
1672         if (methodindent)
1673                 methodindent--;
1674         else
1675                 log_text("WARNING: unmatched methodindent--");
1676
1677         /* generate the message */
1678
1679         sprintf(logtext, "           ");
1680         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1681
1682         pos = strlen(logtext);
1683
1684         for (i = 0; i < methodindent; i++)
1685                 logtext[pos++] = '\t';
1686
1687         strcpy(logtext + pos, "finished: ");
1688         utf_cat_classname(logtext, m->class->name);
1689         strcat(logtext, ".");
1690         utf_cat(logtext, m->name);
1691         utf_cat(logtext, m->descriptor);
1692
1693         if (!IS_VOID_TYPE(md->returntype.type)) {
1694                 strcat(logtext, "->");
1695
1696                 switch (md->returntype.type) {
1697                 case TYPE_INT:
1698                 case TYPE_LNG:
1699                 case TYPE_ADR:
1700                         val.l = l;
1701                         break;
1702
1703                 case TYPE_FLT:
1704                         val.f = f;
1705                         break;
1706
1707                 case TYPE_DBL:
1708                         val.d = d;
1709                         break;
1710                 }
1711
1712                 logtext =
1713                         builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1714         }
1715
1716         log_text(logtext);
1717
1718         /* release memory */
1719
1720         dump_release(dumpsize);
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)
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)
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)
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                                         exceptions_throw_arraystoreexception();
2615                                         return false;
2616                                 }
2617
2618                                 oad->data[destStart + i] = o;
2619                         }
2620                 }
2621                 else {
2622                         /* XXX this does not completely obey the specification!
2623                            If an exception is thrown only the elements above the
2624                            current index have been copied. The specification
2625                            requires that only the elements *below* the current
2626                            index have been copied before the throw. */
2627
2628                         for (i = len - 1; i >= 0; i--) {
2629                                 java_objectheader *o = oas->data[srcStart + i];
2630
2631                                 if (!builtin_canstore(oad, o)) {
2632                                         exceptions_throw_arraystoreexception();
2633                                         return false;
2634                                 }
2635
2636                                 oad->data[destStart + i] = o;
2637                         }
2638                 }
2639         }
2640
2641         return true;
2642 }
2643
2644
2645 /* builtin_currenttimemillis ***************************************************
2646
2647    Return the current time in milliseconds.
2648
2649 *******************************************************************************/
2650
2651 s8 builtin_currenttimemillis(void)
2652 {
2653         struct timeval tv;
2654         s8             result;
2655
2656         if (gettimeofday(&tv, NULL) == -1)
2657                 vm_abort("gettimeofday failed: %s", strerror(errno));
2658
2659         result = (s8) tv.tv_sec;
2660         result *= 1000;
2661         result += (tv.tv_usec / 1000);
2662
2663         return result;
2664 }
2665
2666
2667 /* builtin_clone ***************************************************************
2668
2669    Function for cloning objects or arrays.
2670
2671 *******************************************************************************/
2672
2673 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2674 {
2675         arraydescriptor   *ad;
2676         java_arrayheader  *ah;
2677         u4                 size;
2678         classinfo         *c;
2679         java_objectheader *co;              /* cloned object header               */
2680
2681         /* get the array descriptor */
2682
2683         ad = o->vftbl->arraydesc;
2684
2685         /* we are cloning an array */
2686
2687         if (ad != NULL) {
2688                 ah = (java_arrayheader *) o;
2689
2690                 size = ad->dataoffset + ad->componentsize * ah->size;
2691         
2692                 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2693
2694                 if (co == NULL)
2695                         return NULL;
2696
2697                 MCOPY(co, o, u1, size);
2698
2699 #if defined(ENABLE_GC_CACAO)
2700                 heap_init_objectheader(co, size);
2701 #endif
2702
2703 #if defined(ENABLE_THREADS)
2704                 lock_init_object_lock(co);
2705 #endif
2706
2707                 return co;
2708         }
2709     
2710     /* we are cloning a non-array */
2711
2712     if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2713         exceptions_throw_clonenotsupportedexception();
2714         return NULL;
2715     }
2716
2717         /* get the class of the object */
2718
2719     c = o->vftbl->class;
2720
2721         /* create new object */
2722
2723     co = builtin_new(c);
2724
2725     if (co == NULL)
2726         return NULL;
2727
2728     MCOPY(co, o, u1, c->instancesize);
2729
2730 #if defined(ENABLE_GC_CACAO)
2731         heap_init_objectheader(co, c->instancesize);
2732 #endif
2733
2734 #if defined(ENABLE_THREADS)
2735         lock_init_object_lock(co);
2736 #endif
2737
2738     return co;
2739 }
2740
2741
2742 /*
2743  * These are local overrides for various environment variables in Emacs.
2744  * Please do not remove this and leave it at the end of the file, where
2745  * Emacs will automagically detect them.
2746  * ---------------------------------------------------------------------
2747  * Local variables:
2748  * mode: c
2749  * indent-tabs-mode: t
2750  * c-basic-offset: 4
2751  * tab-width: 4
2752  * End:
2753  * vim:noexpandtab:sw=4:ts=4:
2754  */