aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2012-04-02 17:30:32 +0300
committerPekka Enberg <penberg@kernel.org>2012-04-02 18:09:58 +0300
commit1421557342af2e4db5d29fb0d65396e8cff95dd5 (patch)
tree2c528991186a7a411045ec5274ba3385ca5a3707
parentdda8e18a46b4c7d2c5a1041c5e4a868af2a97133 (diff)
downloadjato-1421557342af2e4db5d29fb0d65396e8cff95dd5.tar.gz
jit: Fix argument register clobbering
This patch fixes a long-standing bug on x86-64 where arguments in register are clobbered. The problem is visible in ParameterPassingLivenessTest which passes with this patch applied. Cc: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> Cc: Tomek Grabiec <tgrabiec@gmail.com> Cc: Vegard Nossum <vegardno@ifi.uio.no> Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r--include/jit/args.h3
-rw-r--r--jit/args.c37
-rw-r--r--jit/invoke-bc.c32
3 files changed, 61 insertions, 11 deletions
diff --git a/include/jit/args.h b/include/jit/args.h
index fcaaab39..b527599a 100644
--- a/include/jit/args.h
+++ b/include/jit/args.h
@@ -8,7 +8,8 @@
#include <assert.h>
-struct expression *convert_args(struct stack *mimic_stack, unsigned long nr_args, struct vm_method *method);
+struct expression **pop_args(struct stack *mimic_stack, unsigned long nr_args);
+struct expression *convert_args(struct expression **args_array, unsigned long nr_args, struct vm_method *method);
struct expression *convert_native_args(struct stack *mimic_stack, unsigned long start_arg, unsigned long nr_args);
#ifndef CONFIG_ARGS_MAP
diff --git a/jit/args.c b/jit/args.c
index b7e46aec..52a828d2 100644
--- a/jit/args.c
+++ b/jit/args.c
@@ -78,8 +78,36 @@ insert_arg(struct expression *root, struct expression *expr, struct vm_method *m
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 stack *mimic_stack, unsigned long nr_args, struct vm_method *method)
+convert_args(struct expression **args_array, unsigned long nr_args, struct vm_method *method)
{
struct expression *args_list = NULL;
unsigned long nr_total_args;
@@ -99,12 +127,8 @@ convert_args(struct stack *mimic_stack, unsigned long nr_args, struct vm_method
goto out;
}
- /*
- * 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);
+ struct expression *expr = args_array[i];
if (vm_type_is_pair(expr->vm_type))
i++;
@@ -132,6 +156,7 @@ convert_args(struct stack *mimic_stack, unsigned long nr_args, struct vm_method
* use method index zero here for JNI methods.
*/
}
+
out:
return args_list;
error:
diff --git a/jit/invoke-bc.c b/jit/invoke-bc.c
index 17ae2c3c..d1709ad4 100644
--- a/jit/invoke-bc.c
+++ b/jit/invoke-bc.c
@@ -68,15 +68,39 @@ static int convert_and_add_args(struct parse_context *ctx,
struct vm_method *invoke_target,
struct statement *stmt)
{
+ struct expression **args_array;
struct expression *args_list;
+ unsigned long nr_args, i;
- args_list = convert_args(ctx->bb->mimic_stack,
- method_real_argument_count(invoke_target),
- invoke_target);
- if (!args_list)
+ nr_args = method_real_argument_count(invoke_target);
+
+ args_array = pop_args(ctx->bb->mimic_stack, nr_args);
+ if (!args_array)
return warn("out of memory"), -EINVAL;
+ for (i = 0; i < nr_args; i++) {
+ struct expression *expr = args_array[i];
+
+ if (!expr_is_pure(expr))
+ args_array[i] = get_pure_expr(ctx, expr);
+
+ if (vm_type_is_pair(expr->vm_type))
+ i++;
+
+ if (i >= nr_args)
+ break;
+ }
+
+ args_list = convert_args(args_array, nr_args, invoke_target);
+ if (!args_list) {
+ free(args_array);
+ return warn("out of memory"), -EINVAL;
+ }
+
+ free(args_array);
+
stmt->args_list = &args_list->node;
+
return 0;
}