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