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