Pointer

Functions

static __inline tm_typetm_block_to_type (tm_block *b)
 Returns the tm_type of a tm_block.
static __inline tm_blocktm_ptr_to_block (char *p)
 Returns the potential tm_block of a potential pointer.
static __inline tm_nodetm_pure_ptr_to_node (void *_p)
 Returns the tm_node of a pointer.
static __inline void * tm_node_to_ptr (tm_node *n)
 Returns the data pointer of a tm_node.
static __inline tm_blocktm_node_to_block (tm_node *n)
 Returns the tm_block of a tm_node.
static __inline tm_nodetm_ptr_to_node (void *p)
 Returns the tm_node of a potential pointer.
static __inline tm_typetm_node_to_type (tm_node *n)
 Returns the tm_type of a tm_node.

Function Documentation

static __inline tm_type* tm_block_to_type ( tm_block b  )  [static]

Returns the tm_type of a tm_block.

Definition at line 19 of file ptr.h.

References tm_block::type.

00020 {
00021   return b->type;
00022 }

static __inline tm_block* tm_node_to_block ( tm_node n  )  [static]

Returns the tm_block of a tm_node.

Definition at line 130 of file ptr.h.

References tm_node_to_ptr(), and tm_ptr_to_block().

Referenced by _tm_check_sweep_error(), _tm_free_inner(), _tm_node_mark(), _tm_node_scan(), _tm_node_scan_some(), _tm_node_sweep_some(), _tm_node_sweep_some_for_type(), _tm_node_unmark_some(), _tm_type_alloc_node_from_free_list(), and tm_write_barrier_node().

00131 {
00132   return tm_ptr_to_block(tm_node_to_ptr(n));
00133 }

Here is the call graph for this function:

Here is the caller graph for this function:

static __inline void* tm_node_to_ptr ( tm_node n  )  [static]

Returns the data pointer of a tm_node.

Adds the tm_node header size to the tm_node address.

Definition at line 120 of file ptr.h.

Referenced by _tm_check_sweep_error(), _tm_node_sweep(), _tm_type_alloc_node_from_free_list(), and tm_node_to_block().

00121 {
00122   return (void*) (n + 1);
00123 }

Here is the caller graph for this function:

static __inline tm_type* tm_node_to_type ( tm_node n  )  [static]

Returns the tm_type of a tm_node.

Definition at line 296 of file ptr.h.

References _tm_block_validate, tm_ptr_to_block(), and tm_block::type.

Referenced by _tm_realloc_inner().

00297 {
00298   tm_block *b = tm_ptr_to_block((char*) n);
00299   _tm_block_validate(b);
00300   return b->type;
00301 }

Here is the call graph for this function:

Here is the caller graph for this function:

static __inline tm_block* tm_ptr_to_block ( char *  p  )  [static]

Returns the potential tm_block of a potential pointer.

FIXME: This code does not work for blocks bigger than tm_block_SIZE.

If tm_ptr_AT_END_IS_VALID is true, A pointer directly at the end of tm_block should be considered a pointer into the tm_block before it, because there may be a node allocated contigiously before tm_block header.

Example:

 ... ----------------+----------------------------- ... 
          tm_block a | tm_block b                   
     |  node | node  | tm_block HDR | node | node | 
 ... ----------------+------------------------------... 
             ^       ^
             |       |
             p!      p?
 

Code behaving like this might be pathological, but is valid:

   int *p = tm_alloc(sizeof(p[0]) * 10);
   int i = 10;
   while ( -- i >= 0 ) {
     *(p ++) = i;
     some_function_that_calls_tm_alloc(); 
     //
     // when i == 0, p is (just) past end of tm_alloc() data space and a GC happens.
     // There are no live pointers to the original tm_alloc() data space. 
     //
   }
   p -= 10; 
   // p goes back original tm_alloc() data space, 
   // but p has been reclaimed!
 

If tm_ptr_AT_END_IS_VALID is false, Mask off the tm_block_SIZE bits from the address.

Definition at line 31 of file ptr.h.

References tm_block_SIZE, tm_block_SIZE_MASK, and tm_msg().

Referenced by tm_node_to_block(), tm_node_to_type(), and tm_ptr_to_node().

00032 {
00033   /**
00034    * If tm_ptr_AT_END_IS_VALID is true,
00035    * A pointer directly at the end of tm_block should be considered
00036    * a pointer into the tm_block before it,
00037    * because there may be a node allocated contigiously before
00038    * tm_block header.
00039    *
00040    * Example:
00041    * 
00042    * <pre>
00043    *
00044    * ... ----------------+----------------------------- ... 
00045    *          tm_block a | tm_block b                   
00046    *     |  node | node  | tm_block HDR | node | node | 
00047    * ... ----------------+------------------------------... 
00048    *             ^       ^
00049    *             |       |
00050    *             p!      p?
00051    *
00052    * </pre>
00053    *
00054    * Code behaving like this might be pathological, but is valid:
00055    * 
00056    * <pre>
00057    * 
00058    *   int *p = tm_alloc(sizeof(p[0]) * 10);
00059    *   int i = 10;
00060    *   while ( -- i >= 0 ) {
00061    *     *(p ++) = i;
00062    *     some_function_that_calls_tm_alloc(); 
00063    *     //
00064    *     // when i == 0, p is (just) past end of tm_alloc() data space and a GC happens.
00065    *     // There are no live pointers to the original tm_alloc() data space. 
00066    *     //
00067    *   }
00068    *   p -= 10; 
00069    *   // p goes back original tm_alloc() data space, 
00070    *   // but p has been reclaimed!
00071    *
00072    * </pre>
00073    */
00074 
00075 #if tm_ptr_AT_END_IS_VALID
00076   char *b; /*!< The pptr aligned to the tm_block_SIZE. */
00077   size_t offset; /*! The offset of the pptr in a tm_block. */
00078 
00079   /*! Find the offset of p in an aligned tm_block. */
00080   offset = (((unsigned long) p) % tm_block_SIZE);
00081   b = p - offset;
00082   /*! If the pptr is directly at the beginning of the block, */
00083   if ( offset == 0 && p ) {
00084     /*! Assume its in the previous block, by subtracting tm_block_SIZE. */
00085     b -= tm_block_SIZE;
00086     tm_msg("P bb p%p b%p\n", (void*) p, (void*) b);
00087     // tm_stop();
00088   }
00089 
00090   return (void*) b;
00091 #else
00092   /**
00093    * If tm_ptr_AT_END_IS_VALID is false,
00094    * Mask off the tm_block_SIZE bits from the address.
00095    */
00096   return (void*) ((unsigned long) p & tm_block_SIZE_MASK);
00097 #endif /* tm_ptr_AT_END_IS_VALID */
00098 }

Here is the call graph for this function:

Here is the caller graph for this function:

static __inline tm_node* tm_ptr_to_node ( void *  p  )  [static]

Returns the tm_node of a potential pointer.

If tm_ptr_AT_END_IS_VALID is true, A pointer directly at the end of block should be considered a pointer into the block before it. See tm_ptr_to_block().

Avoid pointers into pages not marked in use.

Get the block and type.

Avoid untyped blocks.

Avoid references to block headers or outsize the allocated space.

Normalize p to node head by using its tm_type size.

If tm_ptr_AT_END_IS_VALID is true, If the pointer is directly after a node boundary assume it's a pointer to the node before.

 node0               node1
 +---------------...-+---------------...-+...
 | tm_node | t->size | tm_node | t->size |
 +---------------...-+---------------...-+...
 ^                   ^
 |                   |
 new pp              pp
 

Translate the pointer back to the tm_block header.

If the pointer is in the node header, it's not a pointer into the node data.

 node0               node1
 +---------------...-+---------------...-+...
 | tm_node | t->size | tm_node | t->size |
 +---------------...-+---------------...-+...
                         ^
                         |
                         pp
 

Remove intra-node offset.

 node0               node1
 +---------------...-+---------------...-+...
 | tm_node | t->size | tm_node | t->size |
 +---------------...-+---------------...-+...
                     ^            ^
                     |            |
                     new pp       pp
 

Translate back to block header.

It's a node.

Avoid references to free nodes.

Return a node.

Definition at line 140 of file ptr.h.

References _tm_block_validate, _tm_page_in_use(), tm_type::n, tm_block_HDR_SIZE, tm_block_node_begin, tm_block_node_next_parcel, tm_block_node_size, tm_msg(), tm_node_color, tm_node_HDR_SIZE, tm_ptr_h, tm_ptr_is_aligned_to_block, tm_ptr_l, tm_ptr_to_block(), tm_WHITE, and tm_block::type.

Referenced by __tm_write_barrier(), _tm_alloc_type_inner(), and _tm_mark_possible_ptr().

00141 {
00142   tm_block *b;
00143 
00144 #if 0
00145   /*! If p is 0, it is not a pointer to a tm_node. */
00146   if ( ! p )
00147     return 0;
00148 #endif
00149 
00150   /**
00151    * If tm_ptr_AT_END_IS_VALID is true,
00152    * A pointer directly at the end of block should be considered
00153    * a pointer into the block before it.
00154    * See tm_ptr_to_block().
00155    */
00156 #if tm_ptr_AT_END_IS_VALID
00157   if ( tm_ptr_is_aligned_to_block(p) ) {
00158     /*! This allows _tm_page_in_use(p) to pass. */
00159     p = p - 1;
00160   }
00161 #endif
00162 
00163 #if 1
00164   /*! Avoid pointers into pages not marked in use. */
00165   if ( ! _tm_page_in_use(p) ) 
00166     return 0;
00167 #else
00168   /*! Avoid out of range pointers. */
00169   if ( ! (tm_ptr_l <= p && p <= tm_ptr_h) )
00170     return 0;
00171 #endif
00172 
00173   /*! Get the block and type. */
00174   b = tm_ptr_to_block(p);
00175 
00176   _tm_block_validate(b);
00177 
00178   /*! Avoid untyped blocks. */
00179   if ( ! b->type )
00180     return 0;
00181 
00182   /*! Avoid references to block headers or outsize the allocated space. */ 
00183   if ( p > tm_block_node_next_parcel(b) )
00184     return 0;
00185 
00186   if ( p < tm_block_node_begin(b) )
00187     return 0;
00188 
00189   /*! Normalize p to node head by using its tm_type size. */
00190   {
00191     unsigned long pp = (unsigned long) p;
00192     unsigned long node_size = tm_block_node_size(b);
00193     tm_node *n;
00194     
00195     /*
00196     ** Translate away the block header.
00197     */
00198     pp -= (unsigned long) b + tm_block_HDR_SIZE;
00199 
00200 
00201     {
00202       unsigned long node_off = pp % node_size;
00203 
00204       /**
00205        * If tm_ptr_AT_END_IS_VALID is true,
00206        * If the pointer is directly after a node boundary
00207        * assume it's a pointer to the node before.
00208        *
00209        * <pre>
00210        *
00211        * node0               node1
00212        * +---------------...-+---------------...-+...
00213        * | tm_node | t->size | tm_node | t->size |
00214        * +---------------...-+---------------...-+...
00215        * ^                   ^
00216        * |                   |
00217        * new pp              pp
00218        *
00219        * </pre>
00220        *
00221        * Translate the pointer back to the tm_block header.
00222        */
00223 #if tm_ptr_AT_END_IS_VALID
00224       if ( node_off == 0 && pp ) {
00225         pp -= node_size;
00226         pp += (unsigned long) b + tm_block_HDR_SIZE;
00227 
00228 #if 0   
00229         tm_msg("P nb p%p p0%p\n", (void*) p, (void*) pp);
00230 #endif
00231       } else
00232 #endif
00233 
00234         /**
00235          * If the pointer is in the node header,
00236          * it's not a pointer into the node data.
00237          * 
00238          * <pre>
00239          * node0               node1
00240          * +---------------...-+---------------...-+...
00241          * | tm_node | t->size | tm_node | t->size |
00242          * +---------------...-+---------------...-+...
00243          *                         ^
00244          *                         |
00245          *                         pp
00246          * </pre>
00247          *
00248          */
00249       if ( node_off < tm_node_HDR_SIZE ) {
00250         return 0;
00251       }
00252 
00253       /**
00254        * Remove intra-node offset.
00255        *
00256        * <pre>
00257        *
00258        * node0               node1
00259        * +---------------...-+---------------...-+...
00260        * | tm_node | t->size | tm_node | t->size |
00261        * +---------------...-+---------------...-+...
00262        *                     ^            ^
00263        *                     |            |
00264        *                     new pp       pp
00265        *
00266        * </pre>
00267        *
00268        */
00269       else {
00270         pp -= node_off;
00271 
00272         /**
00273          * Translate back to block header.
00274          */
00275         pp += (unsigned long) b + tm_block_HDR_SIZE;
00276       }
00277     }
00278 
00279     /*! It's a node. */
00280     n = (tm_node*) pp;
00281 
00282     /*! Avoid references to free nodes. */
00283     if ( tm_node_color(n) == tm_WHITE )
00284       return 0;
00285 
00286     /*! Return a node. */
00287     return n;
00288   }
00289 }

Here is the call graph for this function:

Here is the caller graph for this function:

static __inline tm_node* tm_pure_ptr_to_node ( void *  _p  )  [static]

Returns the tm_node of a pointer.

Subtracts the tm_node header size from the pointer.

Definition at line 107 of file ptr.h.

Referenced by __tm_write_barrier_pure(), _tm_free_inner(), and _tm_realloc_inner().

00108 {
00109   // return (tm_node*) (((char*) _p) - tm_node_HDR_SIZE);
00110   return ((tm_node*) _p) - 1;
00111 }

Here is the caller graph for this function:


Generated on Mon Jan 25 06:33:12 2010 for TM(tredmill) by  doxygen 1.6.1