From bc717d84023eadd0fe94668f4034e4a09e4be9c9 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 15 Jun 2009 16:07:08 -0700 Subject: [PATCH] Implement inlining that works with both C99 and all versions of GCC. --- Makefile | 3 ++- upb.h | 10 +++++++++ upb_parse.c | 2 +- upb_parse.h | 2 +- upb_struct.c | 40 +----------------------------------- upb_struct.h | 57 ++++++++++++++++++++++++++-------------------------- upb_table.h | 8 ++++---- 7 files changed, 48 insertions(+), 74 deletions(-) diff --git a/Makefile b/Makefile index da620fe1d2..a95652a81a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ .PHONY: all clean CC=gcc -CFLAGS=-std=c99 +CXX=g++ +CFLAGS=-std=c99 -fgnu89-inline CPPFLAGS=-O3 -Wall -Wextra -pedantic -g OBJ=upb_parse.o upb_table.o upb_struct.o descriptor.o all: $(OBJ) test_table diff --git a/upb.h b/upb.h index b09a39cbe3..ae1845a181 100644 --- a/upb.h +++ b/upb.h @@ -15,6 +15,16 @@ extern "C" { #endif +/* Portable inlining strategy: use C99 rules except on GCC. + * see: http://www.greenend.org.uk/rjk/2003/03/inline.html. */ +#ifndef INLINE +# if __GNUC__ && !__GNUC_STDC_INLINE__ +# define INLINE extern inline +# else +# define INLINE inline +# endif +#endif + /* The maximum that any submessages can be nested. Matches proto2's limit. */ #define UPB_MAX_NESTING 64 diff --git a/upb_parse.c b/upb_parse.c index 458876e442..3dac5ebe09 100644 --- a/upb_parse.c +++ b/upb_parse.c @@ -4,6 +4,7 @@ * Copyright (c) 2008-2009 Joshua Haberman. See LICENSE for details. */ +#define INLINE #include "upb_parse.h" #include @@ -262,4 +263,3 @@ upb_status_t upb_parse_value(uint8_t **b, upb_field_type_t ft, } #undef CASE } - diff --git a/upb_parse.h b/upb_parse.h index 829e97c4f6..068d522d56 100644 --- a/upb_parse.h +++ b/upb_parse.h @@ -27,7 +27,7 @@ upb_status_t parse_tag(uint8_t **buf, struct upb_tag *tag); extern upb_wire_type_t upb_expected_wire_types[]; /* Returns true if wt is the correct on-the-wire type for ft. */ -inline bool upb_check_type(upb_wire_type_t wt, upb_field_type_t ft) { +INLINE bool upb_check_type(upb_wire_type_t wt, upb_field_type_t ft) { return upb_expected_wire_types[ft] == wt; } diff --git a/upb_struct.c b/upb_struct.c index 32847967a9..e3121831ba 100644 --- a/upb_struct.c +++ b/upb_struct.c @@ -1,45 +1,7 @@ /* * upb - a minimalist implementation of protocol buffers. * - * Definitions that will emit code for inline functions, per C99 inlining - * rules (see http://www.greenend.org.uk/rjk/2003/03/inline.html). */ +#define INLINE #include "upb_struct.h" - -#define UPB_DECLARE_ACCESSORS(ctype, name) \ - extern ctype *upb_struct_get_ ## name ## _ptr( \ - uint8_t *s, struct upb_struct_field *f); \ - extern ctype upb_struct_get_ ## name( \ - uint8_t *s, struct upb_struct_field *f); \ - extern void upb_struct_set_ ## name( \ - uint8_t *s, struct upb_struct_field *f, ctype val); - -#define UPB_DECLARE_ARRAY_ACCESSORS(ctype, name) \ - extern ctype *upb_array_get_ ## name ## _ptr(struct upb_array *a, int n); \ - extern ctype upb_array_get_ ## name(struct upb_array *a, int n); \ - extern void upb_array_set_ ## name(struct upb_array *a, int n, ctype val); - -#define UPB_DECLARE_ALL_ACCESSORS(ctype, name) \ - UPB_DECLARE_ACCESSORS(ctype, name) \ - UPB_DECLARE_ARRAY_ACCESSORS(ctype, name) - -UPB_DECLARE_ALL_ACCESSORS(double, double) -UPB_DECLARE_ALL_ACCESSORS(float, float) -UPB_DECLARE_ALL_ACCESSORS(int32_t, int32) -UPB_DECLARE_ALL_ACCESSORS(int64_t, int64) -UPB_DECLARE_ALL_ACCESSORS(uint32_t, uint32) -UPB_DECLARE_ALL_ACCESSORS(uint64_t, uint64) -UPB_DECLARE_ALL_ACCESSORS(bool, bool) -UPB_DECLARE_ALL_ACCESSORS(struct upb_struct_delimited*, bytes) -UPB_DECLARE_ALL_ACCESSORS(struct upb_struct_delimited*, string) -UPB_DECLARE_ALL_ACCESSORS(uint8_t*, substruct) -UPB_DECLARE_ACCESSORS(struct upb_array*, array) - -extern void upb_struct_set(uint8_t *s, struct upb_struct_field *f); -extern void upb_struct_unset(uint8_t *s, struct upb_struct_field *f); -extern bool upb_struct_is_set(uint8_t *s, struct upb_struct_field *f); -extern bool upb_struct_all_required_fields_set( - uint8_t *s, struct upb_struct_definition *d); -extern void upb_struct_clear(uint8_t *s, struct upb_struct_definition *d); - diff --git a/upb_struct.h b/upb_struct.h index 7d5c219f1a..c43fdca8d0 100644 --- a/upb_struct.h +++ b/upb_struct.h @@ -29,6 +29,7 @@ #ifndef PBSTRUCT_H_ #define PBSTRUCT_H_ +#include "upb.h" #include #include #include @@ -134,67 +135,67 @@ UPB_DEFINE_PRIMITIVE_ARRAY(bool, bool) * * These do no existence checks, bounds checks, or type checks. */ -#define UPB_DEFINE_ACCESSORS(ctype, name) \ - inline ctype *upb_struct_get_ ## name ## _ptr( \ +#define UPB_DEFINE_ACCESSORS(ctype, name, INLINE) \ + INLINE ctype *upb_struct_get_ ## name ## _ptr( \ uint8_t *s, struct upb_struct_field *f) { \ return (ctype*)(s + f->byte_offset); \ } \ - inline ctype upb_struct_get_ ## name( \ + INLINE ctype upb_struct_get_ ## name( \ uint8_t *s, struct upb_struct_field *f) { \ return *upb_struct_get_ ## name ## _ptr(s, f); \ } \ - inline void upb_struct_set_ ## name( \ + INLINE void upb_struct_set_ ## name( \ uint8_t *s, struct upb_struct_field *f, ctype val) { \ *upb_struct_get_ ## name ## _ptr(s, f) = val; \ } -#define UPB_DEFINE_ARRAY_ACCESSORS(ctype, name) \ - inline ctype *upb_array_get_ ## name ## _ptr(struct upb_array *a, int n) { \ +#define UPB_DEFINE_ARRAY_ACCESSORS(ctype, name, INLINE) \ + INLINE ctype *upb_array_get_ ## name ## _ptr(struct upb_array *a, int n) { \ return ((ctype*)a->data) + n; \ } \ - inline ctype upb_array_get_ ## name(struct upb_array *a, int n) { \ + INLINE ctype upb_array_get_ ## name(struct upb_array *a, int n) { \ return *upb_array_get_ ## name ## _ptr(a, n); \ } \ - inline void upb_array_set_ ## name(struct upb_array *a, int n, ctype val) { \ + INLINE void upb_array_set_ ## name(struct upb_array *a, int n, ctype val) { \ *upb_array_get_ ## name ## _ptr(a, n) = val; \ } -#define UPB_DEFINE_ALL_ACCESSORS(ctype, name) \ - UPB_DEFINE_ACCESSORS(ctype, name) \ - UPB_DEFINE_ARRAY_ACCESSORS(ctype, name) - -UPB_DEFINE_ALL_ACCESSORS(double, double) -UPB_DEFINE_ALL_ACCESSORS(float, float) -UPB_DEFINE_ALL_ACCESSORS(int32_t, int32) -UPB_DEFINE_ALL_ACCESSORS(int64_t, int64) -UPB_DEFINE_ALL_ACCESSORS(uint32_t, uint32) -UPB_DEFINE_ALL_ACCESSORS(uint64_t, uint64) -UPB_DEFINE_ALL_ACCESSORS(bool, bool) -UPB_DEFINE_ALL_ACCESSORS(struct upb_struct_delimited*, bytes) -UPB_DEFINE_ALL_ACCESSORS(struct upb_struct_delimited*, string) -UPB_DEFINE_ALL_ACCESSORS(uint8_t*, substruct) -UPB_DEFINE_ACCESSORS(struct upb_array*, array) +#define UPB_DEFINE_ALL_ACCESSORS(ctype, name, INLINE) \ + UPB_DEFINE_ACCESSORS(ctype, name, INLINE) \ + UPB_DEFINE_ARRAY_ACCESSORS(ctype, name, INLINE) + +UPB_DEFINE_ALL_ACCESSORS(double, double, INLINE) +UPB_DEFINE_ALL_ACCESSORS(float, float, INLINE) +UPB_DEFINE_ALL_ACCESSORS(int32_t, int32, INLINE) +UPB_DEFINE_ALL_ACCESSORS(int64_t, int64, INLINE) +UPB_DEFINE_ALL_ACCESSORS(uint32_t, uint32, INLINE) +UPB_DEFINE_ALL_ACCESSORS(uint64_t, uint64, INLINE) +UPB_DEFINE_ALL_ACCESSORS(bool, bool, INLINE) +UPB_DEFINE_ALL_ACCESSORS(struct upb_struct_delimited*, bytes, INLINE) +UPB_DEFINE_ALL_ACCESSORS(struct upb_struct_delimited*, string, INLINE) +UPB_DEFINE_ALL_ACCESSORS(uint8_t*, substruct, INLINE) +UPB_DEFINE_ACCESSORS(struct upb_array*, array, INLINE) /* Functions for reading and writing the "set" flags in the pbstruct. Note * that these do not perform any memory management associated with any dynamic * memory these fields may be referencing; that is the client's responsibility. * These *only* set and test the flags. */ -inline void upb_struct_set(uint8_t *s, struct upb_struct_field *f) +INLINE void upb_struct_set(uint8_t *s, struct upb_struct_field *f) { s[f->isset_byte_offset] |= f->isset_byte_mask; } -inline void upb_struct_unset(uint8_t *s, struct upb_struct_field *f) +INLINE void upb_struct_unset(uint8_t *s, struct upb_struct_field *f) { s[f->isset_byte_offset] &= ~f->isset_byte_mask; } -inline bool upb_struct_is_set(uint8_t *s, struct upb_struct_field *f) +INLINE bool upb_struct_is_set(uint8_t *s, struct upb_struct_field *f) { return s[f->isset_byte_offset] & f->isset_byte_mask; } -inline bool upb_struct_all_required_fields_set( +INLINE bool upb_struct_all_required_fields_set( uint8_t *s, struct upb_struct_definition *d) { int num_fields = d->num_required_fields; @@ -207,7 +208,7 @@ inline bool upb_struct_all_required_fields_set( return true; } -inline void upb_struct_clear(uint8_t *s, struct upb_struct_definition *d) +INLINE void upb_struct_clear(uint8_t *s, struct upb_struct_definition *d) { memset(s, 0, d->set_flags_bytes); } diff --git a/upb_table.h b/upb_table.h index 5a23ae56a3..93945c7373 100644 --- a/upb_table.h +++ b/upb_table.h @@ -42,26 +42,26 @@ void upb_inttable_init(struct upb_inttable *table, void *entries, /* Frees any data that was allocated by upb_inttable_init. */ void upb_inttable_free(struct upb_inttable *table); -inline struct upb_inttable_entry *upb_inttable_entry_get( +INLINE struct upb_inttable_entry *upb_inttable_entry_get( void *entries, int32_t pos, int entry_size) { return (struct upb_inttable_entry*)(((char*)entries) + pos*entry_size); } -inline struct upb_inttable_entry *upb_inttable_mainpos2( +INLINE struct upb_inttable_entry *upb_inttable_mainpos2( struct upb_inttable *table, upb_inttable_key_t key, int32_t entry_size) { /* Identity hash for integers. */ int32_t pos = key & (table->size-1); return upb_inttable_entry_get(table->entries, pos, entry_size); } -inline struct upb_inttable_entry *upb_inttable_mainpos( +INLINE struct upb_inttable_entry *upb_inttable_mainpos( struct upb_inttable *table, upb_inttable_key_t key) { return upb_inttable_mainpos2(table, key, table->entry_size); } /* Lookups up key in this table. Inlined because this is in the critical path * of parsing. */ -inline void *upb_inttable_lookup(struct upb_inttable *table, +INLINE void *upb_inttable_lookup(struct upb_inttable *table, int32_t key, int32_t entry_size) { /* TODO: experiment with Cuckoo Hashing, which can perform lookups without