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