Browse Source

[sgen] Pack structs for binary protocol entries

We save space and support cross platform grep-ing across platforms with the same word size.
Vlad Brezae 9 years ago
parent
commit
3eb249ce86

+ 5 - 0
mono/metadata/sgen-client-mono.h

@@ -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);

+ 7 - 0
mono/sgen/sgen-protocol-def.h

@@ -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

+ 2 - 0
mono/sgen/sgen-protocol.c

@@ -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

+ 18 - 6
mono/sgen/sgen-protocol.h

@@ -14,10 +14,22 @@
 
 #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; \

+ 1 - 0
tools/sgen/.gitignore

@@ -3,3 +3,4 @@ Makefile
 Makefile.in
 /sgen-grep-binprot
 /*.o
+/*.a

+ 7 - 1
tools/sgen/Makefile.am

@@ -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

+ 8 - 0
tools/sgen/sgen-entry-stream.c

@@ -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)
 {

+ 1 - 0
tools/sgen/sgen-entry-stream.h

@@ -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);

+ 13 - 2
tools/sgen/sgen-grep-binprot-main.c

@@ -15,6 +15,11 @@
 #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);

+ 42 - 2
tools/sgen/sgen-grep-binprot.c

@@ -18,6 +18,13 @@
 #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;
 }

+ 7 - 1
tools/sgen/sgen-grep-binprot.h

@@ -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);