[sgen] Pack structs for binary protocol entries
authorVlad Brezae <brezaevlad@gmail.com>
Fri, 6 May 2016 00:32:17 +0000 (03:32 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Mon, 9 May 2016 23:31:43 +0000 (02:31 +0300)
We save space and support cross platform grep-ing across platforms with the same word size.

mono/metadata/sgen-client-mono.h
mono/sgen/sgen-protocol-def.h
mono/sgen/sgen-protocol.c
mono/sgen/sgen-protocol.h
tools/sgen/.gitignore
tools/sgen/Makefile.am
tools/sgen/sgen-entry-stream.c
tools/sgen/sgen-entry-stream.h
tools/sgen/sgen-grep-binprot-main.c
tools/sgen/sgen-grep-binprot.c
tools/sgen/sgen-grep-binprot.h

index e9f9b1a81a7a5ddeaad89a7ae0ddac596f328fcc..7fe3d017684127007a4e74b72f8f1ae795bf6a56 100644 (file)
@@ -694,6 +694,11 @@ sgen_client_binary_protocol_concurrent_sweep_end (long long timestamp)
 {
 }
 
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_header (long long check, int version, int ptr_size, gboolean little_endian)
+{
+}
+
 int sgen_thread_handshake (BOOL suspend);
 gboolean sgen_suspend_thread (SgenThreadInfo *info);
 gboolean sgen_resume_thread (SgenThreadInfo *info);
index e68f5bf76271e2337868c93513e068ce7a932574..41b8b83829183ecfcefe33f0a761c877c8b25f2c 100644 (file)
@@ -442,6 +442,13 @@ MATCH_INDEX (BINARY_PROTOCOL_MATCH)
 IS_VTABLE_MATCH (FALSE)
 END_PROTOCOL_ENTRY
 
+BEGIN_PROTOCOL_ENTRY4 (binary_protocol_header, TYPE_LONGLONG, check, TYPE_INT, version, TYPE_INT, ptr_size, TYPE_BOOL, little_endian)
+DEFAULT_PRINT ()
+IS_ALWAYS_MATCH (TRUE)
+MATCH_INDEX (BINARY_PROTOCOL_MATCH)
+IS_VTABLE_MATCH (FALSE)
+END_PROTOCOL_ENTRY_FLUSH
+
 #undef BEGIN_PROTOCOL_ENTRY0
 #undef BEGIN_PROTOCOL_ENTRY1
 #undef BEGIN_PROTOCOL_ENTRY2
index ffc47f248de05a2c17a3f93648118bed4e2079ea..0e77588044ccb5e57630f1bcd699bb740ac10c9c 100644 (file)
@@ -106,6 +106,8 @@ binary_protocol_init (const char *filename, long long limit)
        file_size_limit = limit;
 
        binary_protocol_open_file ();
+
+       binary_protocol_header (PROTOCOL_HEADER_CHECK, PROTOCOL_HEADER_VERSION, SIZEOF_VOID_P, G_BYTE_ORDER == G_LITTLE_ENDIAN);
 #else
        g_error ("sgen binary protocol: not supported");
 #endif
index 6ce194c00d8f684ab76d5c80dc3a4d6ccbc8a61a..1c10d29d5c0e367f07e8d26a0163177da59c1b41 100644 (file)
 
 #include "sgen-gc.h"
 
+#define PROTOCOL_HEADER_CHECK 0xde7ec7ab1ec0de
+#define PROTOCOL_HEADER_VERSION 1
+
 /* Special indices returned by MATCH_INDEX. */
 #define BINARY_PROTOCOL_NO_MATCH (-1)
 #define BINARY_PROTOCOL_MATCH (-2)
 
+/* We pack all protocol structs by default unless specified otherwise */
+#ifndef PROTOCOL_STRUCT_ATTR
+#ifdef __GNUC__
+#define PROTOCOL_STRUCT_ATTR __attribute__ ((packed))
+#else
+#define PROTOCOL_STRUCT_ATTR
+#endif
+#endif
+
 #define PROTOCOL_ID(method) method ## _id
 #define PROTOCOL_STRUCT(method) method ## _struct
 #define CLIENT_PROTOCOL_NAME(method) sgen_client_ ## method
@@ -70,29 +82,29 @@ enum {
 
 #define BEGIN_PROTOCOL_ENTRY0(method)
 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
                t3 f3; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
                t3 f3; \
                t4 f4; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
                t3 f3; \
@@ -100,7 +112,7 @@ enum {
                t5 f5; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
                t3 f3; \
index f5d2a72139742369c24805e39e3eb138bfc5e811..e80e90020170ca10e5e40aa65c008b9c9bd94bd8 100644 (file)
@@ -3,3 +3,4 @@ Makefile
 Makefile.in
 /sgen-grep-binprot
 /*.o
+/*.a
index 6d982d29548ad09a3736ef4f3c0b4e5f83dc4281..8f9473eb55413704455aee1dfb702008ca9cdb75 100644 (file)
@@ -2,10 +2,16 @@ bin_PROGRAMS = sgen-grep-binprot
 
 AM_CPPFLAGS =  $(GLIB_CFLAGS) -I$(top_srcdir)
 
+noinst_LIBRARIES = libsgen-grep-binprot.a libsgen-grep-binprotp.a
+libsgen_grep_binprot_a_SOURCES = sgen-grep-binprot.c
+libsgen_grep_binprot_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)
+libsgen_grep_binprotp_a_SOURCES = sgen-grep-binprot.c
+libsgen_grep_binprotp_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -DBINPROT_HAS_HEADER
+
 sgen_grep_binprot_SOURCES = \
        sgen-grep-binprot-main.c        \
        sgen-grep-binprot.c             \
        sgen-entry-stream.c
 
 sgen_grep_binprot_LDADD = \
-       $(GLIB_LIBS) $(LIBICONV)
+       $(GLIB_LIBS) $(LIBICONV) libsgen-grep-binprot.a libsgen-grep-binprotp.a
index 0e0a3c5fc251ed8c8bfbcebcb8ab76dd1f11e2d8..479f0c24574f81ae61086e043002387532fc3c96 100644 (file)
@@ -22,6 +22,14 @@ init_stream (EntryStream *stream, int file)
        stream->pos = stream->end;
 }
 
+void
+reset_stream (EntryStream *stream)
+{
+       stream->end = stream->buffer + BUFFER_SIZE;
+       stream->pos = stream->end;
+       lseek (stream->file, 0, SEEK_SET);
+}
+
 void
 close_stream (EntryStream *stream)
 {
index 1cf6418006ce9d9f880d2e8a5662a8636af68296..93dd2bf8088504067353384ac51a786623b67809 100644 (file)
@@ -14,6 +14,7 @@ typedef struct {
 } EntryStream;
 
 void init_stream (EntryStream *stream, int file);
+void reset_stream (EntryStream *stream);
 void close_stream (EntryStream *stream);
 gboolean refill_stream (EntryStream *in, size_t size);
 ssize_t read_stream (EntryStream *stream, void *out, size_t size);
index 7a4c363762d00f45466a2de51d5f98dc631db0df..2b74ceda11315275b0adcc8e01a1a993386e925b 100644 (file)
 #include "sgen-entry-stream.h"
 #include "sgen-grep-binprot.h"
 
+GrepEntriesFunction grepers [] = {
+       sgen_binary_protocol_grep_entriesp,
+       sgen_binary_protocol_grep_entries
+};
+
 int
 main (int argc, char *argv[])
 {
@@ -85,8 +90,14 @@ main (int argc, char *argv[])
 
        input_file = input_path ? open (input_path, O_RDONLY) : STDIN_FILENO;
        init_stream (&stream, input_file);
-       sgen_binary_protocol_grep_entries (&stream, num_nums, nums, num_vtables, vtables,
-                               dump_all, pause_times, color_output, first_entry_to_consider);
+       for (i = 0; i < sizeof (grepers) / sizeof (GrepEntriesFunction); i++) {
+               if (grepers [i] (&stream, num_nums, nums, num_vtables, vtables, dump_all,
+                               pause_times, color_output, first_entry_to_consider)) {
+                       /* Success */
+                       break;
+               }
+               reset_stream (&stream);
+       }
        close_stream (&stream);
        if (input_path)
                close (input_file);
index 911d1ce8aaea1bdcedeee6b61f2926888a7730b3..7b46827fcfb330d6e7ada5d13a3e3a350474de6d 100644 (file)
 #include "sgen-entry-stream.h"
 #include "sgen-grep-binprot.h"
 
+#ifdef BINPROT_HAS_HEADER
+#define PACKED_SUFFIX  p
+#else
+#define PROTOCOL_STRUCT_ATTR
+#define PACKED_SUFFIX
+#endif
+
 #if SIZEOF_VOID_P == 4
 typedef int32_t mword;
 #define MWORD_FORMAT_SPEC_D PRId32
@@ -543,8 +550,37 @@ is_vtable_match (mword ptr, int type, void *data)
 #undef TYPE_SIZE
 #undef TYPE_POINTER
 
-void
-sgen_binary_protocol_grep_entries (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
+static gboolean
+sgen_binary_protocol_read_header (EntryStream *stream)
+{
+#ifdef BINPROT_HAS_HEADER
+       char data [MAX_ENTRY_SIZE];
+       int type = read_entry (stream, data);
+       if (type == SGEN_PROTOCOL_EOF)
+               return FALSE;
+       if (type == PROTOCOL_ID (binary_protocol_header)) {
+               PROTOCOL_STRUCT (binary_protocol_header) * str = (PROTOCOL_STRUCT (binary_protocol_header) *) data;
+               if (str->check == PROTOCOL_HEADER_CHECK)
+                       return TRUE;
+       }
+       return FALSE;
+#else
+       /*
+        * This implementation doesn't account for the presence of a header,
+        * reading all the entries with the default configuration of the host
+        * machine. It has to be used only after all other implementations
+        * fail to identify a header, for backward compatibility.
+        */
+       return TRUE;
+#endif
+}
+
+#define CONC(A, B) CONC_(A, B)
+#define CONC_(A, B) A##B
+#define GREP_ENTRIES_FUNCTION_NAME CONC(sgen_binary_protocol_grep_entries, PACKED_SUFFIX)
+
+gboolean
+GREP_ENTRIES_FUNCTION_NAME (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
                        gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider)
 {
        int type;
@@ -556,6 +592,9 @@ sgen_binary_protocol_grep_entries (EntryStream *stream, int num_nums, long nums
        long long pause_times_ts = 0;
        unsigned long long entry_index;
 
+       if (!sgen_binary_protocol_read_header (stream))
+               return FALSE;
+
        entry_index = 0;
        while ((type = read_entry (stream, data)) != SGEN_PROTOCOL_EOF) {
                if (entry_index < first_entry_to_consider)
@@ -618,4 +657,5 @@ sgen_binary_protocol_grep_entries (EntryStream *stream, int num_nums, long nums
                ++entry_index;
        }
        g_free (data);
+       return TRUE;
 }
index 643c0db288c5fce25c47c1e1ad54b55677beed00..360e7d435e360970f06edda4c2aa269f5fe720f9 100644 (file)
@@ -1,3 +1,9 @@
-void
+typedef gboolean (*GrepEntriesFunction) (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
+               gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider);
+
+gboolean
 sgen_binary_protocol_grep_entries (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
                         gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider);
+gboolean
+sgen_binary_protocol_grep_entriesp (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
+                        gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider);