Skip to content

Instantly share code, notes, and snippets.

@timo
Last active July 7, 2017 01:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timo/f85f49d0e4b1e9dc52f312e64caeb3cb to your computer and use it in GitHub Desktop.
Save timo/f85f49d0e4b1e9dc52f312e64caeb3cb to your computer and use it in GitHub Desktop.
this is how you don't teach the guard tree interpreter how to skip virtual function calls
diff --git a/src/6model/containers.c b/src/6model/containers.c
index 6f941b1..3e6f9d3 100644
--- a/src/6model/containers.c
+++ b/src/6model/containers.c
@@ -123,7 +123,8 @@ static const MVMContainerSpec code_pair_spec = {
code_pair_serialize,
code_pair_deserialize,
code_pair_can_store,
- 0
+ 0,
+ -1
};
static void code_pair_set_container_spec(MVMThreadContext *tc, MVMSTable *st) {
@@ -367,7 +368,8 @@ static const MVMContainerSpec native_ref_spec = {
native_ref_serialize,
native_ref_deserialize,
native_ref_can_store,
- 1
+ 1,
+ -1
};
static void native_ref_set_container_spec(MVMThreadContext *tc, MVMSTable *st) {
diff --git a/src/6model/containers.h b/src/6model/containers.h
index 2d7bbfe..2c1f1cd 100644
--- a/src/6model/containers.h
+++ b/src/6model/containers.h
@@ -51,6 +51,10 @@ struct MVMContainerSpec {
* code. This means the VM knows it can safely decontainerize in places
* it would not be safe or practical to return to the interpreter. */
MVMuint8 fetch_never_invokes;
+
+ /* Set this to zero or above if fetching involves just grabbing a pointer
+ * at an offset to the object's data section. Otherwise, -1. */
+ MVMint16 fetch_simple_offset;
};
/* A container configurer knows how to attach a certain type of container
diff --git a/src/6model/reprs/P6opaque.c b/src/6model/reprs/P6opaque.c
index f87ad45..d78f58a 100644
--- a/src/6model/reprs/P6opaque.c
+++ b/src/6model/reprs/P6opaque.c
@@ -1620,8 +1620,14 @@ static const MVMREPROps P6opaque_this_repr = {
/* This is meant to be called in a debugging session and not used anywhere else.
* Plese don't delete. */
static void dump_p6opaque(MVMThreadContext *tc, MVMObject *obj, int nested) {
- MVMP6opaqueREPRData *repr_data = (MVMP6opaqueREPRData *)STABLE(obj)->REPR_data;
- MVMP6opaqueBody *data = MVM_p6opaque_real_data(tc, OBJECT_BODY(obj));
+ MVMP6opaqueREPRData *repr_data;
+ MVMP6opaqueBody *data;
+ if (STABLE(obj)->REPR->ID != MVM_REPR_ID_P6opaque) {
+ fprintf(stderr, "cannot p6opaque-dump this object, because it is a %s.\n",
+ STABLE(obj)->REPR->name);
+ }
+ repr_data = (MVMP6opaqueREPRData *)STABLE(obj)->REPR_data;
+ data = MVM_p6opaque_real_data(tc, OBJECT_BODY(obj));
if (repr_data) {
MVMint16 const num_attributes = repr_data->num_attributes;
MVMint16 cur_attribute = 0;
@@ -1654,10 +1660,22 @@ static void dump_p6opaque(MVMThreadContext *tc, MVMObject *obj, int nested) {
}
}
else {
- MVMString * const s = attr_st->REPR->box_funcs.get_str(tc, attr_st, obj, (char *)data + offset);
- char * const str = MVM_string_utf8_encode_C_string(tc, s);
- fprintf(stderr, "='%s'", str);
- MVM_free(str);
+ MVMuint16 reprid = attr_st->REPR->ID;
+ if (reprid == MVM_REPR_ID_MVMString) {
+ char * str = MVM_string_utf8_encode_C_string(tc, (MVMString *)get_obj_at_offset(data, offset));
+ fprintf(stderr, "='%s'", str);
+ MVM_free(str);
+ } else if (reprid == MVM_REPR_ID_P6str) {
+ if (attr_st->REPR->box_funcs.get_str) {
+ MVMString * s = attr_st->REPR->box_funcs.get_str(tc, attr_st, obj, (char *)data + offset);
+ char * str = MVM_string_utf8_encode_C_string(tc, s);
+ fprintf(stderr, "='%s'", str);
+ MVM_free(str);
+ }
+ } else {
+ MVMREPROps const *repr = MVM_repr_get_by_id(tc, reprid);
+ fprintf(stderr, "=(%s)", repr->name);
+ }
}
}
if (cur_attribute++ < num_attributes - 1)
@@ -1666,6 +1684,15 @@ static void dump_p6opaque(MVMThreadContext *tc, MVMObject *obj, int nested) {
cur_map_entry++;
}
}
+ /*if (repr_data->unbox_slots) {*/
+ /*MVMuint16 i;*/
+ /*for (i = 0; i < MVM_REPR_NO_UNBOX_SLOT; i++) {*/
+ /*if (repr_data->unbox_slots[i] != MVM_P6OPAQUE_NO_UNBOX_SLOT) {*/
+ /*MVMREPROps *ops = MVM_repr_get_by_id(tc, i);*/
+
+ /*}*/
+ /*}*/
+ /*}*/
fprintf(stderr, nested ? ")" : ")\n");
}
else {
diff --git a/src/core/bytecodedump.c b/src/core/bytecodedump.c
index 97637b3..1f2aba2 100644
--- a/src/core/bytecodedump.c
+++ b/src/core/bytecodedump.c
@@ -474,6 +474,11 @@ void MVM_dump_bytecode_staticframe(MVMThreadContext *tc, MVMStaticFrame *frame)
MVMuint32 l = 0;
char *o = MVM_calloc(s, sizeof(char));
+ if (!frame->body.fully_deserialized) {
+ MVM_bytecode_finish_frame(tc, frame->body.cu, frame, 1);
+ }
+
+
bytecode_dump_frame_internal(tc, frame, NULL, NULL, NULL, &o, &s, &l);
o[l] = 0;
diff --git a/src/spesh/arg_guard.c b/src/spesh/arg_guard.c
index 9e21e57..df6569e 100644
--- a/src/spesh/arg_guard.c
+++ b/src/spesh/arg_guard.c
@@ -161,12 +161,18 @@ MVMuint32 get_type_check_node(MVMThreadContext *tc, MVMSpeshArgGuard *ag,
* we can know if there is such a node for this container type by just looking
* at the "yes" branch of the base node we are passed. */
MVMuint32 get_rw_cont_node(MVMThreadContext *tc, MVMSpeshArgGuard *ag,
- MVMuint32 base_node) {
+ MVMuint32 base_node, MVMSTable *type) {
MVMuint32 yes_node = ag->nodes[base_node].yes;
+ MVMint32 offset;
if (yes_node && ag->nodes[yes_node].op == MVM_SPESH_GUARD_OP_DEREF_RW)
return yes_node;
+ if (type->container_spec && type->container_spec->fetch_never_invokes) {
+ offset = type->container_spec->fetch_simple_offset;
+ if (offset < 0)
+ offset = -1;
+ }
ag->nodes[ag->used_nodes].op = MVM_SPESH_GUARD_OP_DEREF_RW;
- ag->nodes[ag->used_nodes].offset = 0; /* TODO populate this properly */
+ ag->nodes[ag->used_nodes].offset = offset;
ag->nodes[ag->used_nodes].yes = 0;
ag->nodes[ag->used_nodes].no = yes_node;
ag->nodes[base_node].yes = ag->used_nodes;
@@ -179,9 +185,10 @@ MVMuint32 get_rw_cont_node(MVMThreadContext *tc, MVMSpeshArgGuard *ag,
* node is already in the tree at this point, *or* that there is an RW
* guard node and *then* the one we're looking for. */
MVMuint32 get_decont_node(MVMThreadContext *tc, MVMSpeshArgGuard *ag,
- MVMuint32 base_node) {
+ MVMuint32 base_node, MVMSTable *type) {
MVMuint32 check_node = ag->nodes[base_node].yes;
MVMuint32 update_no_node = 0;
+ MVMint16 offset;
if (check_node) {
if (ag->nodes[check_node].op == MVM_SPESH_GUARD_OP_DEREF_VALUE) {
return check_node;
@@ -199,8 +206,13 @@ MVMuint32 get_decont_node(MVMThreadContext *tc, MVMSpeshArgGuard *ag,
if (!update_no_node)
MVM_panic(1, "Spesh arg guard: unexpected tree structure adding deref value");
}
+ if (type->container_spec && type->container_spec->fetch_never_invokes) {
+ offset = type->container_spec->fetch_simple_offset;
+ if (offset < 0)
+ offset = -1;
+ }
ag->nodes[ag->used_nodes].op = MVM_SPESH_GUARD_OP_DEREF_VALUE;
- ag->nodes[ag->used_nodes].offset = 0; /* TODO populate this properly */
+ ag->nodes[ag->used_nodes].offset = offset;
ag->nodes[ag->used_nodes].yes = 0;
ag->nodes[ag->used_nodes].no = 0;
if (update_no_node)
@@ -217,9 +229,9 @@ MVMuint32 get_type_node(MVMThreadContext *tc, MVMSpeshArgGuard *ag, MVMuint32 ba
MVMuint32 current_node = get_load_node(tc, ag, base_node, arg_idx);
current_node = get_type_check_node(tc, ag, current_node, type->type, type->type_concrete);
if (type->rw_cont)
- current_node = get_rw_cont_node(tc, ag, current_node);
+ current_node = get_rw_cont_node(tc, ag, current_node, type->type->st);
if (type->decont_type) {
- current_node = get_decont_node(tc, ag, current_node);
+ current_node = get_decont_node(tc, ag, current_node, type->type->st);
current_node = get_type_check_node(tc, ag, current_node, type->decont_type,
type->decont_type_concrete);
}
@@ -369,10 +381,21 @@ MVMint32 MVM_spesh_arg_guard_run(MVMThreadContext *tc, MVMSpeshArgGuard *ag,
: agn->no;
break;
case MVM_SPESH_GUARD_OP_DEREF_VALUE: {
- /* TODO Use offset approach later to avoid these calls. */
MVMRegister dc;
+ MVMObject *other_result;
+ if (agn->offset >= 0) {
+ if (REPR(test)->ID == MVM_REPR_ID_P6opaque) {
+ char *data = MVM_p6opaque_real_data(tc, OBJECT_BODY(test));
+ other_result = *((MVMObject **)(data + agn->offset));
+ } else {
+ other_result = *(MVMObject**)((char *)test + agn->offset);
+ }
+ }
test->st->container_spec->fetch(tc, test, &dc);
test = dc.o;
+ if (other_result && other_result != test) {
+ MVM_oops(tc, "fetch and offset disagree.");
+ }
current_node = test ? agn->yes : agn->no;
break;
}
diff --git a/src/spesh/arg_guard.h b/src/spesh/arg_guard.h
index 8277636..75cbb49 100644
--- a/src/spesh/arg_guard.h
+++ b/src/spesh/arg_guard.h
@@ -67,7 +67,7 @@ struct MVMSpeshArgGuardNode {
/* Used by STABLE_CONC, STABLE_TYPE */
MVMSTable *st;
/* Used by DEREF_VALUE and DEREF_RW. */
- MVMuint32 offset;
+ MVMint32 offset;
/* Used by RESULT. */
MVMuint32 result;
};
diff --git a/src/vm/moar/ops/container.c b/src/vm/moar/ops/container.c
index f28e3b7..6648345 100644
--- a/src/vm/moar/ops/container.c
+++ b/src/vm/moar/ops/container.c
@@ -258,7 +258,8 @@ static const MVMContainerSpec rakudo_scalar_spec = {
rakudo_scalar_serialize,
rakudo_scalar_deserialize,
rakudo_scalar_can_store,
- 1
+ 1,
+ offsetof( Rakudo_Scalar, value ) - offsetof( MVMObjectStooge, data )
};
static void rakudo_scalar_set_container_spec(MVMThreadContext *tc, MVMSTable *st) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment