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