-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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