static void get_callstack(value* sp, intnat trap_spoff,
                          struct stack_info* stack,
                          intnat max_frames,
                          code_t** trace, intnat* trace_size)
{
  CAMLnoalloc;
  struct stack_info* parent = Stack_parent(stack);
  value *stack_high = Stack_high(stack);
  value* saved_sp = sp;
  intnat saved_trap_spoff = trap_spoff;

  /* first compute the size of the trace */
  {
    *trace_size = 0;
    while (*trace_size < max_frames) {
      code_t p = caml_next_frame_pointer(stack_high, &sp, &trap_spoff);
      if (p == NULL) {
        if (parent == NULL) break;
        sp = parent->sp;
        trap_spoff = Long_val(sp[0]);
        stack_high = Stack_high(parent);
        parent = Stack_parent(parent);
      } else {
        ++*trace_size;
      }
    }
  }

  *trace = caml_stat_alloc(sizeof(code_t*) * *trace_size);

  sp = saved_sp;
  parent = Stack_parent(stack);
  stack_high = Stack_high(stack);
  trap_spoff = saved_trap_spoff;

  /* then collect the trace */
  {
    uintnat trace_pos = 0;

    while (trace_pos < *trace_size) {
      code_t p = caml_next_frame_pointer(stack_high, &sp, &trap_spoff);
      if (p == NULL) {
        sp = parent->sp;
        trap_spoff = Long_val(sp[0]);
        stack_high = Stack_high(parent);
        parent = Stack_parent(parent);
      } else {
        (*trace)[trace_pos] = p;
        ++trace_pos;
      }
    }
  }
}
void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise)
{
  if (pc != NULL) pc = pc - 1;
  if (exn != caml_read_root(Caml_state->backtrace_last_exn) || !reraise) {
    Caml_state->backtrace_pos = 0;
    caml_modify_root(Caml_state->backtrace_last_exn, exn);
  }

  if (Caml_state->backtrace_buffer == NULL &&
      caml_alloc_backtrace_buffer() == -1)
    return;

  if (Caml_state->backtrace_pos >= BACKTRACE_BUFFER_SIZE) return;
  /* testing the code region is needed: PR#1554 */
  if (find_debug_info(pc) != NULL)
    Caml_state->backtrace_buffer[Caml_state->backtrace_pos++] = pc;

  /* Traverse the stack and put all values pointing into bytecode
     into the backtrace buffer. */
  value *trap_sp = Stack_high(Caml_state->current_stack) + Caml_state->trap_sp_off;
  for (/*nothing*/; sp < trap_sp; sp++) {
    if (Is_long(*sp)) {
      code_t p = Pc_val(*sp);
      if (Caml_state->backtrace_pos >= BACKTRACE_BUFFER_SIZE) break;
      if (find_debug_info(p) != NULL)
        Caml_state->backtrace_buffer[Caml_state->backtrace_pos++] = p;
    }
  }
}
Beispiel #3
0
void caml_realloc_stack () {
  CAMLparam0();
  CAMLlocal2(old_stack, new_stack);
  /* All sizes are in bytes */
  asize_t size;
  uintnat stack_used;

  old_stack = caml_current_stack;
  stack_used = Stack_sp(old_stack);
  size = Wosize_val(old_stack);
  size *= 2;

  caml_gc_log ("Growing old_stack=0x%lx to %lu words\n", old_stack, size);
  new_stack = caml_alloc(size, Stack_tag);
  caml_gc_log ("New_stack=0x%lx\n", new_stack);

  memcpy(Stack_high(new_stack) - stack_used,
         Stack_high(old_stack) - stack_used,
         stack_used);

  Stack_sp(new_stack) = Stack_sp(old_stack);
  Stack_handle_value(new_stack) = Stack_handle_value(old_stack);
  Stack_handle_exception(new_stack) = Stack_handle_exception(old_stack);
  Stack_handle_effect(new_stack) = Stack_handle_effect(old_stack);
  Stack_parent(new_stack) = Stack_parent(old_stack);
  Stack_dirty(new_stack) = Val_long(0);

  if (Stack_dirty(old_stack) == Val_long(1)) {
    dirty_stack(new_stack);
  }

  load_stack(new_stack);

  /* Reset old stack */
  Stack_sp(old_stack) = 0;
  Stack_dirty(old_stack) = Val_long(0);
  Stack_handle_value(old_stack) = Val_long(0);
  Stack_handle_exception(old_stack) = Val_long(0);
  Stack_handle_effect(old_stack) = Val_long(0);
  Stack_parent(old_stack) = Val_unit;

  CAMLreturn0;
}
Beispiel #4
0
value caml_alloc_stack (value hval, value hexn, value heff) {
  CAMLparam3(hval, hexn, heff);
  CAMLlocal1(stack);
  char* sp;
  struct caml_context *ctxt;

  stack = caml_alloc(caml_init_fiber_wsz, Stack_tag);
  Stack_dirty(stack) = Val_long(0);
  Stack_handle_value(stack) = hval;
  Stack_handle_exception(stack) = hexn;
  Stack_handle_effect(stack) = heff;
  Stack_parent(stack) = Val_unit;

  sp = Stack_high(stack);
  /* Fiber exception handler that returns to parent */
  sp -= sizeof(value);
  *(value**)sp = (value*)caml_fiber_exn_handler;
  /* No previous exception frame */
  sp -= sizeof(value);
  *(uintnat*)sp = 0;
  /* Value handler that returns to parent */
  sp -= sizeof(value);
  *(value**)sp = (value*)caml_fiber_val_handler;

  /* Build a context */
  sp -= sizeof(struct caml_context);
  ctxt = (struct caml_context*)sp;
  ctxt->exception_ptr_offset = 2 * sizeof(value);
  ctxt->gc_regs = NULL;
  Stack_sp(stack) = 3 * sizeof(value) + sizeof(struct caml_context);

  caml_gc_log ("Allocate stack=0x%lx of %lu words\n",
               stack, caml_init_fiber_wsz);

  CAMLreturn (stack);
}
Beispiel #5
0
static void load_stack (value stack) {
  caml_stack_threshold = Stack_base(stack) + Stack_threshold;
  caml_top_of_stack = Stack_high(stack);
  caml_current_stack = stack;
}