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