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