CACAO
argument.cpp
Go to the documentation of this file.
1 /* src/vm/jit/argument.cpp - argument passing from and to JIT methods
2 
3  Copyright (C) 1996-2013
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 */
24 
25 
26 #include "config.h"
27 
28 #include <cassert>
29 #include <stdint.h>
30 
31 #include "arch.hpp"
32 #include "md-abi.hpp"
33 
34 #include "mm/dumpmemory.hpp"
35 
36 #include "native/llni.hpp"
37 
38 #include "vm/array.hpp"
39 #include "vm/descriptor.hpp"
40 #include "vm/global.hpp"
41 #include "vm/method.hpp"
42 #include "vm/primitive.hpp"
43 #include "vm/resolve.hpp"
44 #include "vm/vm.hpp"
45 
46 #include "vm/jit/abi-asm.hpp"
47 #include "vm/jit/codegen-common.hpp" // for GET_LOW_REG, GET_HIGH_REG
48 
49 
50 /* argument_jitarray_load ******************************************************
51 
52  Returns the argument specified by index from one of the passed arrays
53  and returns it.
54 
55 *******************************************************************************/
56 
58  uint64_t *arg_regs, uint64_t *stack)
59 {
60  imm_union ret;
61  paramdesc *pd;
62 
63  pd = &md->params[index];
64 
65  switch (md->paramtypes[index].type) {
66  case TYPE_INT:
67  case TYPE_ADR:
68  if (pd->inmemory) {
69 #if (SIZEOF_VOID_P == 8)
70  ret.l = (int64_t)stack[pd->index];
71 #else
72  ret.l = *(int32_t *)(stack + pd->index);
73 #endif
74  } else {
75 #if (SIZEOF_VOID_P == 8)
76  ret.l = arg_regs[index];
77 #else
78  ret.l = *(int32_t *)(arg_regs + index);
79 #endif
80  }
81  break;
82  case TYPE_LNG:
83  if (pd->inmemory) {
84  ret.l = (int64_t)stack[pd->index];
85  } else {
86  ret.l = (int64_t)arg_regs[index];
87  }
88  break;
89  case TYPE_FLT:
90  if (pd->inmemory) {
91  ret.l = (int64_t)stack[pd->index];
92  } else {
93  ret.l = (int64_t)arg_regs[index];
94  }
95  break;
96  case TYPE_DBL:
97  if (pd->inmemory) {
98  ret.l = (int64_t)stack[pd->index];
99  } else {
100  ret.l = (int64_t)arg_regs[index];
101  }
102  break;
103  default:
104  ret.l = 0;
106  break;
107  }
108 
109  return ret;
110 }
111 
112 
113 /* argument_jitarray_store *****************************************************
114 
115  Stores the argument into one of the passed arrays at a slot specified
116  by index.
117 
118 *******************************************************************************/
119 
121  uint64_t *arg_regs, uint64_t *stack,
122  imm_union param)
123 {
124  paramdesc *pd;
125 
126  pd = &md->params[index];
127 
128  switch (md->paramtypes[index].type) {
129  case TYPE_ADR:
130  if (pd->inmemory) {
131 #if (SIZEOF_VOID_P == 8)
132  stack[pd->index] = param.l;
133 #else
134  assert(0);
135 #endif
136  } else {
137  arg_regs[index] = param.l;
138  }
139  break;
140  default:
141  os::unimplemented("argument_jitarray_store: type not implemented");
142  break;
143  }
144 }
145 
146 
147 /* argument_jitreturn_load *****************************************************
148 
149  Loads the proper return value form the return register and returns it.
150 
151 *******************************************************************************/
152 
153 imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
154 {
155  imm_union ret;
156 
157  switch (md->returntype.type) {
158  case TYPE_INT:
159  case TYPE_ADR:
160 #if (SIZEOF_VOID_P == 8)
161  ret.l = return_regs[0];
162 #else
163  ret.l = *(int32_t *)return_regs;
164 #endif
165  break;
166  case TYPE_LNG:
167  ret.l = *(int64_t *)return_regs;
168  break;
169  case TYPE_FLT:
170  ret.l = *(int64_t *)return_regs;
171  break;
172  case TYPE_DBL:
173  ret.l = *(int64_t *)return_regs;
174  break;
175  default:
176  ret.l = 0;
178  break;
179  }
180 
181  return ret;
182 }
183 
184 
185 /* argument_jitreturn_store ****************************************************
186 
187  Stores the proper return value into the return registers.
188 
189 *******************************************************************************/
190 
191 void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
192 {
193  switch (md->returntype.type) {
194  case TYPE_ADR:
195 #if (SIZEOF_VOID_P == 8)
196  return_regs[0] = ret.l;
197 #else
198  assert(0);
199 #endif
200  break;
201  default:
202  os::unimplemented("argument_jitreturn_store: type not implemented");
203  break;
204  }
205 }
206 
207 
208 /* argument_vmarray_store_int **************************************************
209 
210  Helper function to store an integer into the argument array, taking
211  care of architecture specific issues.
212 
213 *******************************************************************************/
214 
215 static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
216 {
217  int32_t index;
218 
219  if (!pd->inmemory) {
220  index = pd->index;
221  array[index] = (int64_t) value;
222  }
223  else {
224  index = ARG_CNT + pd->index;
225 #if SIZEOF_VOID_P == 8
226  array[index] = (int64_t) value;
227 #else
228 # if WORDS_BIGENDIAN == 1
229  array[index] = ((int64_t) value) << 32;
230 # else
231  array[index] = (int64_t) value;
232 # endif
233 #endif
234  }
235 }
236 
237 
238 /* argument_vmarray_store_lng **************************************************
239 
240  Helper function to store a long into the argument array, taking
241  care of architecture specific issues.
242 
243 *******************************************************************************/
244 
245 static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
246 {
247  int32_t index;
248 
249 #if SIZEOF_VOID_P == 8
250  if (!pd->inmemory)
251  index = pd->index;
252  else
253  index = ARG_CNT + pd->index;
254 
255  array[index] = value;
256 #else
257  if (!pd->inmemory) {
258  /* move low and high 32-bits into it's own argument slot */
259 
260  index = GET_LOW_REG(pd->index);
261  array[index] = value & 0x00000000ffffffff;
262 
263  index = GET_HIGH_REG(pd->index);
264  array[index] = value >> 32;
265  }
266  else {
267  index = ARG_CNT + pd->index;
268  array[index] = value;
269  }
270 #endif
271 }
272 
273 
274 /* argument_vmarray_store_flt **************************************************
275 
276  Helper function to store a float into the argument array, taking
277  care of architecture specific issues.
278 
279 *******************************************************************************/
280 
281 static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
282 {
283  int32_t index;
284 
285  if (!pd->inmemory) {
286 #if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
287  index = pd->index;
288 #else
289  index = INT_ARG_CNT + pd->index;
290 #endif
291 #if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
292  array[index] = value >> 32;
293 #else
294  array[index] = value;
295 #endif
296  }
297  else {
298  index = ARG_CNT + pd->index;
299 #if defined(__SPARC_64__)
300  array[index] = value >> 32;
301 #else
302  array[index] = value;
303 #endif
304  }
305 }
306 
307 
308 /* argument_vmarray_store_dbl **************************************************
309 
310  Helper function to store a double into the argument array, taking
311  care of architecture specific issues.
312 
313 *******************************************************************************/
314 
315 static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
316 {
317  int32_t index;
318 
319  if (!pd->inmemory) {
320 #if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
321  index = GET_LOW_REG(pd->index);
322  array[index] = value & 0x00000000ffffffff;
323 
324  index = GET_HIGH_REG(pd->index);
325  array[index] = value >> 32;
326 #else
327  index = INT_ARG_CNT + pd->index;
328  array[index] = value;
329 #endif
330  }
331  else {
332  index = ARG_CNT + pd->index;
333  array[index] = value;
334  }
335 }
336 
337 
338 /* argument_vmarray_store_adr **************************************************
339 
340  Helper function to store an address into the argument array, taking
341  care of architecture specific issues.
342 
343  ATTENTION: This function has to be used outside the nativeworld.
344 
345 *******************************************************************************/
346 
347 static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
348 {
349  void *value;
350  int32_t index;
351 
352  /* Take the reference value out of the handle. */
353 
354  value = LLNI_UNWRAP(h);
355 
356  if (!pd->inmemory) {
357  index = pd->index;
358  array[index] = (uint64_t) (intptr_t) value;
359  }
360  else {
361  index = ARG_CNT + pd->index;
362 #if SIZEOF_VOID_P == 8
363  array[index] = (uint64_t) (intptr_t) value;
364 #else
365 # if WORDS_BIGENDIAN == 1
366  array[index] = ((uint64_t) (intptr_t) value) << 32;
367 # else
368  array[index] = (uint64_t) (intptr_t) value;
369 # endif
370 #endif
371  }
372 }
373 
374 
375 /* argument_vmarray_from_valist ************************************************
376 
377  Creates an argument array which can be passed to asm_vm_call_method.
378  The array is created from the passed valist.
379 
380  ATTENTION: This function has to be used outside the native world.
381 
382 *******************************************************************************/
383 
385 {
386  methoddesc *md;
387  paramdesc *pd;
388  typedesc *td;
389  uint64_t *array;
390  int32_t i;
391  imm_union value;
392 
393  /* get the descriptors */
394 
395  md = m->parseddesc;
396  pd = md->params;
397  td = md->paramtypes;
398 
399  // Allocate argument array.
400  array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
401 
402  /* if method is non-static fill first block and skip `this' pointer */
403 
404  i = 0;
405 
406  if (o != NULL) {
407  /* the `this' pointer */
408  argument_vmarray_store_adr(array, pd, o);
409 
410  pd++;
411  td++;
412  i++;
413  }
414 
415  for (; i < md->paramcount; i++, pd++, td++) {
416  switch (td->type) {
417  case TYPE_INT:
418  value.i = va_arg(ap, int32_t);
419  argument_vmarray_store_int(array, pd, value.i);
420  break;
421 
422  case TYPE_LNG:
423  value.l = va_arg(ap, int64_t);
424  argument_vmarray_store_lng(array, pd, value.l);
425  break;
426 
427  case TYPE_FLT:
428 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
429  // The assembler code loads these directly and unconditionally into
430  // the argument registers.
431 
432  if (!pd->inmemory)
433  value.d = (double) va_arg(ap, double);
434  else
435  value.f = (float) va_arg(ap, double);
436 #else
437  value.f = (float) va_arg(ap, double);
438 #endif
439  argument_vmarray_store_flt(array, pd, value.l);
440  break;
441 
442  case TYPE_DBL:
443  value.d = va_arg(ap, double);
444  argument_vmarray_store_dbl(array, pd, value.l);
445  break;
446 
447  case TYPE_ADR:
448  value.a = va_arg(ap, void*);
449  argument_vmarray_store_adr(array, pd, static_cast<java_handle_t*>(value.a));
450  break;
451  default:
452  assert(false);
453  break;
454  }
455  }
456 
457  return array;
458 }
459 
460 
461 /* argument_vmarray_from_jvalue ************************************************
462 
463  Creates an argument array which can be passed to asm_vm_call_method.
464  The array is created from the passed jvalue array.
465 
466  ATTENTION: This function has to be used outside the native world.
467 
468 *******************************************************************************/
469 
471  const jvalue *args)
472 {
473  methoddesc *md;
474  paramdesc *pd;
475  typedesc *td;
476  uint64_t *array;
477  int32_t i;
478  int32_t j;
479 
480  /* get the descriptors */
481 
482  md = m->parseddesc;
483  pd = md->params;
484  td = md->paramtypes;
485 
486  /* allocate argument array */
487 
488  array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
489 
490  /* if method is non-static fill first block and skip `this' pointer */
491 
492  i = 0;
493 
494  if (o != NULL) {
495  /* the `this' pointer */
496  argument_vmarray_store_adr(array, pd, o);
497 
498  pd++;
499  td++;
500  i++;
501  }
502 
503  for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
504  switch (td->primitivetype) {
505  case TYPE_INT:
506  argument_vmarray_store_int(array, pd, args[j].i);
507  break;
508 
509  case TYPE_LNG:
510  argument_vmarray_store_lng(array, pd, args[j].j);
511  break;
512 
513  case TYPE_FLT:
514  argument_vmarray_store_flt(array, pd, args[j].j);
515  break;
516 
517  case TYPE_DBL:
518  argument_vmarray_store_dbl(array, pd, args[j].j);
519  break;
520 
521  case TYPE_ADR:
522  argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
523  break;
524  default:
525  assert(false);
526  break;
527  }
528  }
529 
530  return array;
531 }
532 
533 
534 /* argument_vmarray_from_objectarray *******************************************
535 
536  Creates an argument array which can be passed to asm_vm_call_method.
537  The array is created from the passed objectarray of boxed values.
538 
539  ATTENTION: This function has to be used outside the native world.
540 
541  RETURN VALUE:
542  NULL.........indicates an error while creating the array
543  (-1).........no error, but an empty array
544  otherwise....array containing the argument values
545 
546 *******************************************************************************/
547 
550 {
551  methoddesc *md;
552  paramdesc *pd;
553  typedesc *td;
554  uint64_t *array;
555  java_handle_t *param;
556  classinfo *c;
557  int type;
558  int32_t i;
559  int32_t j;
560  imm_union value;
561 
562  /* get the descriptors */
563 
564  md = m->parseddesc;
565  pd = md->params;
566  td = md->paramtypes;
567 
568  /* allocate argument array */
569 
570  array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
571 
572  /* The array can be NULL if we don't have any arguments to pass
573  and the architecture does not have any argument registers
574  (e.g. i386). In that case we return (-1) to indicate
575  that no exception should be thrown */
576 
577  if (array == NULL)
578  array = (uint64_t *)(-1);
579 
580  /* if method is non-static fill first block and skip `this' pointer */
581 
582  i = 0;
583 
584  if (o != NULL) {
585  /* this pointer */
586  argument_vmarray_store_adr(array, pd, o);
587 
588  pd++;
589  td++;
590  i++;
591  }
592 
593  ObjectArray oa(params);
594 
595  for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
596  /* XXX This function can throw an exception, which should not happend
597  here, since we are outside the nativeworld. */
598  param = oa.get_element(j);
599 
600  switch (td->type) {
601  case TYPE_INT:
602  if (param == NULL)
603  return NULL;
604 
605  /* convert the value according to its declared type */
606 
607  LLNI_class_get(param, c);
609 
610  switch (td->primitivetype) {
612  switch (type) {
614  /* This type is OK. */
615  break;
616  default:
617  return NULL;
618  }
619  break;
620 
621  case PRIMITIVETYPE_BYTE:
622  switch (type) {
623  case PRIMITIVETYPE_BYTE:
624  /* This type is OK. */
625  break;
626  default:
627  return NULL;
628  }
629  break;
630 
631  case PRIMITIVETYPE_CHAR:
632  switch (type) {
633  case PRIMITIVETYPE_CHAR:
634  /* This type is OK. */
635  break;
636  default:
637  return NULL;
638  }
639  break;
640 
641  case PRIMITIVETYPE_SHORT:
642  switch (type) {
643  case PRIMITIVETYPE_BYTE:
644  case PRIMITIVETYPE_SHORT:
645  /* These types are OK. */
646  break;
647  default:
648  return NULL;
649  }
650  break;
651 
652  case PRIMITIVETYPE_INT:
653  switch (type) {
654  case PRIMITIVETYPE_BYTE:
655  case PRIMITIVETYPE_SHORT:
656  case PRIMITIVETYPE_INT:
657  /* These types are OK. */
658  break;
659  default:
660  return NULL;
661  }
662  break;
663 
664  default:
665  os::abort("argument_vmarray_from_objectarray: invalid type %d",
666  td->primitivetype);
667  }
668 
669  value = Primitive::unbox(param);
670  argument_vmarray_store_int(array, pd, value.i);
671  break;
672 
673  case TYPE_LNG:
674  if (param == NULL)
675  return NULL;
676 
677  LLNI_class_get(param, c);
679 
680  assert(td->primitivetype == PRIMITIVETYPE_LONG);
681 
682  switch (type) {
683  case PRIMITIVETYPE_BYTE:
684  case PRIMITIVETYPE_SHORT:
685  case PRIMITIVETYPE_INT:
686  case PRIMITIVETYPE_LONG:
687  /* These types are OK. */
688  break;
689  default:
690  return NULL;
691  }
692 
693  value = Primitive::unbox(param);
694  argument_vmarray_store_lng(array, pd, value.l);
695  break;
696 
697  case TYPE_FLT:
698  if (param == NULL)
699  return NULL;
700 
701  LLNI_class_get(param, c);
703 
704  assert(td->primitivetype == PRIMITIVETYPE_FLOAT);
705 
706  switch (type) {
707  case PRIMITIVETYPE_FLOAT:
708  /* This type is OK. */
709  break;
710  default:
711  return NULL;
712  }
713 
714  value = Primitive::unbox(param);
715  argument_vmarray_store_flt(array, pd, value.l);
716  break;
717 
718  case TYPE_DBL:
719  if (param == NULL)
720  return NULL;
721 
722  LLNI_class_get(param, c);
724 
725  assert(td->primitivetype == PRIMITIVETYPE_DOUBLE);
726 
727  switch (type) {
728  case PRIMITIVETYPE_FLOAT:
730  /* These types are OK. */
731  break;
732  default:
733  return NULL;
734  }
735 
736  value = Primitive::unbox(param);
737  argument_vmarray_store_dbl(array, pd, value.l);
738  break;
739 
740  case TYPE_ADR:
741  if (!resolve_class_from_typedesc(td, true, true, &c))
742  return NULL;
743 
744  if (param != NULL) {
745  if (td->arraydim > 0) {
746  if (!builtin_arrayinstanceof(param, c))
747  return NULL;
748  }
749  else {
750  if (!builtin_instanceof(param, c))
751  return NULL;
752  }
753  }
754 
755  argument_vmarray_store_adr(array, pd, param);
756  break;
757 
758  default:
759  os::abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
760  }
761  }
762 
763  return array;
764 }
765 
766 
767 /*
768  * These are local overrides for various environment variables in Emacs.
769  * Please do not remove this and leave it at the end of the file, where
770  * Emacs will automagically detect them.
771  * ---------------------------------------------------------------------
772  * Local variables:
773  * mode: c++
774  * indent-tabs-mode: t
775  * c-basic-offset: 4
776  * tab-width: 4
777  * End:
778  * vim:noexpandtab:sw=4:ts=4:
779  */
bool builtin_instanceof(java_handle_t *o, classinfo *c)
Definition: builtin.cpp:403
#define GET_HIGH_REG(a)
std::size_t index
static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
Definition: argument.cpp:347
imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
Definition: argument.cpp:153
float f
Definition: global.hpp:56
double d
Definition: global.hpp:57
paramdesc * params
Definition: descriptor.hpp:164
imm_union argument_jitarray_load(methoddesc *md, int32_t index, uint64_t *arg_regs, uint64_t *stack)
Definition: argument.cpp:57
void * a
Definition: global.hpp:58
static void unimplemented()
Definition: os.hpp:695
uint64_t * argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o, const jvalue *args)
Definition: argument.cpp:470
Actual implementation of access class for Java Object arrays.
Definition: array.hpp:381
T get_element(int32_t index)
Definition: array.hpp:238
void argument_jitarray_store(methoddesc *md, int32_t index, uint64_t *arg_regs, uint64_t *stack, imm_union param)
Definition: argument.cpp:120
static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
Definition: argument.cpp:315
uint32_t index
Definition: descriptor.hpp:152
static imm_union unbox(java_handle_t *o)
Unbox a primitive of the given type.
Definition: primitive.cpp:442
bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
Definition: resolve.cpp:473
static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
Definition: argument.cpp:215
uint64_t * argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
Definition: argument.cpp:384
typedesc paramtypes[1]
Definition: descriptor.hpp:167
#define LLNI_class_get(obj, variable)
Definition: llni.hpp:60
#define GET_LOW_REG(a)
static int get_type_by_wrapperclass(classinfo *c)
Returns the primitive type of the given wrapper-class.
Definition: primitive.cpp:349
alloc::list< PassInfo::IDTy >::type & stack
#define ARG_CNT
Definition: abi-asm.hpp:41
#define INT_ARG_CNT
Definition: md-abi.hpp:74
MIIterator i
typedesc returntype
Definition: descriptor.hpp:166
void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
Definition: argument.cpp:191
bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
Definition: builtin.cpp:494
static void abort()
Definition: os.hpp:196
#define LLNI_UNWRAP(hdl)
Definition: llni.hpp:52
bool inmemory
Definition: descriptor.hpp:151
methoddesc * parseddesc
Definition: method.hpp:78
#define FLT_ARG_CNT
Definition: md-abi.hpp:81
static void * allocate(size_t size)
Definition: dumpmemory.hpp:251
static void shouldnotreach()
Definition: os.hpp:690
uint64_t * argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params)
Definition: argument.cpp:548
static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
Definition: argument.cpp:281
static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
Definition: argument.cpp:245
PrimitiveType primitivetype
Definition: descriptor.hpp:137