123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- /*
- #define DBG(x) do { x; fflush(stdout); } while(0)
- */
- #define DBG(x) do{}while(0)
- #define DUMP 0
- #define PRF(x) bitarray##x
- #include "bitarray.c"
- #include "util.h"
- #include <caml/memory.h>
- // FROM byterun/gc.h
- #define Caml_white (0 << 8)
- #define Caml_gray (1 << 8)
- #define Caml_blue (2 << 8)
- #define Caml_black (3 << 8)
- #define Colornum_hd(hd) ((color_t) (((hd) >> 8) & 3))
- #define Coloredhd_hd(hd,colnum) (((hd) & ~Caml_black) | ((colnum) << 8))
- #define Col_white (Caml_white >> 8)
- #define Col_gray (Caml_gray >> 8)
- #define Col_blue (Caml_blue >> 8)
- #define Col_black (Caml_black >> 8)
- #define COLORS_INIT_COUNT 256
- //--------------------------------------------------------
- // From byterun/memory.h:
- #define Not_in_heap 0
- #define In_heap 1
- #define In_young 2
- #define In_static_data 4
- #define In_code_area 8
- #ifdef ARCH_SIXTYFOUR
- // 64 bits: Represent page table as a sparse hash table
- int caml_page_table_lookup(void * addr);
- #define Classify_addr(a) (caml_page_table_lookup((void *)(a)))
- #else
- // 32 bits: Represent page table as a 2-level array
- #define Pagetable2_log 11
- #define Pagetable2_size (1 << Pagetable2_log)
- #define Pagetable1_log (Page_log + Pagetable2_log)
- #define Pagetable1_size (1 << (32 - Pagetable1_log))
- CAMLextern unsigned char * caml_page_table[Pagetable1_size];
- #define Pagetable_index1(a) (((uintnat)(a)) >> Pagetable1_log)
- #define Pagetable_index2(a) \
- ((((uintnat)(a)) >> Page_log) & (Pagetable2_size - 1))
- #define Classify_addr(a) \
- caml_page_table[Pagetable_index1(a)][Pagetable_index2(a)]
- #endif
- #define Is_in_heap_or_young(a) (Classify_addr(a) & (In_heap | In_young))
- //--------------------------------------------------------
- unsigned char* colors = NULL;
- size_t colors_bitcap = 0;
- size_t colors_writeindex = 0;
- size_t colors_readindex = 0;
- void colors_init(void)
- {
- ASSERT(colors==NULL, "colors_init");
- colors_bitcap = COLORS_INIT_COUNT*2;
- colors = bitarray_alloc(colors_bitcap);
- colors_writeindex = 0;
- colors_readindex = 0;
- return;
- }
- void colors_deinit(void)
- {
- bitarray_free(colors);
- colors = NULL;
- return;
- }
- void writebit(int bit)
- {
- if (colors_writeindex == colors_bitcap)
- {
- size_t colors_new_bitcap = colors_bitcap * 2;
- unsigned char* newarr = bitarray_realloc(colors, colors_new_bitcap);
- ASSERT(newarr != NULL, "realloc");
- colors = newarr;
- colors_bitcap = colors_new_bitcap;
- };
- ASSERT(colors_writeindex < colors_bitcap, "bound on write");
- bitarray_set(colors, colors_writeindex++, bit);
- return;
- }
- int readbit(void)
- {
- int res;
- ASSERT(colors_readindex < colors_writeindex, "bound on read");
- res = bitarray_get(colors, colors_readindex++);
- ASSERT(res == 0 || res == 1, "bitarray_get");
- return res;
- }
- void writeint(unsigned int arg, unsigned int width)
- {
- while(width-- > 0)
- {
- writebit(arg&1);
- arg >>= 1;
- };
- ASSERT(arg == 0, "writeint");
- return;
- }
- unsigned int readint(unsigned int width)
- {
- unsigned int acc = 0;
- unsigned int hibit = 1 << (width-1);
- ASSERT(width > 0, "readint width");
- while(width-- > 0)
- {
- int bit = readbit();
- acc >>= 1;
- if (bit) acc |= hibit;
- };
- return acc;
- }
- int prev_color = 0;
- int repeat_count = 0;
- #define BITS_FOR_COUNT 5
- #define BITS_FOR_ORDER 4
- #define MAX_REPEAT_COUNT (1<<BITS_FOR_COUNT)
- #define MAX_REPEAT_ORDER (1<<BITS_FOR_ORDER)
- void rle_write_repeats(void)
- {
- while(repeat_count >= MAX_REPEAT_COUNT)
- {
- unsigned int ord = 0;
- while(ord < MAX_REPEAT_ORDER-1 && (1<<ord) <= repeat_count/2)
- {
- ++ord;
- };
- writeint(Col_blue, 2);
- writeint(1, 1);
- ASSERT((1<<ord) != 0, "write_repeats#2");
- writeint(ord, BITS_FOR_ORDER);
- repeat_count -= (1 << ord);
- };
- ASSERT(repeat_count < MAX_REPEAT_COUNT, "write_repeats");
- if (repeat_count > 0)
- {
- writeint(Col_blue, 2);
- writeint(0, 1);
- writeint(repeat_count, BITS_FOR_COUNT);
- repeat_count = 0;
- };
- return;
- }
- void rle_write_flush(void)
- {
- if (repeat_count > 0)
- {
- rle_write_repeats();
- };
- ASSERT(repeat_count == 0, "rle_write_flush");
- return;
- }
- void rle_read_flush(void)
- {
- DBG(printf("rle_read_flush: repeat_count=%i, ri=%i, wi=%i\n",
- repeat_count, colors_readindex, colors_writeindex)
- );
- ASSERT
- ( repeat_count == 0
- && colors_readindex == colors_writeindex
- , "rle_reader_flush"
- );
- return;
- }
- void rle_write(int color)
- {
- if (prev_color == color)
- {
- ++repeat_count;
- }
- else
- {
- rle_write_flush();
- ASSERT(color != Col_blue, "rle_write");
- writeint(color, 2);
- prev_color = color;
- };
- }
- int rle_read(void);
- int rle_read(void)
- {
- if (repeat_count > 0)
- {
- --repeat_count;
- return prev_color;
- }
- else
- {
- int c = readint(2);
- if (c == Col_blue)
- {
- int rk = readint(1);
- if (rk == 0)
- { repeat_count = readint(BITS_FOR_COUNT); }
- else
- { repeat_count = 1 << readint(BITS_FOR_ORDER); };
- ASSERT(repeat_count > 0, "rle_read");
- return rle_read();
- }
- else
- {
- prev_color = c;
- return c;
- };
- };
- }
- void rle_init(void)
- {
- prev_color = 0;
- repeat_count = 0;
- return;
- }
- void writecolor(int col)
- {
- ASSERT(col >= 0 && col <= 3 && col != Col_blue, "writecolor");
- rle_write(col);
- return;
- }
- int readcolor(void)
- {
- int res = rle_read();
- ASSERT(res >= 0 && res <= 3 && res != Col_blue, "readcolor");
- return res;
- }
- size_t acc_hdrs;
- size_t acc_data;
- size_t acc_depth;
- #define COND_BLOCK(q) \
- ( Is_block(q) \
- && (Is_in_heap_or_young(q)) \
- )
- #define GEN_COND_NOTVISITED(v, op) \
- ( Colornum_hd(Hd_val(v)) op Col_blue )
- #define ENTERING_COND_NOTVISITED(v) GEN_COND_NOTVISITED(v, != )
- #define RESTORING_COND_NOTVISITED(v) GEN_COND_NOTVISITED(v, == )
- #define REC_WALK(cond_notvisited, rec_call, rec_goto) \
- size_t i; \
- value prev_block; \
- value f; \
- prev_block = Val_unit; \
- \
- for (i=0; i<sz; ++i) \
- { \
- f = Field(v,i); \
- DBG(printf("(*%p)[%i/%i] = %p\n", (void*)v, i, sz, (void*)f)); \
- \
- if ( COND_BLOCK(f) ) \
- { \
- if (prev_block != Val_unit && cond_notvisited(prev_block)) \
- { \
- rec_call \
- }; \
- prev_block = f; \
- }; /* if ( COND_BLOCK ) */ \
- }; \
- \
- if (prev_block != Val_unit && cond_notvisited(prev_block) ) \
- { \
- rec_goto \
- };
- void c_rec_objsize(value v, size_t depth)
- {
- int col;
- header_t hd;
- size_t sz;
- rec_enter:
- DBG(printf("c_rec_objsize: v=%p\n"
- , (void*)v)
- );
- sz = Wosize_val(v);
- DBG(printf("after_if: v=%p\n", (void*)v));
- acc_data += sz;
- ++acc_hdrs;
- if (depth > acc_depth) { acc_depth = depth; };
- hd = Hd_val(v);
- col = Colornum_hd(hd);
- writecolor(col);
- DBG(printf("COL: w %08lx %i\n", v, col));
- Hd_val(v) = Coloredhd_hd(hd, Col_blue);
- if (Tag_val(v) < No_scan_tag)
- {
- REC_WALK
- ( ENTERING_COND_NOTVISITED
- , c_rec_objsize(prev_block, (depth+1));
- , v = prev_block; \
- depth = depth + 1; \
- DBG(printf("goto, depth=%i, v=%p\n", depth, (void*)v)); \
- goto rec_enter;
- )
- }; /* (Tag_val(v) < No_scan_tag) */
- return;
- }
- void restore_colors(value v)
- {
- int col;
- rec_restore:
- col = readcolor();
- DBG(printf("COL: r %08lx %i\n", v, col));
- Hd_val(v) = Coloredhd_hd(Hd_val(v), col);
- if (Tag_val(v) < No_scan_tag)
- {
- size_t sz = Wosize_val(v);
- REC_WALK
- ( RESTORING_COND_NOTVISITED
- , restore_colors(prev_block);
- , v = prev_block; \
- goto rec_restore;
- )
- };
- return;
- }
- int c_objsize(value v, value scan, value reach, size_t* headers, size_t* data, size_t* depth)
- {
- value head;
- int reached = 0;
- colors_init();
- rle_init();
- /*
- DBG(printf("young heap from %p to %p\n", caml_young_start, caml_young_end));
- DBG(printf("old heap from %p to %p\n", caml_heap_start, caml_heap_end));
- */
- DBG(printf("COL writing\n"));
- head = scan;
- while( COND_BLOCK(head) ) {
- value v = Field(head,0);
- header_t hd = Hd_val(v);
- int col = Colornum_hd(hd);
- head = Field(head,1);
- if( col == Col_blue ) continue;
- writecolor(col);
- Hd_val(v) = Coloredhd_hd(hd, Col_blue);
- }
- acc_data = 0;
- acc_hdrs = 0;
- acc_depth = 0;
- if ( COND_BLOCK(v) && Colornum_hd(Hd_val(v)) != Col_blue )
- {
- c_rec_objsize(v, 0);
- };
- if( headers != NULL ) {
- *headers = acc_hdrs;
- *data = acc_data;
- *depth = acc_depth;
- }
- rle_write_flush();
- DBG(printf("COL reading\n"));
- rle_init();
- head = scan;
- while( COND_BLOCK(head) ) {
- value v = Field(head,0);
- int col;
- head = Field(head,1);
- if( Colornum_hd(Hd_val(v)) != Col_blue ) continue;
- col = readcolor();
- Hd_val(v) = Coloredhd_hd(Hd_val(v), col);
- }
- while( COND_BLOCK(reach) ) {
- value v = Field(reach,0);
- if( Colornum_hd(Hd_val(v)) == Col_blue ) {
- reached = 1;
- break;
- }
- reach = Field(reach,1);
- }
- if ( COND_BLOCK(v) && Colornum_hd(Hd_val(v)) == Col_blue )
- {
- restore_colors(v);
- };
- rle_read_flush();
- #if DUMP
- printf("objsize: bytes for rle data = %i\n", colors_readindex/8);
- fflush(stdout);
- {
- FILE* f = fopen("colors-dump", "w");
- fwrite(colors, 1, colors_readindex/8, f);
- fclose(f);
- };
- #endif
- colors_deinit();
- DBG(printf("c_objsize done.\n"));
- return reached;
- }
- #include <caml/alloc.h>
- value ml_objsize(value start,value scan,value reach)
- {
- CAMLparam2(start,scan);
- CAMLlocal1(res);
- size_t hdrs, data, depth;
- int reached = c_objsize(start, scan, reach, &hdrs, &data, &depth);
- res = caml_alloc_small(4, 0);
- Field(res, 0) = Val_int(data);
- Field(res, 1) = Val_int(hdrs);
- Field(res, 2) = Val_int(depth);
- Field(res, 3) = Val_bool(reached);
- CAMLreturn(res);
- }
|