Permalink
Fetching contributors…
Cannot retrieve contributors at this time
193 lines (148 sloc) 3.91 KB
/*
* Copyright (c) 2008 Pekka Enberg
*
* This file is released under the 2-clause BSD license. Please refer to the
* file LICENSE for details.
*/
#include <assert.h>
#include "jit/expression.h"
#include "jit/args.h"
#include "vm/method.h"
#include "lib/stack.h"
#ifdef CONFIG_ARGS_MAP
static inline void set_expr_arg_reg(struct expression *expr,
struct vm_method *method,
int index)
{
expr->arg_reg = method->args_map[index].reg;
}
#else /* CONFIG_ARGS_MAP */
static void set_expr_arg_reg(struct expression *expr,
struct vm_method *method,
int index)
{
}
#endif /* CONFIG_ARGS_MAP */
static bool is_this_arg(struct vm_method *method, int index)
{
if (vm_method_is_static(method))
return false;
if (vm_method_is_jni(method))
return index == 1;
return index == 0;
}
static struct expression *
insert_arg(struct expression *root, struct expression *expr, struct vm_method *method, int index)
{
struct expression *_expr;
/* Check if we should put @expr in EXPR_ARG_THIS. */
if (is_this_arg(method, index))
_expr = arg_this_expr(expr);
else
_expr = arg_expr(expr);
_expr->bytecode_offset = expr->bytecode_offset;
set_expr_arg_reg(_expr, method, index);
if (!root)
return _expr;
return args_list_expr(root, _expr);
}
struct expression **pop_args(struct stack *mimic_stack, unsigned long nr_args)
{
struct expression **args_array;
unsigned long i;
args_array = malloc(nr_args * sizeof(void *));
if (!args_array)
return NULL;
/*
* We scan the args map in reverse order, since the order of arguments
* is already reversed.
*/
for (i = 0; i < nr_args; i++) {
struct expression *expr = stack_pop(mimic_stack);
args_array[i] = expr;
if (vm_type_is_pair(expr->vm_type))
i++;
if (i >= nr_args)
break;
}
return args_array;
}
struct expression *
convert_args(struct expression **args_array, unsigned long nr_args, struct vm_method *method)
{
struct expression *args_list = NULL;
unsigned long nr_total_args;
unsigned long i;
nr_total_args = nr_args;
if (vm_method_is_jni(method)) {
if (vm_method_is_static(method))
nr_total_args++;
nr_total_args++;
}
if (nr_total_args == 0) {
args_list = no_args_expr();
goto out;
}
for (i = 0; i < nr_args; i++) {
struct expression *expr = args_array[i];
if (vm_type_is_pair(expr->vm_type))
i++;
if (i >= nr_args)
break;
args_list = insert_arg(args_list, expr, method, nr_total_args - i - 1);
}
if (vm_method_is_jni(method)) {
struct expression *expr;
if (vm_method_is_static(method)) {
expr = value_expr(J_REFERENCE, (unsigned long) method->class->object);
if (!expr)
goto error;
args_list = insert_arg(args_list, expr, method, 1);
}
/*
* JNI methods also need a pointer to JNI environment. That's
* done in jni_trampoline automagically which is why we never
* use method index zero here for JNI methods.
*/
}
out:
return args_list;
error:
expr_put(args_list);
return NULL;
}
static struct expression *
insert_native_arg(struct expression *root, struct expression *expr, unsigned long idx)
{
struct expression *_expr;
_expr = arg_expr(expr);
_expr->bytecode_offset = expr->bytecode_offset;
#ifdef CONFIG_ARGS_MAP
_expr->arg_reg = args_map_alloc_gpr(idx);
#endif
if (!root)
return _expr;
return args_list_expr(root, _expr);
}
/**
* This function prepares argument list that will be used
* with the native VM call. All arguments are passed on stack.
*/
struct expression *
convert_native_args(struct stack *mimic_stack, unsigned long start_arg, unsigned long nr_args)
{
struct expression *args_list = NULL;
unsigned long i;
if (nr_args == 0) {
args_list = no_args_expr();
goto out;
}
for (i = 0; i < nr_args; i++) {
struct expression *expr = stack_pop(mimic_stack);
assert(expr->vm_type != J_FLOAT);
assert(expr->vm_type != J_DOUBLE);
args_list = insert_native_arg(args_list, expr, nr_args + start_arg - i - 1);
}
out:
return args_list;
}