예제 #1
0
// static
already_AddRefed<Shmem::SharedMemory>
Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
                    const IPC::Message& aDescriptor,
                    id_t* aId,
                    bool aProtect)
{
  size_t size;
  size_t pageSize = SharedMemory::SystemPageSize();
  // |2*pageSize| is for the front and back sentinels
  RefPtr<SharedMemory> segment = ReadSegment(aDescriptor, aId, &size, 2*pageSize);
  if (!segment) {
    return nullptr;
  }

  Header* header = GetHeader(segment);

  if (size != header->mSize) {
    // Deallocation should zero out the header, so check for that.
    if (header->mSize || header->mUnsafe || header->mMagic[0] ||
        memcmp(header->mMagic, &header->mMagic[1], sizeof(header->mMagic)-1)) {
      NS_ERROR("Wrong size for this Shmem!");
    } else {
      NS_WARNING("Shmem was deallocated");
    }
    return nullptr;
  }

  // The caller of this function may not know whether the segment is
  // unsafe or not
  if (!header->mUnsafe && aProtect)
    Protect(segment);

  return segment.forget();
}
예제 #2
0
/*----------------------------------------------*/
PLH::MemoryProtect::MemoryProtect(void* Address, size_t Size, DWORD ProtectionFlags)
{
	m_Address = Address;
	m_Size = Size;
	m_Flags = ProtectionFlags;
	Protect(m_Address, m_Size, m_Flags);
}
예제 #3
0
MonoBoolean
ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectUser (const gunichar2 *path, MonoError *error)
{
	gboolean ret = FALSE;
	
	/* read/write to user, no access to everyone else */
	ret = Protect (path, (S_IRUSR | S_IWUSR), S_IXUSR);
	return (MonoBoolean)ret;
}
예제 #4
0
MonoBoolean
ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectMachine (const gunichar2 *path, MonoError *error)
{
	gboolean ret = FALSE;

	/* read/write to owner, read to everyone else */
	ret = Protect (path, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), (S_IXUSR | S_IXGRP | S_IXOTH));
	return (MonoBoolean)ret;
}
예제 #5
0
// static
Shmem::SharedMemory*
Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
                    const IPC::Message& aDescriptor,
                    id_t* aId,
                    bool aProtect)
{
  if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type())
    NS_RUNTIMEABORT("expected 'shmem created' message");

  void* iter = 0;
  SharedMemory::SharedMemoryType type;
  size_t size;
  if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type))
    return 0;

  SharedMemory* segment = 0;
  size_t pageSize = SharedMemory::SystemPageSize();
  // |2*pageSize| is for the front and back sentinels
  size_t segmentSize = SharedMemory::PageAlignedSize(size + 2*pageSize);

  if (SharedMemory::TYPE_BASIC == type) {
    SharedMemoryBasic::Handle handle;
    if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle))
      return 0;

    if (!SharedMemoryBasic::IsHandleValid(handle))
      NS_RUNTIMEABORT("trying to open invalid handle");
    segment = CreateSegment(segmentSize, handle);
  }
#ifdef MOZ_HAVE_SHAREDMEMORYSYSV
  else if (SharedMemory::TYPE_SYSV == type) {
    SharedMemorySysV::Handle handle;
    if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle))
      return 0;

    if (!SharedMemorySysV::IsHandleValid(handle))
      NS_RUNTIMEABORT("trying to open invalid handle");
    segment = CreateSegment(segmentSize, handle);
  }
#endif
  else {
    NS_RUNTIMEABORT("unknown shmem type");
  }

  if (!segment)
    return 0;

  // The caller of this function may not know whether the segment is
  // unsafe or not
  Header* header = GetHeader(segment);
  if (!header->mUnsafe && aProtect)
    Protect(segment);

  return segment;
}
예제 #6
0
quad_float sqrt(const quad_float& y) {
  if (y.hi < 0.0) 
    ArithmeticError("quad_float: square root of negative number");
  if (y.hi == 0.0) return quad_float(0.0,0.0);

  double c;
  c = sqrt(y.hi);
  ForceToMem(&c);  // This is fairly paranoid, but it doesn't cost too much.

START_FIX

  DOUBLE p,q,hx,tx,u,uu,cc;
  DOUBLE t1;

  p = Protect(NTL_QUAD_FLOAT_SPLIT*c); 
  hx = (c-p); 
  hx = hx+p; 
  tx = c-hx;
  p = Protect(hx*hx);
  q = Protect(hx*tx);
  q = q+q;

  u = p+q;
  uu = p-u;
  uu = uu+q;
  t1 = Protect(tx*tx);
  uu = uu+t1;


  cc = y.hi-u;
  cc = cc-uu;
  cc = cc+y.lo;
  t1 = c+c;
  cc = cc/t1;

  hx = c+cc;
  tx = c-hx;
  tx = tx+cc;
END_FIX
  return quad_float(hx, tx);
}
예제 #7
0
MonoBoolean
ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectMachine (MonoString *path)
{
	gboolean ret = FALSE;

	/* read/write to owner, read to everyone else */
#ifdef HOST_WIN32
	ret = ProtectMachine (mono_string_chars (path));
#else
	ret = Protect (path, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), (S_IXUSR | S_IXGRP | S_IXOTH));
#endif
	return ret;
}
예제 #8
0
MonoBoolean
ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectUser (MonoString *path)
{
	gboolean ret = FALSE;
	
	/* read/write to user, no access to everyone else */
#ifdef HOST_WIN32
	ret = ProtectUser (mono_string_chars (path));
#else
	ret = Protect (path, (S_IRUSR | S_IWUSR), S_IXUSR);
#endif
	return ret;
}
예제 #9
0
// static
already_AddRefed<Shmem::SharedMemory>
Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
             size_t aNBytes,
             SharedMemoryType aType,
             bool aUnsafe,
             bool aProtect)
{
  NS_ASSERTION(aNBytes <= UINT32_MAX, "Will truncate shmem segment size!");
  MOZ_ASSERT(!aProtect || !aUnsafe, "protect => !unsafe");

  size_t pageSize = SharedMemory::SystemPageSize();
  nsRefPtr<SharedMemory> segment;
  // |2*pageSize| is for the front and back sentinel
  size_t segmentSize = SharedMemory::PageAlignedSize(aNBytes + 2*pageSize);

  if (aType == SharedMemory::TYPE_BASIC)
    segment = CreateSegment(segmentSize, SharedMemoryBasic::NULLHandle());
#ifdef MOZ_HAVE_SHAREDMEMORYSYSV
  else if (aType == SharedMemory::TYPE_SYSV)
    segment = CreateSegment(segmentSize, SharedMemorySysV::NULLHandle());
#endif
  else {
    NS_ERROR("unknown shmem type");
    return nullptr;
  }

  if (!segment)
    return nullptr;

  Header* header;
  char *frontSentinel;
  char *data;
  char *backSentinel;
  GetSections(segment, &header, &frontSentinel, &data, &backSentinel);

  // initialize the segment with Shmem-internal information

  // NB: this can't be a static assert because technically pageSize
  // isn't known at compile time, event though in practice it's always
  // going to be 4KiB
  MOZ_ASSERT(sizeof(Header) <= pageSize,
             "Shmem::Header has gotten too big");
  memcpy(header->mMagic, sMagic, sizeof(sMagic));
  header->mSize = static_cast<uint32_t>(aNBytes);
  header->mUnsafe = aUnsafe;

  if (aProtect)
    Protect(segment);

  return segment.forget();
}
예제 #10
0
ECode CVpnService::Protect(
    /* [in] */ IDatagramSocket* socket,
    /* [out] */ Boolean* reault)
{
    VALIDATE_NOT_NULL(reault);

    AutoPtr<IFileDescriptor> descriptor;
    socket->GetFileDescriptor((IFileDescriptor**)&descriptor);

    Int32 fd;
    descriptor->GetDescriptor(&fd);

    return Protect(fd, result);
}
예제 #11
0
quad_float& operator /=(quad_float& x, const quad_float& y ) {
START_FIX
  DOUBLE hc, tc, hy, ty, C, c, U, u;
  DOUBLE t1;

  C = x.hi/y.hi;
  c = Protect(NTL_QUAD_FLOAT_SPLIT*C);
  hc = c-C;
  u = Protect(NTL_QUAD_FLOAT_SPLIT*y.hi);
  hc = c-hc;
  tc = C-hc;
  hy = u-y.hi;
  U = Protect(C * y.hi);
  hy = u-hy;
  ty = y.hi-hy;

  // u = (((hc*hy-U)+hc*ty)+tc*hy)+tc*ty;

  u = Protect(hc*hy);
  u = u-U;
  t1 = Protect(hc*ty);
  u = u+t1;
  t1 = Protect(tc*hy);
  u = u+t1;
  t1 = Protect(tc*ty);
  u = u+t1;

  // c = ((((x.hi-U)-u)+x.lo)-C*y.lo)/y.hi;

  c = x.hi-U;
  c = c-u;
  c = c+x.lo;
  t1 = Protect(C*y.lo);
  c = c - t1;
  c = c/y.hi;
  
  hy = C+c;
  ty = C-hy;
  ty = ty+c;

  x.hi = hy;
  x.lo = ty;
END_FIX
  return x;
}
예제 #12
0
quad_float& operator *=(quad_float& x,const quad_float& y ) {
START_FIX
  DOUBLE hx, tx, hy, ty, C, c;
  DOUBLE t1, t2;

  C = Protect(NTL_QUAD_FLOAT_SPLIT*x.hi);
  hx = C-x.hi;
  c = Protect(NTL_QUAD_FLOAT_SPLIT*y.hi);
  hx = C-hx;
  tx = x.hi-hx;
  hy = c-y.hi;
  C = Protect(x.hi*y.hi);
  hy = c-hy;
  ty = y.hi-hy;

  // c = ((((hx*hy-C)+hx*ty)+tx*hy)+tx*ty)+(x.hi*y.lo+x.lo*y.hi);
  
  t1 = Protect(hx*hy);
  t1 = t1-C;
  t2 = Protect(hx*ty);
  t1 = t1+t2;
  t2 = Protect(tx*hy);
  t1 = t1+t2;
  t2 = Protect(tx*ty);
  c = t1+t2;
  t1 = Protect(x.hi*y.lo);
  t2 = Protect(x.lo*y.hi);
  t1 = t1+t2;
  c = c + t1;


  hx = C+c;
  tx = C-hx;
  tx = tx+c;

  x.hi = hx;
  x.lo = tx;
END_FIX
  return x;
}
예제 #13
0
void vm_mini_vm(lua_State *L, LClosure *cl, int count, int pseudo_ops_offset) {
  const Instruction *pc;
  StkId base;
  TValue *k;

  k = cl->p->k;
  pc = cl->p->code + pseudo_ops_offset;
  base = L->base;
  /* process next 'count' ops */
  for (; count > 0; count--) {
    const Instruction i = *pc++;
    StkId ra = RA(i);
    lua_assert(base == L->base && L->base == L->ci->base);
    lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
    lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
    switch (GET_OPCODE(i)) {
      case OP_MOVE: {
        setobjs2s(L, ra, RB(i));
        continue;
      }
      case OP_LOADK: {
        setobj2s(L, ra, KBx(i));
        continue;
      }
      case OP_GETUPVAL: {
        int b = GETARG_B(i);
        setobj2s(L, ra, cl->upvals[b]->v);
        continue;
      }
      case OP_SETUPVAL: {
        UpVal *uv = cl->upvals[GETARG_B(i)];
        setobj(L, uv->v, ra);
        luaC_barrier(L, uv, ra);
        continue;
      }
      case OP_SETTABLE: {
        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
        continue;
      }
      default: {
        luaG_runerror(L, "Bad opcode: opcode=%d", GET_OPCODE(i));
        continue;
      }
    }
  }
}
예제 #14
0
void
Shmem::RevokeRights(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead)
{
  AssertInvariants();

  size_t pageSize = SharedMemory::SystemPageSize();
  Header* header = GetHeader(mSegment);

  // Open this up for reading temporarily
  mSegment->Protect(reinterpret_cast<char*>(header), pageSize, RightsRead);

  if (!header->mUnsafe) {
    Protect(mSegment);
  } else {
    mSegment->Protect(reinterpret_cast<char*>(header), pageSize, RightsNone);
  }
}
예제 #15
0
파일: lvm.c 프로젝트: lriki/Volkoff
void luaV_execute (lua_State *L) {
  CallInfo *ci = L->ci;
  LClosure *cl;
  TValue *k;
  StkId base;
 newframe:  /* reentry point when frame changes (call/return) */
  lua_assert(ci == L->ci);
  cl = clLvalue(ci->func);
  k = cl->p->k;
  base = ci->u.l.base;

  //printf( "s:%p\n", ci->u.l.savedpc );
  /* main loop of interpreter */
  for (;;) {

    Instruction i = *(ci->u.l.savedpc++);
    StkId ra;
    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
      Protect(traceexec(L));
    }
    /* warning!! several calls may realloc the stack and invalidate `ra' */
    ra = RA(i);
    lua_assert(base == ci->u.l.base);
    lua_assert(base <= L->top && L->top < L->stack + L->stacksize);


    // 命令出力
    //printInst( ci->u.l.savedpc - 1 );


    vmdispatch (GET_OPCODE(i)) {
      vmcase(OP_MOVE,
        setobjs2s(L, ra, RB(i));
      )
      vmcase(OP_LOADK,
        TValue *rb = k + GETARG_Bx(i);
        setobj2s(L, ra, rb);
      )
      vmcase(OP_LOADKX,
        TValue *rb;
        lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
        rb = k + GETARG_Ax(*ci->u.l.savedpc++);
        setobj2s(L, ra, rb);
      )
예제 #16
0
int vm_OP_TFORLOOP(lua_State *L, int a, int c) {
  TValue *base = L->base;
  TValue *ra = base + a;
  StkId cb = ra + 3;  /* call base */
  setobjs2s(L, cb+2, ra+2);
  setobjs2s(L, cb+1, ra+1);
  setobjs2s(L, cb, ra);
  L->top = cb+3;  /* func. + 2 args (state and index) */
  Protect(luaD_call(L, cb, c));
  L->top = L->ci->top;
  cb = base + a + 3;  /* previous call may change the stack */
  if (!ttisnil(cb)) {  /* continue loop? */
    setobjs2s(L, cb-1, cb);  /* save control variable */
    dojump(GETARG_sBx(*L->savedpc));
    return 1;
  }
  return 0;
}
예제 #17
0
void vm_OP_VARARG(lua_State *L, LClosure *cl, int a, int b) {
  TValue *base = L->base;
  TValue *ra = base + a;
  int j;
  CallInfo *ci = L->ci;
  int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;
  b -= 1;
  if (b == LUA_MULTRET) {
    Protect(luaD_checkstack(L, n));
    ra = base + a;  /* previous call may change the stack */
    b = n;
    L->top = ra + n;
  }
  for (j = 0; j < b; j++) {
    if (j < n) {
      setobjs2s(L, ra + j, ci->base - n + j);
    }
    else {
      setnilvalue(ra + j);
    }
  }
}
예제 #18
0
파일: Shmem.cpp 프로젝트: lofter2011/Icefox
// static
Shmem::SharedMemory*
Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
             size_t aNBytes,
             SharedMemoryType aType,
             bool aProtect)
{
  size_t pageSize = SharedMemory::SystemPageSize();
  SharedMemory* segment = nsnull;
  // |2*pageSize| is for the front and back sentinel
  size_t segmentSize = PageAlignedSize(aNBytes + 2*pageSize);

  if (aType == SharedMemory::TYPE_BASIC)
    segment = CreateSegment(segmentSize, SharedMemoryBasic::NULLHandle());
#ifdef MOZ_HAVE_SHAREDMEMORYSYSV
  else if (aType == SharedMemory::TYPE_SYSV)
    segment = CreateSegment(segmentSize, SharedMemorySysV::NULLHandle());
#endif
  else
    NS_RUNTIMEABORT("unknown shmem type");

  if (!segment)
    return 0;

  char *frontSentinel;
  char *data;
  char *backSentinel;
  GetSections(segment, &frontSentinel, &data, &backSentinel);

  // initialize the segment with Shmem-internal information
  Header* header = reinterpret_cast<Header*>(frontSentinel);
  memcpy(header->mMagic, sMagic, sizeof(sMagic));
  header->mSize = aNBytes;

  if (aProtect)
    Protect(segment);

  return segment;
}
예제 #19
0
PLH::MemoryProtect::~MemoryProtect()
{
	Protect(m_Address,m_Size, m_OldProtection);
}
예제 #20
0
파일: Shmem.cpp 프로젝트: lofter2011/Icefox
void
Shmem::RevokeRights(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead)
{
  AssertInvariants();
  Protect(mSegment);
}
예제 #21
0
파일: ai.cpp 프로젝트: hyperlogic/cylindrix
void AI_Control( WorldStuff *world_stuff, int vehicle_number )
    {
     Player *player;
     team_type team, enemy_team;

     short frames_till_traitor_deactivate;
     short frames_till_unscramble;
     short scramble_life;
     short traitor_life;


     /* Alias pointer to this player */
     player = world_stuff->player_array;

     frames_till_traitor_deactivate = player[vehicle_number].tank.frames_till_traitor_deactivate;
     frames_till_unscramble         = player[vehicle_number].tank.frames_till_unscramble; 
     scramble_life                  = player[vehicle_number].tank.scramble_life;
     traitor_life                   = player[vehicle_number].tank.traitor_life;


     if( player[vehicle_number].tank.team == RED_TEAM )
         {
          team = RED_TEAM;
          enemy_team = BLUE_TEAM;
         }
     else
         {
          team = BLUE_TEAM;
          enemy_team = RED_TEAM;
         }



     if( player[vehicle_number].character.skill_level > 2 && player[vehicle_number].controller != USER_CONTROL )
         {
          if( player[vehicle_number].tank.traitor_active )
          if( frames_till_traitor_deactivate < (traitor_life - 40) )
              player[vehicle_number].tank.traitor_active = FALSE;

          /*
          if( player[vehicle_number].tank.controls_scrambled )
          if( frames_till_unscramble < (scramble_life - 40) )
              player[vehicle_number].tank.controls_scrambled = FALSE;
          */
         }


     if( player[vehicle_number].tank.traitor_active )
         {    
          player[vehicle_number].tank.team = enemy_team;
          player[vehicle_number].team = enemy_team;
         }

     
     /* Clear this players input table */
     Clear_Input_Table( player[vehicle_number].table );

     /* Fill up this players events data structure */
     Update_Player_Events( world_stuff, vehicle_number );

     /* Figure out what state we are in now */
     world_stuff->player_array[vehicle_number].character.state = Find_State( world_stuff, vehicle_number );


     if( player[vehicle_number].tank.traitor_active )
         {    
          world_stuff->player_array[vehicle_number].character.state = ATTACK;
         }

     /* Based on the state of the ai call appropriate control function */
     switch( world_stuff->player_array[vehicle_number].character.state )
         {
          case ATTACK:
              Attack( world_stuff, vehicle_number );
              break;
          case GET_ENERGY:
              Get_Energy( world_stuff, vehicle_number );
              break;
          case PANIC:
              Panic( world_stuff, vehicle_number );
              break;
          case BEZERK:
              Bezerk( world_stuff, vehicle_number );
              break;
          case HIDE:
              Hide( world_stuff, vehicle_number );
              break;
          case GROUPUP:
              Group( world_stuff, vehicle_number );
              break;
          case GET_PYLONS:
              Get_Pylons( world_stuff, vehicle_number );
              break;
          case PROTECT:
              Protect( world_stuff, vehicle_number );
              break;
          case KILL_RADAR_BASE:
              Kill_Radar_Base( world_stuff, vehicle_number );
              break;
          case PROTECT_RADAR_BASE:
              Protect_Radar_Base( world_stuff, vehicle_number );
              break;
          case EVADE:
              Evade( world_stuff, vehicle_number );
          default:
              break;

         } /* End case */

     if( player[vehicle_number].tank.traitor_active )
         {    
          player[vehicle_number].tank.team = team;
          player[vehicle_number].team = team;
         }

     if( player[vehicle_number].tank.vtype == Dragonfly )
         Cloak_Override( world_stuff, vehicle_number );

     if( player[vehicle_number].tank.vtype == Roach )
         Mines( world_stuff, vehicle_number );

     if( player_events[vehicle_number].memory.stuck )
         Stuck_Override( world_stuff, vehicle_number );

    } /* End of AI_Control */
예제 #22
0
파일: lvm.c 프로젝트: zapline/zlib
static void Arith (lua_State *L, StkId ra, const TValue *rb,
                   const TValue *rc, TMS op) {
  TValue tempb, tempc;
  const TValue *b, *c;
#if LUA_REFCOUNT
  luarc_newvalue(&tempb);
  luarc_newvalue(&tempc);
  if ((b = luaV_tonumber(L, rb, &tempb)) != NULL &&
      (c = luaV_tonumber(L, rc, &tempc)) != NULL) {
#else
  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
      (c = luaV_tonumber(rc, &tempc)) != NULL) {
#endif /* LUA_REFCOUNT */
    lua_Number nb = nvalue(b), nc = nvalue(c);
#if LUA_REFCOUNT
    luarc_cleanvalue(&tempb);
    luarc_cleanvalue(&tempc);
#endif /* LUA_REFCOUNT */
    switch (op) {
      case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
      case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
      case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
      case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
      case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
      case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
      case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
      default: lua_assert(0); break;
    }
  }
#if LUA_REFCOUNT
  else if (!call_binTM(L, rb, rc, ra, op)) {
    luarc_cleanvalue(&tempb);
    luarc_cleanvalue(&tempc);
    luaG_aritherror(L, rb, rc);
  }
#else
  else if (!call_binTM(L, rb, rc, ra, op))
    luaG_aritherror(L, rb, rc);
#endif /* LUA_REFCOUNT */
}



/*
** some macros for common tasks in `luaV_execute'
*/

#define runtime_check(L, c)	{ if (!(c)) break; }

#define RA(i)	(base+GETARG_A(i))
/* to be used after possible stack reallocation */
#define RB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
#define RC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
#define RKB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
	ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
#define RKC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
	ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
#define KBx(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))


#define dojump(L,pc,i)	{(pc) += (i); luai_threadyield(L);}


#define Protect(x)	{ L->savedpc = pc; {x;}; base = L->base; }


#define arith_op(op,tm) { \
        TValue *rb = RKB(i); \
        TValue *rc = RKC(i); \
        if (ttisnumber(rb) && ttisnumber(rc)) { \
          lua_Number nb = nvalue(rb), nc = nvalue(rc); \
          setnvalue(ra, op(nb, nc)); \
        } \
        else \
          Protect(Arith(L, ra, rb, rc, tm)); \
      }

#if LUA_BITFIELD_OPS

#define bit_op(op) { \
        TValue *rb = RKB(i); \
        TValue *rc = RKC(i); \
        if (ttisnumber(rb) && ttisnumber(rc)) { \
          unsigned int nb = (unsigned int)nvalue(rb), nc = (unsigned int)nvalue(rc); \
          setnvalue(ra, nb op nc); \
        } \
        else \
          luaG_aritherror(L, rb, rc); \
      }

#endif /* LUA_BITFIELD_OPS */



void luaV_execute (lua_State *L, int nexeccalls) {
  LClosure *cl;
  StkId base;
  TValue *k;
  const Instruction *pc;
 reentry:  /* entry point */
  lua_assert(isLua(L->ci));
  pc = L->savedpc;
  cl = &clvalue(L->ci->func)->l;
  base = L->base;
  k = cl->p->k;
  /* main loop of interpreter */
  for (;;) {
    const Instruction i = *pc++;
    StkId ra;
    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
      traceexec(L, pc);
      if (L->status == LUA_YIELD) {  /* did hook yield? */
        L->savedpc = pc - 1;
        return;
      }
      base = L->base;
    }
    /* warning!! several calls may realloc the stack and invalidate `ra' */
    ra = RA(i);
    lua_assert(base == L->base && L->base == L->ci->base);
    lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
    lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
    switch (GET_OPCODE(i)) {
      case OP_MOVE: {
        setobjs2s(L, ra, RB(i));
        continue;
      }
      case OP_LOADK: {
        setobj2s(L, ra, KBx(i));
        continue;
      }
      case OP_LOADBOOL: {
        setbvalue(ra, GETARG_B(i));
        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
        continue;
      }
      case OP_LOADNIL: {
        TValue *rb = RB(i);
        do {
          setnilvalue(rb--);
        } while (rb >= ra);
        continue;
      }
      case OP_GETUPVAL: {
        int b = GETARG_B(i);
        setobj2s(L, ra, cl->upvals[b]->v);
        continue;
      }
      case OP_GETGLOBAL: {
        TValue g;
        TValue *rb = KBx(i);
#if LUA_REFCOUNT
        sethvalue2n(L, &g, cl->env);
#else
        sethvalue(L, &g, cl->env);
#endif /* LUA_REFCOUNT */
        lua_assert(ttisstring(rb));
        Protect(luaV_gettable(L, &g, rb, ra));
#if LUA_REFCOUNT
		setnilvalue(&g);
#endif /* LUA_REFCOUNT */
        continue;
      }
      case OP_GETTABLE: {
        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
        continue;
      }
      case OP_SETGLOBAL: {
        TValue g;
#if LUA_REFCOUNT
        sethvalue2n(L, &g, cl->env);
#else
        sethvalue(L, &g, cl->env);
#endif /* LUA_REFCOUNT */
        lua_assert(ttisstring(KBx(i)));
        Protect(luaV_settable(L, &g, KBx(i), ra));
#if LUA_REFCOUNT
		setnilvalue(&g);
#endif /* LUA_REFCOUNT */
        continue;
      }
      case OP_SETUPVAL: {
        UpVal *uv = cl->upvals[GETARG_B(i)];
        setobj(L, uv->v, ra);
        luaC_barrier(L, uv, ra);
        continue;
      }
      case OP_SETTABLE: {
        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
        continue;
      }
      case OP_NEWTABLE: {
        int b = GETARG_B(i);
        int c = GETARG_C(i);
        sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
        Protect(luaC_checkGC(L));
        continue;
      }
      case OP_SELF: {
        StkId rb = RB(i);
        setobjs2s(L, ra+1, rb);
        Protect(luaV_gettable(L, rb, RKC(i), ra));
        continue;
      }
      case OP_ADD: {
        arith_op(luai_numadd, TM_ADD);
        continue;
      }
      case OP_SUB: {
        arith_op(luai_numsub, TM_SUB);
        continue;
      }
      case OP_MUL: {
        arith_op(luai_nummul, TM_MUL);
        continue;
      }
      case OP_DIV: {
        arith_op(luai_numdiv, TM_DIV);
        continue;
      }
      case OP_MOD: {
        arith_op(luai_nummod, TM_MOD);
        continue;
      }
      case OP_POW: {
        arith_op(luai_numpow, TM_POW);
        continue;
      }
      case OP_UNM: {
        TValue *rb = RB(i);
        if (ttisnumber(rb)) {
          lua_Number nb = nvalue(rb);
          setnvalue(ra, luai_numunm(nb));
        }
        else {
          Protect(Arith(L, ra, rb, rb, TM_UNM));
        }
        continue;
      }
      case OP_NOT: {
        int res = l_isfalse(RB(i));  /* next assignment may change this value */
        setbvalue(ra, res);
        continue;
      }
#if LUA_BITFIELD_OPS
      case OP_BAND: {
        bit_op(&);
        continue;
      }
      case OP_BOR: {
        bit_op(|);
        continue;
      }
      case OP_BXOR: {
        bit_op(^);
        continue;
      }
      case OP_BSHL: {
        bit_op(<<);
        continue;
      }
      case OP_BSHR: {
        bit_op(>>);
        continue;
      }
#endif /* LUA_BITFIELD_OPS */
      case OP_LEN: {
        const TValue *rb = RB(i);
        switch (ttype(rb)) {
          case LUA_TTABLE: {
            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
            break;
          }
          case LUA_TSTRING: {
            setnvalue(ra, cast_num(tsvalue(rb)->len));
            break;
          }
#if LUA_WIDESTRING
          case LUA_TWSTRING: {
            setnvalue(ra, cast_num(tsvalue(rb)->len));
            break;
          }
#endif /* LUA_WIDESTRING */
          default: {  /* try metamethod */
            Protect(
              if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
                luaG_typeerror(L, rb, "get length of");
            )
          }
        }
        continue;
      }
      case OP_CONCAT: {
        int b = GETARG_B(i);
        int c = GETARG_C(i);
        Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
        setobjs2s(L, RA(i), base+b);
        continue;
      }
      case OP_JMP: {
        dojump(L, pc, GETARG_sBx(i));
        continue;
      }
      case OP_EQ: {
        TValue *rb = RKB(i);
        TValue *rc = RKC(i);
        Protect(
          if (equalobj(L, rb, rc) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
      case OP_LT: {
        Protect(
          if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
      case OP_LE: {
        Protect(
          if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
예제 #23
0
// 已经准备好了lua函数的调用环境,开始逐句执行lua函数的指令
void luaV_execute (lua_State *L, int nexeccalls) {
  LClosure *cl;
  StkId base;
  TValue *k;
  const Instruction *pc;
 reentry:  /* entry point */
  pc = L->savedpc;					//这时候已经保存了lua函数的第一个指令位置
  cl = &clvalue(L->ci->func)->l;
  base = L->base;
  k = cl->p->k;
  /* main loop of interpreter */
  for (;;) {
    const Instruction i = *pc++;
    StkId ra;
    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
      traceexec(L, pc);
      if (L->status == LUA_YIELD) {  /* did hook yield? */
        L->savedpc = pc - 1;
        return;
      }
      base = L->base;
    }
    /* warning!! several calls may realloc the stack and invalidate `ra' */
    ra = RA(i);
    lua_assert(base == L->base && L->base == L->ci->base);
    lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
    lua_assert(L->top == L->ci->top || luaG_checkopenop(i));

	// 阅读说明:
	// 每lua的一个函数在编译器会生成这个函数的信息:函数引用到的upvalue,函数固定参数
	// 数量,是否含有可变参数,指令序列等等,这些都记录在Proto结构体中。
	// 可以通过 luac -o tmp <luafile> | luac -l tmp 来函数对应的字节码以及Proto信息
	// 例如以下lua代码:
	// -- t.lua
	// local x, y, z
	// x = x*y + y*z + x*z - (x*x + y*y + z*z)
	// 得到以下输出:
	// main <t.lua:0,0> (12 instructions, 48 bytes at 0074B6A0)
	// 0 + params, 6 slots, 0 upvalues, 3 locals, 0 constants, 0 functions
	//	1[2]	MUL      	3 0 1
	//	2[2]	MUL      	4 1 2
	//	3[2]	ADD      	3 3 4
	//	4[2]	MUL      	4 0 2
	//	5[2]	ADD      	3 3 4
	//	6[2]	MUL      	4 0 0
	//	7[2]	MUL      	5 1 1
	//	8[2]	ADD      	4 4 5
	//	9[2]	MUL      	5 2 2
	//	10[2]	ADD      	4 4 5
	//	11[2]	SUB      	0 3 4
	//	12[2]	RETURN   	0 1
	// 从输出可以得到的信息包括:
	//  1 生成了多少个Proto
	//  2 Proto对应的lua源代码在哪里 (<t.lua:0,0>)
	//  3 Proto中的sizecode (12 instructions, 48 bytes at 0074B6A0)
	//  4 Proto中的固定参数数量numparams (0 + params,这里的0)
	//  5 Proto是否有可变参数is_vararg (0 + params,这里的+表示带有可变参数,没有可变参数就是 0 params)
	//  6 Proto中在栈上用到的临时变量总数maxstacksize (6 slots,表示local变量+计算中辅助用的临时变量=6个)
	//  7 Proto中用到的upvalue数量nups (0 upvalues,表示用到了0个upvalue)
	//  8 Proto中用到的local变量数量sizelocvars (3 locals,刚好t.lua用到了x,y,z三个local变量)
	//  9 Proto中用到的字面常量数量sizek (0 constants)
	// 10 Proto中用到的Closure数量sizep (0 functions)
	// 11 Proto中生成的字节码指令内容code,每条指令包括:
	//    a 指令下标
	//    b 指令在源代码中对应的行号
	//    c 指令opcode
	//    d 指令参数
	// 
	// PS:第6条和第8条,由于计算一条表达式需要用到的辅助临时变量数目是不定的,但是是可以通过
	// 分析一条表达式的AST来确定最少需要几个临时变量(后续遍历+逆波兰式拟真)。
	// PS:lua是会对表达式进行常量计算优化的!例如 x = x + 5*60*60*1000,只有一个常量18000000
	// PS:函数执行的时候需要用到“一段”参数栈上的空间,也就是第6条所谓的临时变量。这一段空间的
	// 范围由L->base开始,到L->top结束。通过相对L->base的下标来标识具体的变量是哪个。一般来说,
	// 固定参数的函数,L->base指向第一个固定参数,而L->base-1指向当前正在运行的函数;而可变参数
	// 的函数,L->base和当前正在运行的函数中间,保存有全部的传入参数。
    switch (GET_OPCODE(i)) {

	  // 功能:用一个已有的变量创建一个新的变量
	  // 将一个 lua_TValue设置成另一个lua_TValue的样子
      // iABC: A待创建变量在参数栈索引,B参数栈已有lua变量的索引。
      case OP_MOVE: {		
		// local x, y   -----> 记录 index(x) = 0, index(y) = 1
		// x = ...
		// .....
		// y = x    -----> OP_MOVE: 1, 0
        setobjs2s(L, ra, RB(i));
        continue;
      }

	  // 功能:用一个常量来创建一个新的变量
	  // 从常量池(保存在Proto类型中)中保存的常量赋值给栈上的变量
	  // iABx: A待创建变量在参数栈索引,Bx常量在常量池的索引
      case OP_LOADK: {		
		// local x = 9	-----> 记录 index(x) = 0, index(constval(9)) = 1 
		//              >----> OP_LOADK: 0, 1
        setobj2s(L, ra, KBx(i));
        continue;
      }

	  // 功能:用一个布尔值来创建一个新的变量
	  // iABC: A待创建变量在参数栈索引,B布尔值,C通常是0
      case OP_LOADBOOL: {	
		// 注意,local c = true这种,true就不作为一个常量放到k里面
		// 而是作为字面值放到参数B里面了!所以不需要KB(i)!
		// local a = false -----> 记录 index(a) = 0
		//                 >----> OP_LOADBOOL 0 0 0
		// local b = true  -----> 记录 index(b) = 1
		//                 >----> OP_LOADBOOL 1 1 0
        setbvalue(ra, GETARG_B(i));
        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
        continue;
      }

	  // 功能:用nil来初始化一个到多个变量
	  // 类似于bzero,这个指令会把一段内存中的变量置为nil
	  // iABC: A第一个要置nil的变量参数栈索引,B最后一个要置nil的变量参数栈索引
      case OP_LOADNIL: {
		// local a, b, c, d, e, f, g = 1, 2, 3, 4 -----> index(a~g) = 0~6
		//                                        >----> OP_LOADNIL 4 6
        TValue *rb = RB(i);
        do {
          setnilvalue(rb--);
        } while (rb >= ra);
        continue;
      }

	  // 功能:用upvalue来创建一个新的变量
	  // 所谓的“创建”操作,其实创建的不是副本而是引用
	  // iABC: A待创建变量在参数栈索引,B当前函数的upvalue表的索引
      case OP_GETUPVAL: {	
		// local x = {}
		// ...  -- do something to x
		// function f() local a = x[1] end   -----> 记录index(a) = 0, index(upval(x)) = 1
		//                                   >----> OP_GETUPVAL 0 1
        int b = GETARG_B(i);
        setobj2s(L, ra, cl->upvals[b]->v);
        continue;
      }

	  // 功能:从全局表中取某个key的值来创建一个新的变量
	  // iABx:A待创建变量在参数栈索引,Bxkey对应的常量在常量池的索引
      case OP_GETGLOBAL: {
		// local a = dofile    ------> 记录 index(a) = 0, index(constval("dofile")) = 1
		//                     >-----> OP_GETGLOBAL 0 1
        TValue g;
        TValue *rb = KBx(i);
        sethvalue(L, &g, cl->env);
        lua_assert(ttisstring(rb));
        Protect(luaV_gettable(L, &g, rb, ra));
        continue;
      }

	  // 功能:从某个table中取某个key的值来创建一个新的变量
	  // iABC:A待创建变量在参数栈索引,B要取出key的table变量在参数栈的索引,Ckey对应的参数栈下标或者常量池下标
      case OP_GETTABLE: {
		// local a = hello["world"] -----> 记录 index(a) = 0, index(hello) = 1 index(constval("world")) = 0
		//                          >----> OP_GETTABLE 0 1 0|BITRK
        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
        continue;
      }

	  // 功能:将参数栈上变量设置到全局表中
	  // iABx:A要写入全局表的变量在栈上的索引,Bx写入到全局表的key在常量池中的下标
      case OP_SETGLOBAL: {
		// 假设我要替换 bit库
		// local mybit = {}
		// mybit.band = ...
		// mybit.bor = ...
		// mybit.bxor = ...
		// ...
		// bit = mybit -----> 记录 index(mybit) = 0, index(constval("bit")) = 1
		//             >----> OP_SETGLOBAL 0 1
        TValue g;
        sethvalue(L, &g, cl->env);
        lua_assert(ttisstring(KBx(i)));
        Protect(luaV_settable(L, &g, KBx(i), ra));
        continue;
      }

	  // 功能:修改upvalue的值
	  // iABC:A要写入upvalue的变量在参数栈上的索引,B待写入的upvalue在upvalue表的索引
      case OP_SETUPVAL: {
		// local a = 5
		// function p()
		//  a = "hello" -----> 记录 index(upval(a)) = 0, index(constval("hello")) = 1
		//              >----> OP_SETUPVAL 0 1
		// end
        UpVal *uv = cl->upvals[GETARG_B(i)];
        setobj(L, uv->v, ra);
        luaC_barrier(L, uv, ra);
        continue;
      }

	  // 功能:修改某个table对应的key
	  // iABC:A要写入table变量在参数栈的索引,B要写入的key的变量的栈索引或者常量索引,C要写入的value的变量索引或者常量索引
      case OP_SETTABLE: {
		// local a = {}
		// a[5] = 3
        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
        continue;
      }

	  // 功能:在栈上创建一个table变量
	  // iABC:A存放table变量的参数栈索引,B创建的table变量的数组容量,C创建的table变量的字典容量
      case OP_NEWTABLE: {
		// local a = {}   -----> index(a) = 0
		//                >----> OP_NEWTABLE 0 szArray szHash
        int b = GETARG_B(i);
        int c = GETARG_C(i);
        sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
        Protect(luaC_checkGC(L));			// 注意,创建table可能会引起GC
        continue;
      }

	  // 功能:把self.method和self放到参数栈上相邻的两个位置。
	  // 为成员方法调用的语法糖提供支持
	  // iABC:A存放self.method的参数栈索引,B存放self的参数栈索引,C需要从self中调用的方法对应的变量索引或者常量索引
	  // 执行完成后,栈上内容为: ... -> self.method -> self -> ...
	  //                                   ^
	  //                                   RA
	  // 当然,OP_SELF之后能看到OP_CALL的身影
      case OP_SELF: {
		// CCNode:create()  -> index(constants("CCNode")) = 1, index(constants("create")) = 2
		//                  -> OP_GETGLOBAL 0 1
		//                  -> OP_SELF 0 0 2
		//                  -> OP_CALL 0 2 1
        StkId rb = RB(i);
        setobjs2s(L, ra+1, rb);
        Protect(luaV_gettable(L, rb, RKC(i), ra));
        continue;
      }

	//---------------------------------------------------------------------------运算符指令
	  // 功能:实现二元运算符:+, -, *, /, %, ^
	  // iABC:A存放运算结果的参数栈索引,B存放第一操作数的参数栈索引,C存放第二操作数的参数栈索引
      case OP_ADD: {
		// local a, b, c = ... -----> index(a) = 0, index(b) = 1, index(c) = 2
		// a = b + c -----> OP_ADD 0 1|BITRK 2|BITRK
		// a = 1 + b -----> index(constval(1)) = 0
		//           >----> OP_ADD 0 0 1|BITRK
		// a = 1 + 100 -----> index(constval(1)) = 0, index(constval(100)) = 1
		//             >----> OP_ADD 0 0 1
        arith_op(luai_numadd, TM_ADD);
        continue;
      }
      case OP_SUB: {
		// see OP_ADD
        arith_op(luai_numsub, TM_SUB);
        continue;
      }
      case OP_MUL: {
		// see OP_ADD
        arith_op(luai_nummul, TM_MUL);
        continue;
      }
      case OP_DIV: {
		// see OP_ADD
        arith_op(luai_numdiv, TM_DIV);
        continue;
      }
      case OP_MOD: {
		// 这个很特殊!由于lua没有整数,所以mod可不是%这个运算符!
		// 这里定义 mod(x, y) => (x - floor(x/y)*y)
		// see OP_ADD
        arith_op(luai_nummod, TM_MOD);
        continue;
      }
      case OP_POW: {
		// see OP_ADD
        arith_op(luai_numpow, TM_POW);
        continue;
      }

	  // 功能:实现一元运算符 -, not, #
	  // iABC:A存放运算结果的参数栈索引,B存放操作数的参数栈索引
      case OP_UNM: {
		// local a = -b -----> index(a) = 1, index(b) = 2
		//              >----> OP_UNM 1 2
        TValue *rb = RB(i);
        if (ttisnumber(rb)) {
          lua_Number nb = nvalue(rb);
          setnvalue(ra, luai_numunm(nb));
        }
        else {
          Protect(Arith(L, ra, rb, rb, TM_UNM));
        }
        continue;
      }
      case OP_NOT: {
		// local a = not b -----> index(a) = 1, index(b) = 2
		//                 >----> OP_NOT 1 2
		// 那local a = not true呢?人家编译期就给你处理好了
        int res = l_isfalse(RB(i));  /* next assignment may change this value */
        setbvalue(ra, res);
        continue;
      }
      case OP_LEN: {
		// local a = #b -----> index(a) = 1, index(b) = 2
		//              >----> OP_LEN 1 2
        const TValue *rb = RB(i);
        switch (ttype(rb)) {
          case LUA_TTABLE: {
            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
            break;
          }
          case LUA_TSTRING: {
            setnvalue(ra, cast_num(tsvalue(rb)->len));
            break;
          }
          default: {  /* try metamethod */
            Protect(
              if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
                luaG_typeerror(L, rb, "get length of");
            )
          }
        }
        continue;
      }

	  // 功能:实现字符串拼接运算符 ..
	  // iABC:A拼接后存放结果的参数栈索引,B第一个要拼接的变量的参数栈索引,C最后一个要拼接的变量的参数栈索引
	  // 要执行这个指令,对参数栈有特殊要求:
	  // ... -> string1 -> string2 ... -> stringN -> ...
	  //          ^                          ^
	  //          RB                         RC
      case OP_CONCAT: {
		// 类似OP_LOADNIL,只不过,这次范围是[rb,rc],loadnil是[ra,rb]
		// local b, c, d, a = "hello", "world", "!"
		// a = b .. c .. d -----> index(a) = 4, index(b~d) = 1~3
		//                 >----> OP_CONCAT 4 1 3
		// 问题是如果b~d不能保证是连续的怎么办?答案是一个个MOVE上去在OP_CONCAT...
        int b = GETARG_B(i);
        int c = GETARG_C(i);
        Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
        setobjs2s(L, RA(i), base+b);
        continue;
      }

	//---------------------------------------------------------------------------跳转指令
	  // 功能:无条件跳转
	  // iAsBx:A不使用,sBx跳转偏移
	  // 一般这个语句不单独出现,都是在一些条件控制中和其他的条件跳转指令配合使用的。
      case OP_JMP: {
		// 无条件跳转指令。由于跳转偏移总是有正向和反向之分的,所以需要用到
		// 负数。那就只能用iAsBx类型的指令了。而sBx是有长度限制的!
		// 所以,如果生成的指令很多,超过了sBx的长度限制,可能就会编译失败
        dojump(L, pc, GETARG_sBx(i));
        continue;
      }

	  // 功能:检查两个变量是否相等,满足预期则跳转。配合OP_JMP使用。
	  // iABC:A纯数字,对比较结果的预期,满足预期则跳转,B参数1的索引,C参数2的索引
      case OP_EQ: {
		// if a == b then -----> index(a) = 1, index(b) = 2
		//                >----> 这里将生成两行指令:
		//                >----> OP_EQ  0 1 2	// 用0,因为成立的话跳过,不成立才执行
		//                >----> OP_JMP N		// N 表示then ... end中间的指令数量
		//                >----> ...			// Instructions between "then" and "end"
        TValue *rb = RKB(i);
        TValue *rc = RKC(i);
        Protect(
          if (equalobj(L, rb, rc) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
	
	  // 功能:检查两个变量是否小于,满足预期则跳转。配合OP_JMP使用。
	  // iABC:A纯数字,对比较结果的预期,满足预期则跳转,B参数1的索引,C参数2的索引
      case OP_LT: {
		// if a < b then -----> index(a) = 1, index(b) = 2
		//               >----> 这里将生成两行指令:
		//               >----> OP_LT  0 1 2	// 用0,因为成立的话跳过,不成立才执行
		//               >----> OP_JMP N		// N 表示then ... end中间的指令数量
		//               >----> ...				// Instructions between "then" and "end"
        Protect(
          if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }

	  // 功能:检查两个变量是否小于等于,满足预期则跳转。配合OP_JMP使用。
	  // iABC:A纯数字,对比较结果的预期,满足预期则跳转,B参数1的索引,C参数2的索引
      case OP_LE: {
		  // if a <= b then -----> index(a) = 1, index(b) = 2
		  //                >----> 这里将生成两行指令:
		  //                >----> OP_LE  0 1 2	// 用0,因为成立的话跳过,不成立才执行
		  //                >----> OP_JMP N		// N 表示then ... end中间的指令数量
		  //                >----> ...			// Instructions between "then" and "end"
		  Protect(
          if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
예제 #24
0
void luaV_execute (lua_State *L, int nexeccalls) {
  LClosure *cl;
  StkId base;
  TValue *k;
  const Instruction *pc;
 reentry:  /* entry point */
  lua_assert(isLua(L->ci));
  pc = L->savedpc;
  cl = &clvalue(L->ci->func)->l;
  base = L->base;
  k = cl->p->k;
  /* main loop of interpreter */
  for (;;) {
    const Instruction i = *pc++;
    StkId ra;
    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
      traceexec(L, pc);
      if (L->status == LUA_YIELD) {  /* did hook yield? */
        L->savedpc = pc - 1;
        return;
      }
      base = L->base;
    }
    /* warning!! several calls may realloc the stack and invalidate `ra' */
    ra = RA(i);
    lua_assert(base == L->base && L->base == L->ci->base);
    lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
    lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
    switch (GET_OPCODE(i)) {
      case OP_MOVE: {
        setobjs2s(L, ra, RB(i));
        continue;
      }
      case OP_LOADK: {
        setobj2s(L, ra, KBx(i));
        continue;
      }
      case OP_LOADBOOL: {
        setbvalue(ra, GETARG_B(i));
        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
        continue;
      }
      case OP_LOADNIL: {
        TValue *rb = RB(i);
        do {
          setnilvalue(rb--);
        } while (rb >= ra);
        continue;
      }
      case OP_GETUPVAL: {
        int b = GETARG_B(i);
        setobj2s(L, ra, cl->upvals[b]->v);
        continue;
      }
      case OP_GETGLOBAL: {
        TValue g;
        TValue *rb = KBx(i);
        sethvalue(L, &g, cl->env);
        lua_assert(ttisstring(rb));
        Protect(luaV_gettable(L, &g, rb, ra));
        continue;
      }
      case OP_GETTABLE: {
        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
        continue;
      }
      case OP_SETGLOBAL: {
        TValue g;
        sethvalue(L, &g, cl->env);
        lua_assert(ttisstring(KBx(i)));
        Protect(luaV_settable(L, &g, KBx(i), ra));
        continue;
      }
      case OP_SETUPVAL: {
        UpVal *uv = cl->upvals[GETARG_B(i)];
        setobj(L, uv->v, ra);
        luaC_barrier(L, uv, ra);
        continue;
      }
      case OP_SETTABLE: {
        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
        continue;
      }
      case OP_NEWTABLE: {
        int b = GETARG_B(i);
        int c = GETARG_C(i);
        sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
        Protect(luaC_checkGC(L));
        continue;
      }
      case OP_SELF: {
        StkId rb = RB(i);
        setobjs2s(L, ra+1, rb);
        Protect(luaV_gettable(L, rb, RKC(i), ra));
        continue;
      }
      case OP_ADD: {
        arith_op(luai_numadd, TM_ADD);
        continue;
      }
      case OP_SUB: {
        arith_op(luai_numsub, TM_SUB);
        continue;
      }
      case OP_MUL: {
        arith_op(luai_nummul, TM_MUL);
        continue;
      }
      case OP_DIV: {
        arith_op(luai_numdiv, TM_DIV);
        continue;
      }
      case OP_MOD: {
        arith_op(luai_nummod, TM_MOD);
        continue;
      }
      case OP_POW: {
        arith_op(luai_numpow, TM_POW);
        continue;
      }
      case OP_UNM: {
        TValue *rb = RB(i);
        if (ttisnumber(rb)) {
          lua_Number nb = nvalue(rb);
          setnvalue(ra, luai_numunm(nb));
        }
        else {
          Protect(luaV_arith(L, ra, rb, rb, TM_UNM));
        }
        continue;
      }
      case OP_NOT: {
        int res = l_isfalse(RB(i));  /* next assignment may change this value */
        setbvalue(ra, res);
        continue;
      }
      case OP_LEN: {
        const TValue *rb = RB(i);
        switch (ttype(rb)) {
          case LUA_TTABLE: {
            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
            break;
          }
          case LUA_TSTRING: {
            setnvalue(ra, cast_num(tsvalue(rb)->len));
            break;
          }
          default: {  /* try metamethod */
            Protect(
              if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
                luaG_typeerror(L, rb, "get length of");
            )
          }
        }
        continue;
      }
      case OP_CONCAT: {
        int b = GETARG_B(i);
        int c = GETARG_C(i);
        Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
        setobjs2s(L, RA(i), base+b);
        continue;
      }
      case OP_JMP: {
        dojump(L, pc, GETARG_sBx(i));
        continue;
      }
      case OP_EQ: {
        TValue *rb = RKB(i);
        TValue *rc = RKC(i);
        Protect(
          if (equalobj(L, rb, rc) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
      case OP_LT: {
        Protect(
          if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
      case OP_LE: {
        Protect(
          if (luaV_lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
예제 #25
0
bool
newcontrols(dbref who, dbref what, bool true_c)
{
    dbref index;

    /* No one controls invalid objects */
    /* if (what < 0 || what >= db_top)  -- not good enough */
    if (!OkObj(what) || !OkObj(who))
        return 0;

    /* Garbage controls nothing. */
    if (Typeof(who) == TYPE_GARBAGE)
        return 0;

    /* No one controls garbage */
    if (Typeof(what) == TYPE_GARBAGE)
        return 0;

    /* Puppets are based on owner */
    if (Typeof(who) != TYPE_PLAYER)
        who = OWNER(who);

    /* owners control their own stuff */
    /* Makes stuff faster here. -Hinoserm */
    if (who == OWNER(what))
        return 1;

    /* CONTROL_ALL controls all objects */
    if ((POWERS(who) & POW_CONTROL_ALL) && !Protect(what))
        return 1;

    /* CONTROL_MUF power controls all MUF objects */
    if ((POWERS(who) & POW_CONTROL_MUF) && (Typeof(what) == TYPE_PROGRAM)
        && (!(Protect(what))))
        return 1;

    /* Wizard controls (most) everything else */
    if (Wiz(who) && (!(Protect(what) && MLevel(OWNER(what)) >= LBOY)
                     || MLevel(who) >= LBOY))
        if (tp_fb_controls ? (MLevel(who) >= LWIZ)
            : (MLevel(who) >= MLevel(OWNER(what))))
            return 1;

    /* If realms control is enabled, the player will Control anything 
     * contained in a parent room he owns with at W1 bit or higher on it.
     * This gives him power to affect any object in his w-bitted parent room.
     */

    /* 
     *  Read the manual (help CONTROLS) about this new stuff.
     */

#ifdef CONTROLS_SUPPORT
    if (!true_c) {
        if (controlsEx(who, what))
            return 1;

        if (tp_realms_control) {
            if (!tp_wiz_realms) {
                if (Typeof(what) != TYPE_PLAYER)
                    for (index = what; index != NOTHING; index = getloc(index))
                        if ((controlsEx(who, index))
                            && (Typeof(index) == TYPE_ROOM
                                && ((FLAGS(index) & BUILDER) || Mage(index))))
                            return 1;
            } else {
                if (Typeof(what) != TYPE_PLAYER)
                    for (index = what; index != NOTHING; index = getloc(index))
                        if ((controlsEx(who, index))
                            && (Typeof(index) == TYPE_ROOM && (Mage(index))))
                            return 1;
            }
        }
    } else {
#endif

        if (tp_realms_control && (Typeof(what) != TYPE_PLAYER))
            for (index = what; index != NOTHING; index = getloc(index))
                if ((OWNER(index) == who) && (Typeof(index) == TYPE_ROOM
                                              && Mage(index)))
                    return 1;
#ifdef CONTROLS_SUPPORT
    }
#endif

    return 0;
}