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