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