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