pike.git / src / interpret_functions.h

version» Context lines:

pike.git/src/interpret_functions.h:3173:    s = ITEM(a);    for(i = 0; i < len-1; i++) {    assign_svalue_no_free(s + i, save_sp + i);    }    assign_svalue_no_free(s + i, Pike_sp-1);       pop_stack();    }    });    + OPCODE1(F_PUSH_CATCHES, "push_catches", I_UPDATE_SP, { +  struct catch_context *cc = Pike_interpreter.catch_ctx; +  while (arg1 > 0) { +  if (!cc) { +  Pike_error("PUSH_CATCHES: Lost track of catch.\n"); +  } +  push_int(Pike_interpreter.evaluator_stack + cc->recovery.stack_pointer - +  frame_get_save_sp(Pike_fp)); +  push_int(Pike_interpreter.mark_stack + cc->recovery.mark_sp - +  Pike_fp->save_mark_sp); +  cc = cc->prev; +  arg1--; +  } +  }); +  + /* Ideally this ought to be an OPCODE0_PTRRETURN but I don't fancy +  * adding that variety to this macro hell. At the end of the day there +  * wouldn't be any difference anyway afaics. /mast */ + OPCODE0_PTRJUMP(F_CATCH_AT, "catch_at", I_UPDATE_ALL|I_RETURN, { +  PIKE_OPCODE_T *addr; +  +  { +  struct catch_context *new_catch_ctx; +  +  if ((TYPEOF(Pike_sp[-1]) != PIKE_T_INT) || +  (TYPEOF(Pike_sp[-2]) != PIKE_T_INT)) { +  Pike_error("CATCH_AT: Invalid arguments.\n"); +  } +  +  new_catch_ctx = alloc_catch_context(); +  DO_IF_REAL_DEBUG ( +  new_catch_ctx->frame = Pike_fp; +  init_recovery (&new_catch_ctx->recovery, 0, 0, PERR_LOCATION()); +  ); +  DO_IF_NOT_REAL_DEBUG ( +  init_recovery (&new_catch_ctx->recovery, 0); +  ); +  +  new_catch_ctx->recovery.stack_pointer = +  frame_get_save_sp(Pike_fp) + Pike_sp[-2].u.integer - +  Pike_interpreter.evaluator_stack; +  new_catch_ctx->recovery.mark_sp = +  Pike_fp->save_mark_sp + Pike_sp[-1].u.integer - +  Pike_interpreter.mark_stack; +  Pike_sp -= 2; +  +  JUMP_SET_TO_PC_AT_NEXT (addr); +  new_catch_ctx->continue_reladdr = GET_JUMP() +  /* We need to run the entry prologue... */ +  - ENTRY_PROLOGUE_SIZE; +  +  new_catch_ctx->next_addr = addr; +  new_catch_ctx->prev = Pike_interpreter.catch_ctx; +  Pike_interpreter.catch_ctx = new_catch_ctx; +  DO_IF_DEBUG({ +  TRACE((3,"- Pushed catch context %p\n", new_catch_ctx)); +  }); +  } +  +  /* Need to adjust next_addr by sizeof(INT32) to skip past the jump +  * address to the continue position after the catch block. */ +  addr = (PIKE_OPCODE_T *) ((INT32 *) addr + 1); +  +  if (Pike_interpreter.catching_eval_jmpbuf) { +  /* There's already a catching_eval_instruction around our +  * eval_instruction, so we can just continue. */ +  debug_malloc_touch_named (Pike_interpreter.catch_ctx, "(1)"); +  /* Skip past the entry prologue... */ +  addr += ENTRY_PROLOGUE_SIZE; +  SET_PROG_COUNTER(addr); +  FETCH; +  DO_IF_DEBUG({ +  TRACE((3,"- In active catch; continuing at %p\n", addr)); +  }); +  JUMP_DONE; +  } +  +  else { +  debug_malloc_touch_named (Pike_interpreter.catch_ctx, "(2)"); +  +  while (1) { +  /* Loop here every time an exception is caught. Once we've +  * gotten here and set things up to run eval_instruction from +  * inside catching_eval_instruction, we keep doing it until it's +  * time to return. */ +  +  int res; +  +  DO_IF_DEBUG({ +  TRACE((3,"- Activating catch; calling %p in context %p\n", +  addr, Pike_interpreter.catch_ctx)); +  }); +  +  res = catching_eval_instruction (addr); +  +  DO_IF_DEBUG({ +  TRACE((3,"- catching_eval_instruction(%p) returned %d\n", +  addr, res)); +  }); +  +  if (res != -3) { +  /* There was an inter return inside the evaluated code. Just +  * propagate it. */ +  DO_IF_DEBUG ({ +  TRACE((3,"- Returning from catch.\n")); +  if (res != -1) Pike_fatal ("Unexpected return value from " +  "catching_eval_instruction: %d\n", res); +  }); +  break; +  } +  +  else { +  /* Caught an exception. */ +  struct catch_context *cc = Pike_interpreter.catch_ctx; +  +  DO_IF_DEBUG ({ +  TRACE((3,"- Caught exception. catch context: %p\n", cc)); +  if (!cc) Pike_fatal ("Catch context dropoff.\n"); +  if (cc->frame != Pike_fp) +  Pike_fatal ("Catch context doesn't belong to this frame.\n"); +  }); +  +  debug_malloc_touch_named (cc, "(3)"); +  UNSETJMP (cc->recovery); +  move_svalue (Pike_sp++, &throw_value); +  mark_free_svalue (&throw_value); +  low_destruct_objects_to_destruct(); +  +  if (cc->continue_reladdr < 0) +  FAST_CHECK_THREADS_ON_BRANCH(); +  addr = cc->next_addr + cc->continue_reladdr; +  +  DO_IF_DEBUG({ +  TRACE((3,"- Popping catch context %p ==> %p\n", +  cc, cc->prev)); +  if (!addr) Pike_fatal ("Unexpected null continue addr.\n"); +  }); +  +  Pike_interpreter.catch_ctx = cc->prev; +  really_free_catch_context (cc); +  } +  } +  +  INTER_RETURN; +  } + }); +    /*   #undef PROG_COUNTER   */