Skip to content

Commit

Permalink
First attempt at a fast box for big integers
Browse files Browse the repository at this point in the history
Almost works, but the range check for whether to store it as a small
int always comes out false, so it always takes the bigint path.
  • Loading branch information
jnthn committed Aug 16, 2018
1 parent cd0020e commit 8fac6c3
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 19 deletions.
18 changes: 11 additions & 7 deletions src/6model/reprs/P6bigint.c
Expand Up @@ -82,13 +82,7 @@ static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *d
}
}

static void set_int(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, MVMint64 value) {
MVMP6bigintBody *body = (MVMP6bigintBody *)data;
if (MVM_IS_32BIT_INT(value)) {
body->u.smallint.flag = MVM_BIGINT_32_FLAG;
body->u.smallint.value = (MVMint32)value;
}
else {
void MVM_p6bigint_store_as_mp_int(MVMP6bigintBody *body, MVMint64 value) {
mp_int *i = MVM_malloc(sizeof(mp_int));
mp_init(i);
if (value >= 0) {
Expand All @@ -99,6 +93,16 @@ static void set_int(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *
mp_neg(i, i);
}
body->u.bigint = i;
}

static void set_int(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, MVMint64 value) {
MVMP6bigintBody *body = (MVMP6bigintBody *)data;
if (MVM_IS_32BIT_INT(value)) {
body->u.smallint.flag = MVM_BIGINT_32_FLAG;
body->u.smallint.value = (MVMint32)value;
}
else {
MVM_p6bigint_store_as_mp_int(body, value);
}
}
static MVMint64 get_int(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data) {
Expand Down
2 changes: 2 additions & 0 deletions src/6model/reprs/P6bigint.h
Expand Up @@ -33,3 +33,5 @@ struct MVMP6bigint {

/* Function for REPR setup. */
const MVMREPROps * MVMP6bigint_initialize(MVMThreadContext *tc);

void MVM_p6bigint_store_as_mp_int(MVMP6bigintBody *body, MVMint64 value);
34 changes: 30 additions & 4 deletions src/6model/reprs/P6opaque.c
Expand Up @@ -1615,7 +1615,33 @@ static void spesh(MVMThreadContext *tc, MVMSTable *st, MVMSpeshGraph *g, MVMSpes
}
break;
}
case MVM_OP_box_n: {
case MVM_OP_box_i:
if (repr_data->num_attributes == 1 && repr_data->unbox_int_slot >= 0 &&
!(st->mode_flags & MVM_FINALIZE_TYPE)) {
MVMSTable *embedded_st = repr_data->flattened_stables[repr_data->unbox_int_slot];
if (embedded_st->REPR->ID == MVM_REPR_ID_P6bigint) {
/* Turn into a sp_fastbox_bi[_ic] instruction. */
MVMint32 int_cache_type_idx = MVM_intcache_type_index(tc, st->WHAT);
MVMSpeshFacts *tgt_facts = MVM_spesh_get_facts(tc, g, ins->operands[0]);
MVMSpeshOperand *orig_operands = ins->operands;
ins->info = MVM_op_get_op(int_cache_type_idx < 0
? MVM_OP_sp_fastbox_bi
: MVM_OP_sp_fastbox_bi_ic);
ins->operands = MVM_spesh_alloc(tc, g, 6 * sizeof(MVMSpeshOperand));
ins->operands[0] = orig_operands[0];
ins->operands[1].lit_i16 = st->size;
ins->operands[2].lit_i16 = MVM_spesh_add_spesh_slot(tc, g, (MVMCollectable *)st);
ins->operands[3].lit_i16 = sizeof(MVMObject) +
repr_data->attribute_offsets[repr_data->unbox_int_slot];
ins->operands[4] = orig_operands[1];
ins->operands[5].lit_i16 = (MVMint16)int_cache_type_idx;
MVM_spesh_usages_delete_by_reg(tc, g, orig_operands[2], ins);
tgt_facts->flags |= MVM_SPESH_FACT_KNOWN_TYPE | MVM_SPESH_FACT_CONCRETE;
tgt_facts->type = st->WHAT;
}
}
break;
case MVM_OP_box_n:
if (repr_data->num_attributes == 1 && repr_data->unbox_num_slot >= 0 &&
!(st->mode_flags & MVM_FINALIZE_TYPE)) {
MVMSTable *embedded_st = repr_data->flattened_stables[repr_data->unbox_num_slot];
Expand All @@ -1642,8 +1668,8 @@ static void spesh(MVMThreadContext *tc, MVMSTable *st, MVMSpeshGraph *g, MVMSpes
MVM_spesh_usages_add_by_reg(tc, g, ins->operands[0], ins);
}
}
}
case MVM_OP_box_s: {
break;
case MVM_OP_box_s:
if (repr_data->num_attributes == 1 && repr_data->unbox_str_slot >= 0 &&
!(st->mode_flags & MVM_FINALIZE_TYPE)) {
MVMSTable *embedded_st = repr_data->flattened_stables[repr_data->unbox_str_slot];
Expand All @@ -1670,7 +1696,7 @@ static void spesh(MVMThreadContext *tc, MVMSTable *st, MVMSpeshGraph *g, MVMSpes
MVM_spesh_usages_add_by_reg(tc, g, ins->operands[0], ins);
}
}
}
break;
}
}

Expand Down
48 changes: 43 additions & 5 deletions src/core/interp.c
Expand Up @@ -5806,8 +5806,24 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
goto NEXT;
}
OP(sp_fastbox_bi): {
//w(obj) int16 sslot int16 r(int64) :pure
MVM_panic(1, "sp_fastbox_bi NYI");
MVMint64 value = GET_REG(cur_op, 8).i64;
MVMuint16 size = GET_UI16(cur_op, 2);
MVMObject *obj = MVM_gc_allocate_nursery(tc, size);
MVMP6bigintBody *body = (MVMP6bigintBody *)((char *)obj + GET_UI16(cur_op, 6));
#if MVM_GC_DEBUG
if (tc->allocate_in_gen2)
MVM_panic(1, "Illegal use of sp_fastbox_i when gen2 allocation flag set");
#endif
obj->st = (MVMSTable *)tc->cur_frame->effective_spesh_slots[GET_UI16(cur_op, 4)];
obj->header.size = size;
obj->header.owner = tc->thread_id;
if (MVM_IS_32BIT_INT(value)) {
body->u.smallint.value = (MVMint32)value;
body->u.smallint.flag = MVM_BIGINT_32_FLAG;
}
else {
MVM_p6bigint_store_as_mp_int(body, value);
}
cur_op += 10;
goto NEXT;
}
Expand All @@ -5834,9 +5850,31 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
goto NEXT;
}
OP(sp_fastbox_bi_ic): {
//w(obj) int16 sslot int16 r(int64) :pure
MVM_panic(1, "sp_fastbox_bi_ic NYI");
cur_op += 10;
MVMint64 value = GET_REG(cur_op, 8).i64;
if (value >= -1 && value < 15) {
MVMint16 slot = GET_UI16(cur_op, 10);
GET_REG(cur_op, 0).o = tc->instance->int_const_cache->cache[slot][value + 1];
}
else {
MVMuint16 size = GET_UI16(cur_op, 2);
MVMObject *obj = MVM_gc_allocate_nursery(tc, size);
MVMP6bigintBody *body = (MVMP6bigintBody *)((char *)obj + GET_UI16(cur_op, 6));
#if MVM_GC_DEBUG
if (tc->allocate_in_gen2)
MVM_panic(1, "Illegal use of sp_fastbox_i when gen2 allocation flag set");

This comment has been minimized.

Copy link
@MasterDuke17

MasterDuke17 Aug 16, 2018

Contributor

Do you care that this says illegal sp_fastbox_i instead of sp_fastbox_bi_ic (same with some of the other new "Illegal use of ...")?

This comment has been minimized.

Copy link
@jnthn

jnthn Aug 16, 2018

Author Member

No, it was just copy pasta

#endif
obj->st = (MVMSTable *)tc->cur_frame->effective_spesh_slots[GET_UI16(cur_op, 4)];
obj->header.size = size;
obj->header.owner = tc->thread_id;
if (MVM_IS_32BIT_INT(value)) {
body->u.smallint.value = (MVMint32)value;
body->u.smallint.flag = MVM_BIGINT_32_FLAG;
}
else {
MVM_p6bigint_store_as_mp_int(body, value);
}
}
cur_op += 12;
goto NEXT;
}
OP(sp_deref_get_i64): {
Expand Down
2 changes: 2 additions & 0 deletions src/jit/graph.c
Expand Up @@ -1826,6 +1826,8 @@ static MVMint32 consume_ins(MVMThreadContext *tc, MVMJitGraph *jg,
/* Specialized boxings */
case MVM_OP_sp_fastbox_i:
case MVM_OP_sp_fastbox_i_ic:
case MVM_OP_sp_fastbox_bi:
case MVM_OP_sp_fastbox_bi_ic:
jg_append_primitive(tc, jg, ins);
break;
/* Unspecialized parameter access */
Expand Down
29 changes: 26 additions & 3 deletions src/jit/x64/emit.dasc
Expand Up @@ -2177,7 +2177,9 @@ void MVM_jit_emit_primitive(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJ
break;
}
case MVM_OP_sp_fastbox_i:
case MVM_OP_sp_fastbox_i_ic: {
case MVM_OP_sp_fastbox_i_ic:
case MVM_OP_sp_fastbox_bi:
case MVM_OP_sp_fastbox_bi_ic: {
MVMint32 use_cache = op == MVM_OP_sp_fastbox_i_ic;
MVMint16 offset = ins->operands[3].lit_i16;
MVMint16 val = ins->operands[4].reg.orig;
Expand All @@ -2197,8 +2199,29 @@ void MVM_jit_emit_primitive(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJ
|1:
}
emit_fastcreate(tc, compiler, jg, ins);
| mov TMP1, WORK[val];
| mov qword [RV+offset], TMP1;
| mov TMP3, WORK[val];
if (op == MVM_OP_sp_fastbox_i || op == MVM_OP_sp_fastbox_i_ic) {
/* Normal integer */
| mov qword [RV+offset], TMP3;
}
else {
/* Big integer; if it's in smallint range we poke it in directly,
* and if not we do a function call to create a bigint. */
MVMuint16 val_offset = offset + 4;
| cmp TMP3, qword 2147483647LL
| jg >3
| cmp TMP3, qword -12147483647LL
| jl >3
| mov dword [RV+offset], 0xFFFFFFFFLL
| mov dword [RV+val_offset], TMP3d
| jmp >4
|3:
| mov ARG1, RV
| add ARG1, offset
| mov ARG2, TMP3
| callp &MVM_p6bigint_store_as_mp_int;
|4:
}
if (use_cache) {
|2:
}
Expand Down

0 comments on commit 8fac6c3

Please sign in to comment.