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