Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

364 lines (273 sloc) 7.744 kB
/*
* Copyright (C) 2005-2006 Pekka Enberg
*
* This file is released under the GPL version 2. Please refer to the file
* LICENSE for details.
*
* The file contains functions for converting Java bytecode load and store
* instructions to immediate representation of the JIT compiler.
*/
#include "jit/bytecode-to-ir.h"
#include "cafebabe/constant_pool.h"
#include "jit/exception.h"
#include "jit/expression.h"
#include "jit/statement.h"
#include "jit/compiler.h"
#include "vm/classloader.h"
#include "vm/bytecode.h"
#include "vm/object.h"
#include "vm/class.h"
#include "vm/die.h"
#include "lib/stack.h"
#include <stdint.h>
#include <errno.h>
#include <stdio.h>
static int __convert_const(struct parse_context *ctx,
unsigned long long value, enum vm_type vm_type)
{
struct expression *expr = value_expr(vm_type, value);
if (!expr)
return warn("out of memory"), -ENOMEM;
convert_expression(ctx, expr);
return 0;
}
int convert_aconst_null(struct parse_context *ctx)
{
return __convert_const(ctx, 0, J_REFERENCE);
}
int convert_iconst_n(struct parse_context *ctx)
{
return __convert_const(ctx, ctx->opc - OPC_ICONST_0, J_INT);
}
int convert_lconst_n(struct parse_context *ctx)
{
return __convert_const(ctx, ctx->opc - OPC_LCONST_0, J_LONG);
}
static int __convert_fconst(struct parse_context *ctx, double value, enum vm_type vm_type)
{
struct expression *expr = fvalue_expr(vm_type, value);
if (!expr)
return warn("out of memory"), -ENOMEM;
convert_expression(ctx, expr);
return 0;
}
int convert_fconst_n(struct parse_context *ctx)
{
return __convert_fconst(ctx, ctx->opc - OPC_FCONST_0, J_FLOAT);
}
int convert_dconst_n(struct parse_context *ctx)
{
return __convert_fconst(ctx, ctx->opc - OPC_DCONST_0, J_DOUBLE);
}
int convert_bipush(struct parse_context *ctx)
{
unsigned long long value;
value = bytecode_read_s8(ctx->buffer);
return __convert_const(ctx, value, J_INT);
}
int convert_sipush(struct parse_context *ctx)
{
unsigned long long value;
value = bytecode_read_s16(ctx->buffer);
return __convert_const(ctx, value, J_INT);
}
static int __convert_ldc(struct parse_context *ctx, unsigned long cp_idx)
{
struct vm_class *vmc;
struct cafebabe_constant_pool *cp;
struct expression *expr = NULL;
vmc = ctx->cu->method->class;
if (cafebabe_class_constant_index_invalid(vmc->class, cp_idx))
return warn("invalid constant index: %ld", cp_idx), -EINVAL;
cp = &vmc->class->constant_pool[cp_idx];
switch (cp->tag) {
case CAFEBABE_CONSTANT_TAG_INTEGER:
expr = value_expr(J_INT, cafebabe_constant_pool_get_integer(cp));
break;
case CAFEBABE_CONSTANT_TAG_FLOAT:
expr = fvalue_expr(J_FLOAT, cafebabe_constant_pool_get_float(cp));
break;
case CAFEBABE_CONSTANT_TAG_STRING: {
const struct cafebabe_constant_info_utf8 *utf8;
struct vm_object *string;
if (cafebabe_class_constant_get_utf8(vmc->class, cp->string.string_index, &utf8))
return warn("unable to lookup class constant"), -EINVAL;
string = vm_object_alloc_string_from_utf8(utf8->bytes, utf8->length);
if (!string)
return warn("out of memory"), -ENOMEM;
expr = value_expr(J_REFERENCE, (unsigned long) string);
break;
}
case CAFEBABE_CONSTANT_TAG_LONG:
expr = value_expr(J_LONG, cafebabe_constant_pool_get_long(cp));
break;
case CAFEBABE_CONSTANT_TAG_DOUBLE:
expr = fvalue_expr(J_DOUBLE, cafebabe_constant_pool_get_double(cp));
break;
case CAFEBABE_CONSTANT_TAG_CLASS: {
/* Added for JDK 1.5 */
struct vm_class *ret = vm_class_resolve_class(vmc, cp_idx);
if (!ret)
return warn("unable to lookup class"), -EINVAL;
if (vm_class_ensure_object(ret))
return -1;
expr = value_expr(J_REFERENCE, (unsigned long) ret->object);
break;
}
default:
return warn("unknown tag: %d", cp->tag), -EINVAL;
}
if (!expr)
return warn("out of memory"), -ENOMEM;
convert_expression(ctx, expr);
return 0;
}
int convert_ldc(struct parse_context *ctx)
{
unsigned long idx;
idx = bytecode_read_u8(ctx->buffer);
return __convert_ldc(ctx, idx);
}
int convert_ldc_w(struct parse_context *ctx)
{
unsigned long idx;
idx = bytecode_read_u16(ctx->buffer);
return __convert_ldc(ctx, idx);
}
int convert_ldc2_w(struct parse_context *ctx)
{
unsigned long idx;
idx = bytecode_read_u16(ctx->buffer);
return __convert_ldc(ctx, idx);
}
static int convert_load(struct parse_context *ctx, unsigned int index, enum vm_type type)
{
struct expression *expr;
expr = local_expr(type, index);
if (!expr)
return warn("out of memory"), -ENOMEM;
convert_expression(ctx, dup_expr(ctx, expr));
return 0;
}
static unsigned int read_index(struct parse_context *ctx)
{
if (ctx->is_wide)
return bytecode_read_u16(ctx->buffer);
return bytecode_read_u8(ctx->buffer);
}
int convert_iload(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_load(ctx, idx, J_INT);
}
int convert_lload(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_load(ctx, idx, J_LONG);
}
int convert_fload(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_load(ctx, idx, J_FLOAT);
}
int convert_dload(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_load(ctx, idx, J_DOUBLE);
}
int convert_aload(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_load(ctx, idx, J_REFERENCE);
}
int convert_iload_n(struct parse_context *ctx)
{
return convert_load(ctx, ctx->opc - OPC_ILOAD_0, J_INT);
}
int convert_lload_n(struct parse_context *ctx)
{
return convert_load(ctx, ctx->opc - OPC_LLOAD_0, J_LONG);
}
int convert_fload_n(struct parse_context *ctx)
{
return convert_load(ctx, ctx->opc - OPC_FLOAD_0, J_FLOAT);
}
int convert_dload_n(struct parse_context *ctx)
{
return convert_load(ctx, ctx->opc - OPC_DLOAD_0, J_DOUBLE);
}
int convert_aload_n(struct parse_context *ctx)
{
return convert_load(ctx, ctx->opc - OPC_ALOAD_0, J_REFERENCE);
}
static int convert_store(struct parse_context *ctx, unsigned int index, enum vm_type type)
{
struct expression *src_expr, *dest_expr;
struct statement *stmt = alloc_statement(STMT_STORE);
if (!stmt)
goto failed;
dest_expr = local_expr(type, index);
src_expr = stack_pop(ctx->bb->mimic_stack);
stmt->store_dest = &dest_expr->node;
stmt->store_src = &src_expr->node;
convert_statement(ctx, stmt);
return 0;
failed:
free_statement(stmt);
return warn("out of memory"), -ENOMEM;
}
int convert_istore(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_store(ctx, idx, J_INT);
}
int convert_lstore(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_store(ctx, idx, J_LONG);
}
int convert_fstore(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_store(ctx, idx, J_FLOAT);
}
int convert_dstore(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_store(ctx, idx, J_DOUBLE);
}
int convert_astore(struct parse_context *ctx)
{
unsigned int idx;
idx = read_index(ctx);
return convert_store(ctx, idx, J_REFERENCE);
}
int convert_istore_n(struct parse_context *ctx)
{
return convert_store(ctx, ctx->opc - OPC_ISTORE_0, J_INT);
}
int convert_lstore_n(struct parse_context *ctx)
{
return convert_store(ctx, ctx->opc - OPC_LSTORE_0, J_LONG);
}
int convert_fstore_n(struct parse_context *ctx)
{
return convert_store(ctx, ctx->opc - OPC_FSTORE_0, J_FLOAT);
}
int convert_dstore_n(struct parse_context *ctx)
{
return convert_store(ctx, ctx->opc - OPC_DSTORE_0, J_DOUBLE);
}
int convert_astore_n(struct parse_context *ctx)
{
return convert_store(ctx, ctx->opc - OPC_ASTORE_0, J_REFERENCE);
}
Jump to Line
Something went wrong with that request. Please try again.