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