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