void ThreadStackTrace::dump_stack_at_safepoint(int maxDepth) { assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped"); if (_thread->has_last_Java_frame()) { RegisterMap reg_map(_thread); vframe* start_vf = _thread->last_java_vframe(®_map); int count = 0; for (vframe* f = start_vf; f; f = f->sender() ) { if (f->is_java_frame()) { javaVFrame* jvf = javaVFrame::cast(f); add_stack_frame(jvf); count++; } else { // Ignore non-Java frames } if (maxDepth > 0 && count == maxDepth) { // Skip frames if more than maxDepth break; } } } if (_with_locked_monitors) { // Iterate inflated monitors and find monitors locked by this thread // not found in the stack InflatedMonitorsClosure imc(_thread, this); ObjectSynchronizer::monitors_iterate(&imc); } }
void mop_call(zword dest, unsigned num_args, zword *args, int result_var) { unsigned i; offset destPC; unsigned num_local; if(dest == 0) { check_set_var(result_var, 0); return; } destPC = UNPACKR(dest); /* printf("call %x -> %x\n", oldPC, destPC); */ #ifndef FAST if(destPC > game_size) { n_show_error(E_INSTR, "call past end of story", dest); check_set_var(result_var, 0); return; } #endif num_local = HIBYTE(destPC); /* first byte is # of local variables */ #ifndef FAST if(num_local > 15) { n_show_error(E_INSTR, "call to non-function (initial byte > 15)", dest); check_set_var(result_var, 0); return; } #endif destPC++; /* Go on past the variable count */ if(zversion < 5) { for(i = num_args; i < num_local; i++) args[i] = HIWORD(destPC + i * ZWORD_SIZE); /* Load default locals */ destPC += num_local * ZWORD_SIZE; } else { for(i = num_args; i < num_local; i++) args[i] = 0; /* locals default to zero */ } add_stack_frame(PC, num_local, args, num_args, result_var); PC = destPC; /*n_show_debug(E_DEBUG, "function starting", dest);*/ }
BOOL quetzal_stack_save(strid_t stream) { unsigned frame_num = 0; if(zversion == 6) frame_num++; if(!verify_stack()) { n_show_error(E_SAVE, "stack did not pass verification before saving", 0); return FALSE; } /* We have to look one ahead to see how much stack space a frame uses; when we get to the last frame, there will be no next frame, so this won't work if there wasn't a frame there earlier with the correct info. Add and remove a frame to make things happy */ add_stack_frame(0, 0, NULL, 0, 0); remove_stack_frame(); for(; frame_num <= frame_count; frame_num++) { unsigned n; int num_locals; unsigned stack_size; glui32 qframe[5]; const unsigned char argarray[8] = { b00000000, b00000001, b00000011, b00000111, b00001111, b00011111, b00111111, b01111111 }; qframe[qreturnPC] = stack_frames[frame_num].return_PC; qframe[qvar] = stack_frames[frame_num].result_variable; num_locals = stack_frames[frame_num].num_locals; if(num_locals > 15) { n_show_error(E_SAVE, "num_locals too big", num_locals); return FALSE; } qframe[qflags] = num_locals; if(stack_frames[frame_num].result_variable == -1) { qframe[qflags] |= b00010000; qframe[qvar] = 0; } if(stack_frames[frame_num].arguments > 7) { n_show_error(E_SAVE, "too many function arguments", stack_frames[frame_num].arguments); return FALSE; } qframe[qargs] = argarray[stack_frames[frame_num].arguments]; stack_size = (stack_frames[frame_num+1].stack_stack_start - stack_frames[frame_num].stack_stack_start - num_locals); qframe[qeval] = stack_size; if(frame_num == 0) { qframe[qreturnPC] = 0; qframe[qflags] = 0; qframe[qvar] = 0; qframe[qargs] = 0; } emptystruct(stream, qstackframe, qframe); for(n = 0; n < num_locals + stack_size; n++) { unsigned char v[ZWORD_SIZE]; zword z = stack_stack[stack_frames[frame_num].stack_stack_start + n]; MSBencodeZ(v, z); w_glk_put_buffer_stream(stream, (char *) v, ZWORD_SIZE); } } return TRUE; }
BOOL quetzal_stack_restore(strid_t stream, glui32 qsize) { glui32 i = 0; int num_frames = 0; kill_stack(); init_stack(1024, 128); while(i < qsize) { unsigned n; unsigned num_locals; zword locals[16]; int num_args; int var; glui32 qframe[5]; i += fillstruct(stream, qstackframe, qframe, NULL); if(qframe[qreturnPC] > total_size) { n_show_error(E_SAVE, "function return PC past end of memory", qframe[qreturnPC]); return FALSE; } if((qframe[qflags] & b11100000) != 0) { n_show_error(E_SAVE, "expected top bits of flag to be zero", qframe[qflags]); return FALSE; } var = qframe[qvar]; if(qframe[qflags] & b00010000) /* from a call_n */ var = -1; num_locals = qframe[qflags] & b00001111; if(num_locals > 15) { n_show_error(E_SAVE, "too many locals", num_locals); return FALSE; } num_args = 0; switch(qframe[qargs]) { default: n_show_error(E_SAVE, "invalid argument count", qframe[qargs]); return FALSE; case b01111111: num_args++; case b00111111: num_args++; case b00011111: num_args++; case b00001111: num_args++; case b00000111: num_args++; case b00000011: num_args++; case b00000001: num_args++; case b00000000: ; } for(n = 0; n < num_locals; n++) { unsigned char v[ZWORD_SIZE]; glk_get_buffer_stream(stream, (char *) v, ZWORD_SIZE); locals[n] = MSBdecodeZ(v); i+=ZWORD_SIZE; } if(zversion != 6 && num_frames == 0) ; /* dummy stack frame; don't really use it */ else add_stack_frame(qframe[qreturnPC], num_locals, locals, num_args, var); for(n = 0; n < qframe[qeval]; n++) { unsigned char v[ZWORD_SIZE]; glk_get_buffer_stream(stream, (char *) v, ZWORD_SIZE); stack_push(MSBdecodeZ(v)); i += ZWORD_SIZE; } num_frames++; } if(!verify_stack()) { n_show_error(E_SAVE, "restored stack fails verification", 0); return FALSE; } return TRUE; }