#include <assert.h>
#include <stdint.h>
+#include "arch.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "vm/array.h"
#include "vm/global.h"
+#include "vm/primitive.h"
+#include "vm/resolve.h"
#include "vm/vm.h"
+#include "vm/jit/abi-asm.h"
+
#include "vmcore/descriptor.h"
+#include "vmcore/method.h"
/* argument_jitarray_load ******************************************************
}
+/* argument_vmarray_store_int **************************************************
+
+ Helper function to store an integer into the argument array, taking
+ care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
+{
+ int32_t index;
+
+ if (!pd->inmemory) {
+ index = pd->index;
+ array[index] = (int64_t) value;
+ }
+ else {
+ index = ARG_CNT + pd->index;
+#if SIZEOF_VOID_P == 8
+ array[index] = (int64_t) value;
+#else
+# if WORDS_BIGENDIAN == 1
+ array[index] = ((int64_t) value) << 32;
+# else
+ array[index] = (int64_t) value;
+# endif
+#endif
+ }
+}
+
+
+/* argument_vmarray_store_lng **************************************************
+
+ Helper function to store a long into the argument array, taking
+ care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
+{
+ int32_t index;
+
+#if SIZEOF_VOID_P == 8
+ if (!pd->inmemory)
+ index = pd->index;
+ else
+ index = ARG_CNT + pd->index;
+
+ array[index] = value;
+#else
+ if (!pd->inmemory) {
+ /* move low and high 32-bits into it's own argument slot */
+
+ index = GET_LOW_REG(pd->index);
+ array[index] = value & 0x00000000ffffffff;
+
+ index = GET_HIGH_REG(pd->index);
+ array[index] = value >> 32;
+ }
+ else {
+ index = ARG_CNT + pd->index;
+ array[index] = value;
+ }
+#endif
+}
+
+
+/* argument_vmarray_store_flt **************************************************
+
+ Helper function to store a float into the argument array, taking
+ care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
+{
+ int32_t index;
+
+ if (!pd->inmemory) {
+#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+ index = pd->index;
+#else
+ index = INT_ARG_CNT + pd->index;
+#endif
+#if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
+ array[index] = value >> 32;
+#else
+ array[index] = value;
+#endif
+ }
+ else {
+ index = ARG_CNT + pd->index;
+#if defined(__SPARC_64__)
+ array[index] = value >> 32;
+#else
+ array[index] = value;
+#endif
+ }
+}
+
+
+/* argument_vmarray_store_dbl **************************************************
+
+ Helper function to store a double into the argument array, taking
+ care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
+{
+ int32_t index;
+
+ if (!pd->inmemory) {
+#if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+ index = GET_LOW_REG(pd->index);
+ array[index] = value & 0x00000000ffffffff;
+
+ index = GET_HIGH_REG(pd->index);
+ array[index] = value >> 32;
+#else
+ index = INT_ARG_CNT + pd->index;
+ array[index] = value;
+#endif
+ }
+ else {
+ index = ARG_CNT + pd->index;
+ array[index] = value;
+ }
+}
+
+
+/* argument_vmarray_store_adr **************************************************
+
+ Helper function to store an address into the argument array, taking
+ care of architecture specific issues.
+
+ ATTENTION: This function has to be used outside the nativeworld.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
+{
+ void *value;
+ int32_t index;
+
+ /* Take the reference value out of the handle. */
+
+ value = LLNI_UNWRAP(h);
+
+ if (!pd->inmemory) {
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ /* When the architecture has address registers, place them
+ after integer and float registers. */
+
+ index = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
+#else
+ index = pd->index;
+#endif
+ array[index] = (uint64_t) (intptr_t) value;
+ }
+ else {
+ index = ARG_CNT + pd->index;
+#if SIZEOF_VOID_P == 8
+ array[index] = (uint64_t) (intptr_t) value;
+#else
+# if WORDS_BIGENDIAN == 1
+ array[index] = ((uint64_t) (intptr_t) value) << 32;
+# else
+ array[index] = (uint64_t) (intptr_t) value;
+# endif
+#endif
+ }
+}
+
+
+/* argument_vmarray_from_valist ************************************************
+
+ Creates an argument array which can be passed to asm_vm_call_method.
+ The array is created from the passed valist.
+
+ ATTENTION: This function has to be used outside the native world.
+
+*******************************************************************************/
+
+uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
+{
+ methoddesc *md;
+ paramdesc *pd;
+ typedesc *td;
+ uint64_t *array;
+ int32_t i;
+ imm_union value;
+
+ /* get the descriptors */
+
+ md = m->parseddesc;
+ pd = md->params;
+ td = md->paramtypes;
+
+ /* allocate argument array */
+
+ array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
+
+ /* if method is non-static fill first block and skip `this' pointer */
+
+ i = 0;
+
+ if (o != NULL) {
+ /* the `this' pointer */
+ argument_vmarray_store_adr(array, pd, o);
+
+ pd++;
+ td++;
+ i++;
+ }
+
+ for (; i < md->paramcount; i++, pd++, td++) {
+ switch (td->type) {
+ case TYPE_INT:
+ value.i = va_arg(ap, int32_t);
+ argument_vmarray_store_int(array, pd, value.i);
+ break;
+
+ case TYPE_LNG:
+ value.l = va_arg(ap, int64_t);
+ argument_vmarray_store_lng(array, pd, value.l);
+ break;
+
+ case TYPE_FLT:
+#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
+ /* This is required to load the correct float value in
+ assembler code. */
+
+ value.d = (double) va_arg(ap, double);
+#else
+ value.f = (float) va_arg(ap, double);
+#endif
+ argument_vmarray_store_flt(array, pd, value.l);
+ break;
+
+ case TYPE_DBL:
+ value.d = va_arg(ap, double);
+ argument_vmarray_store_dbl(array, pd, value.l);
+ break;
+
+ case TYPE_ADR:
+ value.a = va_arg(ap, void*);
+ argument_vmarray_store_adr(array, pd, value.a);
+ break;
+ }
+ }
+
+ return array;
+}
+
+
+/* argument_vmarray_from_jvalue ************************************************
+
+ Creates an argument array which can be passed to asm_vm_call_method.
+ The array is created from the passed jvalue array.
+
+ ATTENTION: This function has to be used outside the native world.
+
+*******************************************************************************/
+
+uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
+ const jvalue *args)
+{
+ methoddesc *md;
+ paramdesc *pd;
+ typedesc *td;
+ uint64_t *array;
+ int32_t i;
+ int32_t j;
+
+ /* get the descriptors */
+
+ md = m->parseddesc;
+ pd = md->params;
+ td = md->paramtypes;
+
+ /* allocate argument array */
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse);
+#else
+ array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
+#endif
+
+ /* if method is non-static fill first block and skip `this' pointer */
+
+ i = 0;
+
+ if (o != NULL) {
+ /* the `this' pointer */
+ argument_vmarray_store_adr(array, pd, o);
+
+ pd++;
+ td++;
+ i++;
+ }
+
+ for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
+ switch (td->decltype) {
+ case TYPE_INT:
+ argument_vmarray_store_int(array, pd, args[j].i);
+ break;
+
+ case TYPE_LNG:
+ argument_vmarray_store_lng(array, pd, args[j].j);
+ break;
+
+ case TYPE_FLT:
+ argument_vmarray_store_flt(array, pd, args[j].j);
+ break;
+
+ case TYPE_DBL:
+ argument_vmarray_store_dbl(array, pd, args[j].j);
+ break;
+
+ case TYPE_ADR:
+ argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
+ break;
+ }
+ }
+
+ return array;
+}
+
+
+/* argument_vmarray_from_objectarray *******************************************
+
+ Creates an argument array which can be passed to asm_vm_call_method.
+ The array is created from the passed objectarray of boxed values.
+
+ ATTENTION: This function has to be used outside the native world.
+
+ RETURN VALUE:
+ NULL.........indicates an error while creating the array
+ (-1).........no error, but an empty array
+ otherwise....array containing the argument values
+
+*******************************************************************************/
+
+uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
+ java_handle_objectarray_t *params)
+{
+ methoddesc *md;
+ paramdesc *pd;
+ typedesc *td;
+ uint64_t *array;
+ java_handle_t *param;
+ classinfo *c;
+ int type;
+ int32_t i;
+ int32_t j;
+ imm_union value;
+
+ /* get the descriptors */
+
+ md = m->parseddesc;
+ pd = md->params;
+ td = md->paramtypes;
+
+ /* allocate argument array */
+
+ array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
+
+ /* The array can be NULL if we don't have any arguments to pass
+ and the architecture does not have any argument registers
+ (e.g. i386). In that case we return (-1) to indicate
+ that no exception should be thrown */
+
+ if (array == NULL)
+ array = (uint64_t *)(-1);
+
+ /* if method is non-static fill first block and skip `this' pointer */
+
+ i = 0;
+
+ if (o != NULL) {
+ /* this pointer */
+ argument_vmarray_store_adr(array, pd, o);
+
+ pd++;
+ td++;
+ i++;
+ }
+
+ for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
+ /* XXX This function can throw an exception, which should not happend
+ here, since we are outside the nativeworld. */
+ param = array_objectarray_element_get(params, j);
+
+ switch (td->type) {
+ case TYPE_INT:
+ if (param == NULL)
+ return NULL;
+
+ /* convert the value according to its declared type */
+
+ LLNI_class_get(param, c);
+ type = primitive_type_get_by_wrapperclass(c);
+
+ switch (td->decltype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ switch (type) {
+ case PRIMITIVETYPE_BOOLEAN:
+ /* This type is OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case PRIMITIVETYPE_BYTE:
+ switch (type) {
+ case PRIMITIVETYPE_BYTE:
+ /* This type is OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case PRIMITIVETYPE_CHAR:
+ switch (type) {
+ case PRIMITIVETYPE_CHAR:
+ /* This type is OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case PRIMITIVETYPE_SHORT:
+ switch (type) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ /* These types are OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case PRIMITIVETYPE_INT:
+ switch (type) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ /* These types are OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ default:
+ vm_abort("argument_vmarray_from_objectarray: invalid type %d",
+ td->decltype);
+ }
+
+ value = primitive_unbox(param);
+ argument_vmarray_store_int(array, pd, value.i);
+ break;
+
+ case TYPE_LNG:
+ if (param == NULL)
+ return NULL;
+
+ LLNI_class_get(param, c);
+ type = primitive_type_get_by_wrapperclass(c);
+
+ assert(td->decltype == PRIMITIVETYPE_LONG);
+
+ switch (type) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ case PRIMITIVETYPE_LONG:
+ /* These types are OK. */
+ break;
+ default:
+ return NULL;
+ }
+
+ value = primitive_unbox(param);
+ argument_vmarray_store_lng(array, pd, value.l);
+ break;
+
+ case TYPE_FLT:
+ if (param == NULL)
+ return NULL;
+
+ LLNI_class_get(param, c);
+ type = primitive_type_get_by_wrapperclass(c);
+
+ assert(td->decltype == PRIMITIVETYPE_FLOAT);
+
+ switch (type) {
+ case PRIMITIVETYPE_FLOAT:
+ /* This type is OK. */
+ break;
+ default:
+ return NULL;
+ }
+
+ value = primitive_unbox(param);
+ argument_vmarray_store_flt(array, pd, value.l);
+ break;
+
+ case TYPE_DBL:
+ if (param == NULL)
+ return NULL;
+
+ LLNI_class_get(param, c);
+ type = primitive_type_get_by_wrapperclass(c);
+
+ assert(td->decltype == PRIMITIVETYPE_DOUBLE);
+
+ switch (type) {
+ case PRIMITIVETYPE_FLOAT:
+ case PRIMITIVETYPE_DOUBLE:
+ /* These types are OK. */
+ break;
+ default:
+ return NULL;
+ }
+
+ value = primitive_unbox(param);
+ argument_vmarray_store_dbl(array, pd, value.l);
+ break;
+
+ case TYPE_ADR:
+ if (!resolve_class_from_typedesc(td, true, true, &c))
+ return NULL;
+
+ if (param != NULL) {
+ if (td->arraydim > 0) {
+ if (!builtin_arrayinstanceof(param, c))
+ return NULL;
+ }
+ else {
+ if (!builtin_instanceof(param, c))
+ return NULL;
+ }
+ }
+
+ argument_vmarray_store_adr(array, pd, param);
+ break;
+
+ default:
+ vm_abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
+ }
+ }
+
+ return array;
+}
+
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where