1 /* src/vm/jit/argument.cpp - argument passing from and to JIT methods
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
33 #include "mm/memory.h"
35 #include "native/llni.h"
37 #include "vm/array.hpp"
38 #include "vm/descriptor.hpp"
39 #include "vm/global.h"
40 #include "vm/method.hpp"
41 #include "vm/primitive.hpp"
42 #include "vm/resolve.hpp"
45 #include "vm/jit/abi-asm.h"
48 /* argument_jitarray_load ******************************************************
50 Returns the argument specified by index from one of the passed arrays
53 *******************************************************************************/
55 imm_union argument_jitarray_load(methoddesc *md, int32_t index,
56 uint64_t *arg_regs, uint64_t *stack)
61 pd = &md->params[index];
63 switch (md->paramtypes[index].type) {
67 #if (SIZEOF_VOID_P == 8)
68 ret.l = (int64_t)stack[pd->index];
70 ret.l = *(int32_t *)(stack + pd->index);
73 #if (SIZEOF_VOID_P == 8)
74 ret.l = arg_regs[index];
76 ret.l = *(int32_t *)(arg_regs + index);
82 ret.l = (int64_t)stack[pd->index];
84 ret.l = (int64_t)arg_regs[index];
89 ret.l = (int64_t)stack[pd->index];
91 ret.l = (int64_t)arg_regs[index];
96 ret.l = (int64_t)stack[pd->index];
98 ret.l = (int64_t)arg_regs[index];
107 /* argument_jitarray_store *****************************************************
109 Stores the argument into one of the passed arrays at a slot specified
112 *******************************************************************************/
114 void argument_jitarray_store(methoddesc *md, int32_t index,
115 uint64_t *arg_regs, uint64_t *stack,
120 pd = &md->params[index];
122 switch (md->paramtypes[index].type) {
125 #if (SIZEOF_VOID_P == 8)
126 stack[pd->index] = param.l;
131 arg_regs[index] = param.l;
135 os::abort("argument_jitarray_store: type not implemented");
141 /* argument_jitreturn_load *****************************************************
143 Loads the proper return value form the return register and returns it.
145 *******************************************************************************/
147 imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
151 switch (md->returntype.type) {
154 #if (SIZEOF_VOID_P == 8)
155 ret.l = return_regs[0];
157 ret.l = *(int32_t *)return_regs;
161 ret.l = *(int64_t *)return_regs;
164 ret.l = *(int64_t *)return_regs;
167 ret.l = *(int64_t *)return_regs;
175 /* argument_jitreturn_store ****************************************************
177 Stores the proper return value into the return registers.
179 *******************************************************************************/
181 void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
183 switch (md->returntype.type) {
185 #if (SIZEOF_VOID_P == 8)
186 return_regs[0] = ret.l;
192 os::abort("argument_jitreturn_store: type not implemented");
198 /* argument_vmarray_store_int **************************************************
200 Helper function to store an integer into the argument array, taking
201 care of architecture specific issues.
203 *******************************************************************************/
205 static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
211 array[index] = (int64_t) value;
214 index = ARG_CNT + pd->index;
215 #if SIZEOF_VOID_P == 8
216 array[index] = (int64_t) value;
218 # if WORDS_BIGENDIAN == 1
219 array[index] = ((int64_t) value) << 32;
221 array[index] = (int64_t) value;
228 /* argument_vmarray_store_lng **************************************************
230 Helper function to store a long into the argument array, taking
231 care of architecture specific issues.
233 *******************************************************************************/
235 static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
239 #if SIZEOF_VOID_P == 8
243 index = ARG_CNT + pd->index;
245 array[index] = value;
248 /* move low and high 32-bits into it's own argument slot */
250 index = GET_LOW_REG(pd->index);
251 array[index] = value & 0x00000000ffffffff;
253 index = GET_HIGH_REG(pd->index);
254 array[index] = value >> 32;
257 index = ARG_CNT + pd->index;
258 array[index] = value;
264 /* argument_vmarray_store_flt **************************************************
266 Helper function to store a float into the argument array, taking
267 care of architecture specific issues.
269 *******************************************************************************/
271 static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
276 #if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
279 index = INT_ARG_CNT + pd->index;
281 #if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
282 array[index] = value >> 32;
284 array[index] = value;
288 index = ARG_CNT + pd->index;
289 #if defined(__SPARC_64__)
290 array[index] = value >> 32;
292 array[index] = value;
298 /* argument_vmarray_store_dbl **************************************************
300 Helper function to store a double into the argument array, taking
301 care of architecture specific issues.
303 *******************************************************************************/
305 static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
310 #if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
311 index = GET_LOW_REG(pd->index);
312 array[index] = value & 0x00000000ffffffff;
314 index = GET_HIGH_REG(pd->index);
315 array[index] = value >> 32;
317 index = INT_ARG_CNT + pd->index;
318 array[index] = value;
322 index = ARG_CNT + pd->index;
323 array[index] = value;
328 /* argument_vmarray_store_adr **************************************************
330 Helper function to store an address into the argument array, taking
331 care of architecture specific issues.
333 ATTENTION: This function has to be used outside the nativeworld.
335 *******************************************************************************/
337 static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
342 /* Take the reference value out of the handle. */
344 value = LLNI_UNWRAP(h);
347 #if defined(HAS_ADDRESS_REGISTER_FILE)
348 /* When the architecture has address registers, place them
349 after integer and float registers. */
351 index = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
355 array[index] = (uint64_t) (intptr_t) value;
358 index = ARG_CNT + pd->index;
359 #if SIZEOF_VOID_P == 8
360 array[index] = (uint64_t) (intptr_t) value;
362 # if WORDS_BIGENDIAN == 1
363 array[index] = ((uint64_t) (intptr_t) value) << 32;
365 array[index] = (uint64_t) (intptr_t) value;
372 /* argument_vmarray_from_valist ************************************************
374 Creates an argument array which can be passed to asm_vm_call_method.
375 The array is created from the passed valist.
377 ATTENTION: This function has to be used outside the native world.
379 *******************************************************************************/
381 uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
390 /* get the descriptors */
396 // Allocate argument array.
397 array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
399 /* if method is non-static fill first block and skip `this' pointer */
404 /* the `this' pointer */
405 argument_vmarray_store_adr(array, pd, o);
412 for (; i < md->paramcount; i++, pd++, td++) {
415 value.i = va_arg(ap, int32_t);
416 argument_vmarray_store_int(array, pd, value.i);
420 value.l = va_arg(ap, int64_t);
421 argument_vmarray_store_lng(array, pd, value.l);
425 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
426 /* This is required to load the correct float value in
429 value.d = (double) va_arg(ap, double);
431 value.f = (float) va_arg(ap, double);
433 argument_vmarray_store_flt(array, pd, value.l);
437 value.d = va_arg(ap, double);
438 argument_vmarray_store_dbl(array, pd, value.l);
442 value.a = va_arg(ap, void*);
443 argument_vmarray_store_adr(array, pd, static_cast<java_handle_t*>(value.a));
452 /* argument_vmarray_from_jvalue ************************************************
454 Creates an argument array which can be passed to asm_vm_call_method.
455 The array is created from the passed jvalue array.
457 ATTENTION: This function has to be used outside the native world.
459 *******************************************************************************/
461 uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
471 /* get the descriptors */
477 /* allocate argument array */
479 #if defined(HAS_ADDRESS_REGISTER_FILE)
480 array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse));
482 array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
485 /* if method is non-static fill first block and skip `this' pointer */
490 /* the `this' pointer */
491 argument_vmarray_store_adr(array, pd, o);
498 for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
499 switch (td->primitivetype) {
501 argument_vmarray_store_int(array, pd, args[j].i);
505 argument_vmarray_store_lng(array, pd, args[j].j);
509 argument_vmarray_store_flt(array, pd, args[j].j);
513 argument_vmarray_store_dbl(array, pd, args[j].j);
517 argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
526 /* argument_vmarray_from_objectarray *******************************************
528 Creates an argument array which can be passed to asm_vm_call_method.
529 The array is created from the passed objectarray of boxed values.
531 ATTENTION: This function has to be used outside the native world.
534 NULL.........indicates an error while creating the array
535 (-1).........no error, but an empty array
536 otherwise....array containing the argument values
538 *******************************************************************************/
540 uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
541 java_handle_objectarray_t *params)
547 java_handle_t *param;
554 /* get the descriptors */
560 /* allocate argument array */
562 array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
564 /* The array can be NULL if we don't have any arguments to pass
565 and the architecture does not have any argument registers
566 (e.g. i386). In that case we return (-1) to indicate
567 that no exception should be thrown */
570 array = (uint64_t *)(-1);
572 /* if method is non-static fill first block and skip `this' pointer */
578 argument_vmarray_store_adr(array, pd, o);
585 for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
586 /* XXX This function can throw an exception, which should not happend
587 here, since we are outside the nativeworld. */
588 param = array_objectarray_element_get(params, j);
595 /* convert the value according to its declared type */
597 LLNI_class_get(param, c);
598 type = Primitive::get_type_by_wrapperclass(c);
600 switch (td->primitivetype) {
601 case PRIMITIVETYPE_BOOLEAN:
603 case PRIMITIVETYPE_BOOLEAN:
604 /* This type is OK. */
611 case PRIMITIVETYPE_BYTE:
613 case PRIMITIVETYPE_BYTE:
614 /* This type is OK. */
621 case PRIMITIVETYPE_CHAR:
623 case PRIMITIVETYPE_CHAR:
624 /* This type is OK. */
631 case PRIMITIVETYPE_SHORT:
633 case PRIMITIVETYPE_BYTE:
634 case PRIMITIVETYPE_SHORT:
635 /* These types are OK. */
642 case PRIMITIVETYPE_INT:
644 case PRIMITIVETYPE_BYTE:
645 case PRIMITIVETYPE_SHORT:
646 case PRIMITIVETYPE_INT:
647 /* These types are OK. */
655 os::abort("argument_vmarray_from_objectarray: invalid type %d",
659 value = Primitive::unbox(param);
660 argument_vmarray_store_int(array, pd, value.i);
667 LLNI_class_get(param, c);
668 type = Primitive::get_type_by_wrapperclass(c);
670 assert(td->primitivetype == PRIMITIVETYPE_LONG);
673 case PRIMITIVETYPE_BYTE:
674 case PRIMITIVETYPE_SHORT:
675 case PRIMITIVETYPE_INT:
676 case PRIMITIVETYPE_LONG:
677 /* These types are OK. */
683 value = Primitive::unbox(param);
684 argument_vmarray_store_lng(array, pd, value.l);
691 LLNI_class_get(param, c);
692 type = Primitive::get_type_by_wrapperclass(c);
694 assert(td->primitivetype == PRIMITIVETYPE_FLOAT);
697 case PRIMITIVETYPE_FLOAT:
698 /* This type is OK. */
704 value = Primitive::unbox(param);
705 argument_vmarray_store_flt(array, pd, value.l);
712 LLNI_class_get(param, c);
713 type = Primitive::get_type_by_wrapperclass(c);
715 assert(td->primitivetype == PRIMITIVETYPE_DOUBLE);
718 case PRIMITIVETYPE_FLOAT:
719 case PRIMITIVETYPE_DOUBLE:
720 /* These types are OK. */
726 value = Primitive::unbox(param);
727 argument_vmarray_store_dbl(array, pd, value.l);
731 if (!resolve_class_from_typedesc(td, true, true, &c))
735 if (td->arraydim > 0) {
736 if (!builtin_arrayinstanceof(param, c))
740 if (!builtin_instanceof(param, c))
745 argument_vmarray_store_adr(array, pd, param);
749 os::abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
758 * These are local overrides for various environment variables in Emacs.
759 * Please do not remove this and leave it at the end of the file, where
760 * Emacs will automagically detect them.
761 * ---------------------------------------------------------------------
764 * indent-tabs-mode: t
768 * vim:noexpandtab:sw=4:ts=4: