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