예제 #1
0
파일: mpsi.c 프로젝트: alisheikh/hornet
/* mps_addr_fmt -- what format might this address have?
 *
 * .per-pool: There's no reason why all objects in a pool should have 
 * the same format.  But currently, MPS internals support at most one 
 * format per pool.
 *
 * If the address is in a pool and has a format, returns TRUE and 
 * updates *mps_fmt_o to be that format.  Otherwise, returns FALSE 
 * and does not update *mps_fmt_o.
 *
 * Note: may return an MPS-internal format.
 */
mps_bool_t mps_addr_fmt(mps_fmt_t *mps_fmt_o,
                        mps_arena_t arena,
                        mps_addr_t p)
{
    Bool b;
    Pool pool;
    Format format = 0;

    AVER(mps_fmt_o != NULL);
    /* mps_arena -- will be checked by ArenaEnterRecursive */
    /* p -- cannot be checked */

    /* One of the few functions that can be called
       during the call to an MPS function.  IE this function
       can be called when walking the heap. */
    ArenaEnterRecursive(arena);
    /* .per-pool */
    b = PoolOfAddr(&pool, arena, (Addr)p);
    if(b)
      b = PoolFormat(&format, pool);
    ArenaLeaveRecursive(arena);

    if(b)
      *mps_fmt_o = (mps_fmt_t)format;

    return b;
}
예제 #2
0
파일: buffer.c 프로젝트: Ravenbrook/mps
Bool BufferTrip(Buffer buffer, Addr p, Size size)
{
  Pool pool;

  AVERT(Buffer, buffer);
  AVER(p != 0);
  AVER(size > 0);
  AVER(SizeIsAligned(size, buffer->alignment));

  /* The limit field should be zero, because that's how trip gets */
  /* called.  See .commit.trip. */
  AVER(buffer->ap_s.limit == 0);
  /* Of course we should be trapped. */
  AVER(BufferIsTrapped(buffer));

  /* The init and alloc fields should be equal at this point, because */
  /* the step .commit.update has happened. */
  AVER(buffer->ap_s.init == buffer->ap_s.alloc);

  /* The p parameter points at the base address of the allocated */
  /* block, the end of which should now coincide with the init and */
  /* alloc fields. */
  /* Note that we don't _really_ care about p too much.  We don't */
  /* do anything else with it apart from these checks. (in particular */
  /* it seems like the algorithms could be modified to cope with the */
  /* case of the object having been copied between Commit updating i */
  /* and testing limit) */
  AVER(AddrAdd(p, size) == buffer->ap_s.init);

  pool = BufferPool(buffer);

  AVER(PoolHasAddr(pool, p));

  /* .trip.unflip: If the flip occurred before commit set "init" */
  /* to "alloc" (see .commit.before) then the object is invalid */
  /* (won't've been scanned) so undo the allocation and fail commit. */
  /* Otherwise (see .commit.after) the object is valid (will've been */
  /* scanned) so commit can simply succeed. */
  if ((buffer->mode & BufferModeFLIPPED)
      && buffer->ap_s.init != buffer->initAtFlip) {
    /* Reset just enough state for Reserve/Fill to work. */
    /* The buffer is left trapped and we leave the untrapping */
    /* for the next reserve (which goes out of line to Fill */
    /* (.fill.unflip) because the buffer is still trapped) */
    buffer->ap_s.init = p;
    buffer->ap_s.alloc = p;
    return FALSE;
  }

  /* Emit event including class if logged */
  if (buffer->mode & BufferModeLOGGED) {
    Bool b;
    Format format;
    Addr clientClass;

    b = PoolFormat(&format, buffer->pool);
    if (b) {
      clientClass = format->klass(p);
    } else {
      clientClass = (Addr)0;
    }
    EVENT4(BufferCommit, buffer, p, size, clientClass);
  }
  return TRUE;
}