Skip to content

Commit

Permalink
put some of annotations into backtrace. kinda works, kinda doesn't; n…
Browse files Browse the repository at this point in the history
…ot looking into it today.
  • Loading branch information
diakopter committed Aug 19, 2013
1 parent 799a294 commit 9ad92ba
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 16 deletions.
7 changes: 5 additions & 2 deletions src/6model/reprs/MVMStaticFrame.h
Expand Up @@ -63,8 +63,11 @@ struct MVMStaticFrameBody {
MVMuint32 pool_index;

/* Annotation details */
MVMuint32 num_annotations;
MVMuint8 *annotations;
MVMuint32 num_annotations;
MVMBytecodeAnnotation *annotations;

/* Cached instruction offsets */
MVMuint8 *instr_offsets;
};
struct MVMStaticFrame {
MVMObject common;
Expand Down
16 changes: 15 additions & 1 deletion src/core/bytecode.c
Expand Up @@ -367,7 +367,7 @@ static MVMStaticFrame ** deserialize_frames(MVMThreadContext *tc, MVMCompUnit *c
cleanup_all(tc, rs);
MVM_exception_throw_adhoc(tc, "Frame annotation segment overflows bytecode stream");
}
static_frame_body->annotations = rs->annotation_seg + annot_offset;
static_frame_body->annotations = (MVMBytecodeAnnotation *)(rs->annotation_seg + annot_offset);
static_frame_body->num_annotations = num_annotations;
}

Expand Down Expand Up @@ -574,3 +574,17 @@ void MVM_bytecode_unpack(MVMThreadContext *tc, MVMCompUnit *cu) {
/* Clean up reader state. */
cleanup_all(tc, rs);
}

/* returns the annotation for that bytecode offset */
MVMBytecodeAnnotation * MVM_bytecode_resolve_annotation(MVMThreadContext *tc, MVMStaticFrameBody *sfb, MVMuint32 offset) {
MVMBytecodeAnnotation *ba = NULL;
MVMuint32 i, j;

if (offset >= sfb->bytecode_size)
return NULL;
for (i = 0, j = 0; i <= offset && j < sfb->num_annotations; i++)
/* if we reached an annotation point, advance to the next */
if (!ba || ba->bytecode_offset == i)
ba = &sfb->annotations[j++];
return ba;
}
1 change: 1 addition & 0 deletions src/core/bytecode.h
@@ -1,4 +1,5 @@
void MVM_bytecode_unpack(MVMThreadContext *tc, MVMCompUnit *cu);
MVMBytecodeAnnotation * MVM_bytecode_resolve_annotation(MVMThreadContext *tc, MVMStaticFrameBody *sfb, MVMuint32 offset);

/* Steal endianness from APR */
#ifdef APR_IS_BIGENDIAN
Expand Down
44 changes: 33 additions & 11 deletions src/core/exceptions.c
Expand Up @@ -181,6 +181,31 @@ static void unwind_after_handler(MVMThreadContext *tc, void *sr_data) {
free(ah);
}

static char * backtrace_line(MVMThreadContext *tc, MVMFrame *cur_frame, MVMuint16 not_top) {
MVMString *filename = cur_frame->static_info->body.cu->body.filename;
MVMString *name = cur_frame->static_info->body.name;
char *o = malloc(1024);
MVMuint8 *cur_op = !not_top ? (*tc->interp_cur_op) : cur_frame->return_address;
MVMuint32 offset = cur_op - cur_frame->static_info->body.bytecode;
MVMuint32 instr = MVM_bytecode_offset_to_instr_idx(tc, cur_frame->static_info, offset);
MVMBytecodeAnnotation *annot = MVM_bytecode_resolve_annotation(tc, &cur_frame->static_info->body, offset);
char *tmp1 = NULL;

sprintf(o, " line %d in %s (op %s, instr %u%s, frame %s, compunit %s)",
annot ? annot->line_number + 1 : 1,
annot ? (tmp1 = MVM_string_utf8_encode(tc,
cur_frame->static_info->body.cu->body.strings[
annot->filename_string_heap_index], NULL
)) : "<unknown>",
(offset && instr) ? MVM_op_get_op(*cur_op, *(cur_op+1))->name : "<unknown>",
instr,
instr ? "" : "<unknown>",
name ? MVM_string_utf8_encode(tc, name, NULL) : "<anonymous frame>",
filename ? MVM_string_utf8_encode(tc, filename, NULL) : "<ephemeral file>");
if (tmp1) free(tmp1);
return o;
}

/* Returns the lines (backtrace) of an exception-object as an array. */
MVMObject * MVM_exception_backtrace_strings(MVMThreadContext *tc, MVMObject *ex_obj) {
MVMException *ex;
Expand All @@ -198,9 +223,11 @@ MVMObject * MVM_exception_backtrace_strings(MVMThreadContext *tc, MVMObject *ex_
MVMROOT(tc, arr, {
while (cur_frame != NULL) {
MVMObject *pobj = MVM_repr_alloc_init(tc, tc->instance->boot_types->BOOTStr);
MVM_repr_set_str(tc, pobj, cur_frame->static_info->body.name);
MVM_repr_push_o(tc, arr, pobj);
cur_frame = cur_frame->caller;
MVMROOT(tc, pobj, {
MVM_repr_set_str(tc, pobj, cur_frame->static_info->body.name);
MVM_repr_push_o(tc, arr, pobj);
cur_frame = cur_frame->caller;
});
}
});

Expand All @@ -209,15 +236,10 @@ MVMObject * MVM_exception_backtrace_strings(MVMThreadContext *tc, MVMObject *ex_

/* Dumps a backtrace relative to the current frame to stderr. */
static void dump_backtrace(MVMThreadContext *tc) {
MVMFrame *cur_frame = tc->cur_frame, *last = NULL;
MVMFrame *cur_frame = tc->cur_frame;
MVMuint32 count = 0;
while (cur_frame != NULL && cur_frame != last && count++ < 256) {
MVMString *filename = cur_frame->static_info->body.cu->body.filename;
MVMString *name = cur_frame->static_info->body.name;
last = cur_frame;
fprintf(stderr, " in %s, %s\n",
name ? MVM_string_utf8_encode(tc, name, NULL) : "<anonymous frame>",
filename ? MVM_string_utf8_encode(tc, filename, NULL) : "<ephemeral file>");
while (cur_frame != NULL) {
fprintf(stderr, "%s\n", backtrace_line(tc, cur_frame, count++));
cur_frame = cur_frame->caller;
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/core/exceptions.h
Expand Up @@ -57,6 +57,12 @@ struct MVMActiveHandler {
MVMActiveHandler *next_handler;
};

struct MVMBytecodeAnnotation {
MVMuint32 bytecode_offset;
MVMuint16 filename_string_heap_index;
MVMuint32 line_number;
};

/* Exception related functions. */
MVMObject * MVM_exception_backtrace_strings(MVMThreadContext *tc, MVMObject *exObj);
void MVM_exception_throwcat(MVMThreadContext *tc, MVMuint8 mode, MVMuint32 cat, MVMRegister *resume_result);
Expand Down
24 changes: 23 additions & 1 deletion src/core/validation.c
Expand Up @@ -267,7 +267,6 @@ void MVM_validate_static_frame(MVMThreadContext *tc, MVMStaticFrame *static_fram
"Bytecode validation error: branch to a non-op start position at instruction %u", i);
}
}
cleanup_all(tc, labels);
/* check that the last op is a return of some sort so we don't run off the */
/* XXX TODO maybe also allow tailcalls of some sort, but currently compiler.c
* adds the trailing return anyway, so... */
Expand All @@ -280,4 +279,27 @@ void MVM_validate_static_frame(MVMThreadContext *tc, MVMStaticFrame *static_fram
MVM_exception_throw_adhoc(tc,
"Bytecode validation error: missing final return instruction");
}

/* successfully passed validation. Cache the located instruction offsets. */
static_frame_body->instr_offsets = labels;
}

/* Returns nonzero if the provided offset is the start of an instruction in the
* executable bytecode range. The value returned is the instruction index. The
* caller already knows that offset 0 is an instruction index (and which one!)
* so it simply doesn't ask in that case. */
MVMuint32 MVM_bytecode_offset_to_instr_idx(MVMThreadContext *tc,
MVMStaticFrame *static_frame, MVMuint32 offset) {
MVMuint8 *labels = static_frame->body.instr_offsets;
MVMuint32 i, idx;
if (offset >= static_frame->body.bytecode_size
|| (labels[offset] & MVM_val_op_boundary) == 0) {
return 0;
}
for (i = 0; i < offset; i++) {
if (labels[i] & MVM_val_op_boundary) {
idx++;
}
}
return idx;
}
4 changes: 3 additions & 1 deletion src/core/validation.h
@@ -1,2 +1,4 @@

void MVM_validate_static_frame(MVMThreadContext *tc, MVMStaticFrame *static_frame);
void MVM_validate_static_frame(MVMThreadContext *tc, MVMStaticFrame *static_frame);
MVMuint32 MVM_bytecode_offset_to_instr_idx(MVMThreadContext *tc,
MVMStaticFrame *static_frame, MVMuint32 offset);
1 change: 1 addition & 0 deletions src/types.h
Expand Up @@ -9,6 +9,7 @@ typedef struct MVMArrayREPRData MVMArrayREPRData;
typedef struct MVMAttributeIdentifier MVMAttributeIdentifier;
typedef struct MVMBoolificationSpec MVMBoolificationSpec;
typedef struct MVMBootTypes MVMBootTypes;
typedef struct MVMBytecodeAnnotation MVMBytecodeAnnotation;
typedef struct MVMCallCapture MVMCallCapture;
typedef struct MVMCallCaptureBody MVMCallCaptureBody;
typedef struct MVMCallsite MVMCallsite;
Expand Down

0 comments on commit 9ad92ba

Please sign in to comment.