⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hipe_mode_switch.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 2 页
字号:
    DPRINTF("result == %#x (%s)", result, code_str(result));    HIPE_CHECK_PCB(p);    switch( result ) {      case HIPE_MODE_SWITCH_RES_RETURN: {	  hipe_return_from_native(p);	  reg[0] = p->def_arg_reg[0];	  DPRINTF("returning with r(0) == %#lx", reg[0]);	  break;      }      case HIPE_MODE_SWITCH_RES_THROW: {	  DPRINTF("native throws freason %#lx fvalue %#lx", p->freason, p->fvalue);	  hipe_throw_from_native(p);	  break;      }      case HIPE_MODE_SWITCH_RES_TRAP: {	  /*	   * Native code called a BIF, which "failed" with a TRAP to BEAM.	   * Prior to returning, the BIF stored (see BIF_TRAP<N>):	   * the callee's Export* in p->def_arg_reg[3]	   * the callee's parameters in p->def_arg_reg[0..2]	   * the callee's arity in p->arity (for BEAM gc purposes)	   *	   * We need to remove the BIF's parameters from the native	   * stack: to this end hipe_${ARCH}_glue.S overwrites p->arity	   * with the BIF's arity. We will recompute the callee's	   * arity by fetching it from its BEAM function head.	   */	  unsigned int i, is_recursive;	  /* Here p->arity still describes the original BIF's arity.	     Get rid of any stacked parameters in that call. */	  /* XXX: hipe_call_from_native_is_recursive() copies data to	     reg[], which is useless in the TRAP case. Maybe write a	     specialised hipe_trap_from_native_is_recursive() later. */	  is_recursive = hipe_call_from_native_is_recursive(p, reg);	  p->i = ((Export*)(p->def_arg_reg[3]))->address;	  p->arity = p->i[-1];	  for(i = 0; i < p->arity; ++i)	      reg[i] = p->def_arg_reg[i];	  if( is_recursive )	      hipe_push_beam_trap_frame(p, reg, p->arity);	  result = HIPE_MODE_SWITCH_RES_CALL;	  break;      }      case HIPE_MODE_SWITCH_RES_CALL: {	  /* Native code calls or tailcalls BEAM.	   *	   * p->i is the callee's BEAM code	   * p->arity is the callee's arity	   * p->def_arg_reg[] contains the register parameters	   * p->hipe.nsp[] contains the stacked parameters	   */	  if( hipe_call_from_native_is_recursive(p, reg) ) {	      /* BEAM called native, which now calls BEAM */	      hipe_push_beam_trap_frame(p, reg, p->arity);	  }	  break;      }      case HIPE_MODE_SWITCH_RES_CALL_CLOSURE: {	  /* Native code calls or tailcalls a closure in BEAM	   *	   * In native code a call to a closure of arity n looks like	   * F(A1, ..., AN, Closure),	   * Beam expects to get:	   * F(A1, ..., AN, FV1, ..., FVM, Closure)	   *  (Where Ai is argument i and FVi is free variable i)	   *	   * p->hipe.closure contains the closure	   * p->def_arg_reg[] contains the parameters (on SPARC)	   */	  ErlFunThing *closure;	  unsigned num_free, arity, i, is_recursive;	  HIPE_ASSERT(is_fun(p->hipe.closure));	  closure = (ErlFunThing*)fun_val(p->hipe.closure);	  num_free = closure->num_free;	  arity = closure->fe->address[-1] - num_free;	  /* Store the arity in p->arity for the stack popping. */	  p->arity = arity+1; /* +1 for the closure */	  /* Get parameters, don't do GC just yet. */	  is_recursive = hipe_call_from_native_is_recursive(p, reg);	  /* Append the free vars to the actual parameters. */	  for(i = 0; i < num_free; ++i)	      reg[arity+i] = closure->env[i];	  /* Put the closure as the last argument. */	  reg[arity+i] = p->hipe.closure;	  /* Make a call to the closure's BEAM code. */	  p->i = closure->fe->address;	  if( is_recursive ) {	      /* BEAM called native, which now calls BEAM.		 Need to put a trap-frame on the beam stack.		 This may cause GC, which is safe now that		 the arguments, free vars, and most		 importantly the closure, all are in reg[]. */	      hipe_push_beam_trap_frame(p, reg, arity+i);	  }	  result = HIPE_MODE_SWITCH_RES_CALL;	  break;      }      case HIPE_MODE_SWITCH_RES_RESCHEDULE: {	  DPRINTF("native reschedules 0x%#lx/%u\r\n", p->hipe.ncallee, p->arity);	  hipe_reschedule_from_native(p);	  p->i = hipe_beam_pc_reschedule;	  goto do_schedule;      }      case HIPE_MODE_SWITCH_RES_SUSPEND: {	  p->i = hipe_beam_pc_resume;	  p->arity = 0;	  erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);	  add_to_schedule_q(p);	  erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);	  goto do_schedule;      }      case HIPE_MODE_SWITCH_RES_WAIT:      case HIPE_MODE_SWITCH_RES_WAIT_TIMEOUT: {	  /* same semantics, different debug trace messages */#ifdef ERTS_SMP	  /* XXX: BEAM has different entries for the locked and unlocked	     cases. HiPE doesn't, so we must check dynamically. */	  if (p->hipe_smp.have_receive_locks)	      p->hipe_smp.have_receive_locks = 0;	  else	      erts_smp_proc_lock(p, ERTS_PROC_LOCKS_MSG_RECEIVE);#endif	  p->i = hipe_beam_pc_resume;	  p->arity = 0;	  p->status = P_WAITING;	  erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_MSG_RECEIVE);      do_schedule:	  {#if !(NR_ARG_REGS > 5)	      int reds_in = p->def_arg_reg[5];#endif	      p = schedule(p, reds_in - p->fcalls);#ifdef ERTS_SMP	      p->hipe_smp.have_receive_locks = 0;	      reg = p->scheduler_data->save_reg;#endif	  }	  {	      Eterm *argp;	      int i;	  	      argp = p->arg_reg;	      for(i = p->arity; --i >= 0;)		  reg[i] = argp[i];	  }	  {#if !(NR_ARG_REGS > 5)	      Eterm reds_in;#endif#if !(NR_ARG_REGS > 4)	      Eterm o_reds;#endif	      reds_in = p->fcalls;	      o_reds = 0;	      if( p->ct != NULL ) {		  o_reds = reds_in;		  reds_in = 0;		  p->fcalls = 0;	      }	      p->def_arg_reg[4] = o_reds;	      p->def_arg_reg[5] = reds_in;	      if( p->i == hipe_beam_pc_resume ) {		  p->i = NULL;		  p->arity = 0;		  goto do_resume;	      }	  }	  HIPE_CHECK_PCB(p);	  result = HIPE_MODE_SWITCH_RES_CALL;	  p->def_arg_reg[3] = result;	  return p;      }      case HIPE_MODE_SWITCH_RES_APPLY: {	  Eterm mfa[3], args;	  unsigned int arity;	  void *address;	  hipe_pop_params(p, 3, &mfa[0]);	  /* Unroll the arglist onto reg[]. */	  args = mfa[2];	  arity = 0;	  while( is_list(args) ) {	      if( arity < 255 ) {		  reg[arity++] = CAR(list_val(args));		  args = CDR(list_val(args));	      } else		  goto do_apply_fail;	  }	  if( is_not_nil(args) )	      goto do_apply_fail;	  /* find a native code entry point for {M,F,A} for a remote call */	  address = hipe_get_remote_na(mfa[0], mfa[1], arity);	  if (!address)		  goto do_apply_fail;	  p->hipe.ncallee = (void(*)(void)) address;	  result = hipe_tailcall_to_native(p, arity, reg);	  goto do_return_from_native;      do_apply_fail:	  p->freason = BADARG;	  goto do_throw_to_native;      }      default:	erl_exit(1, "hipe_mode_switch: result %#x\r\n", result);    }    HIPE_CHECK_PCB(p);    p->def_arg_reg[3] = result;#if NR_ARG_REGS > 4    p->def_arg_reg[4] = o_reds;#endif#if NR_ARG_REGS > 5    p->def_arg_reg[5] = reds_in;#endif    return p;}#define HIPE_INITIAL_NSTACK_SIZE	128/* PRE: size is zero or a power of two */static unsigned hipe_next_nstack_size(unsigned size){    return size ? size * 2 : HIPE_INITIAL_NSTACK_SIZE;}#ifdef HIPE_NSTACK_GROWS_UP#define hipe_nstack_avail(p)	((p)->hipe.nstend - (p)->hipe.nsp)void hipe_inc_nstack(Process *p){    Eterm *old_nstack = p->hipe.nstack;    unsigned old_size = p->hipe.nstend - old_nstack;    unsigned new_size = hipe_next_nstack_size(old_size);    Eterm *new_nstack = erts_realloc(ERTS_ALC_T_HIPE,				     (char *) old_nstack,				     new_size*sizeof(Eterm));    p->hipe.nstend = new_nstack + new_size;    if( new_nstack != old_nstack ) {	p->hipe.nsp = new_nstack + (p->hipe.nsp - old_nstack);	p->hipe.nstack = new_nstack;	if( p->hipe.nstgraylim )	    p->hipe.nstgraylim = 		new_nstack + (p->hipe.nstgraylim - old_nstack);	if( p->hipe.nstblacklim )	    p->hipe.nstblacklim = 		new_nstack + (p->hipe.nstblacklim - old_nstack);    }}#endif#ifdef HIPE_NSTACK_GROWS_DOWN#define hipe_nstack_avail(p)	((unsigned)((p)->hipe.nsp - (p)->hipe.nstack))void hipe_inc_nstack(Process *p){    unsigned old_size = p->hipe.nstend - p->hipe.nstack;    unsigned new_size = hipe_next_nstack_size(old_size);    Eterm *new_nstack = erts_alloc(ERTS_ALC_T_HIPE, new_size*sizeof(Eterm));    unsigned used_size = p->hipe.nstend - p->hipe.nsp;    sys_memcpy(new_nstack+new_size-used_size, p->hipe.nsp, used_size*sizeof(Eterm));    if( p->hipe.nstgraylim )	p->hipe.nstgraylim = new_nstack + new_size - (p->hipe.nstend - p->hipe.nstgraylim);    if( p->hipe.nstblacklim )	p->hipe.nstblacklim = new_nstack + new_size - (p->hipe.nstend - p->hipe.nstblacklim);    if( p->hipe.nstack )	erts_free(ERTS_ALC_T_HIPE, p->hipe.nstack);    p->hipe.nstack = new_nstack;    p->hipe.nstend = new_nstack + new_size;    p->hipe.nsp = new_nstack + new_size - used_size;}#endifstatic void hipe_check_nstack(Process *p, unsigned nwords){    while( hipe_nstack_avail(p) < nwords )	hipe_inc_nstack(p);}void hipe_set_closure_stub(ErlFunEntry *fe, unsigned num_free){    unsigned arity;    arity = fe->address[-1] - num_free;    fe->native_address = (Eterm*) hipe_closure_stub_address(arity);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -