Implement inlining that works with both C99 and all versions of GCC.

pull/13171/head
Joshua Haberman 16 years ago
parent ccca4d7136
commit bc717d8402
  1. 3
      Makefile
  2. 10
      upb.h
  3. 2
      upb_parse.c
  4. 2
      upb_parse.h
  5. 40
      upb_struct.c
  6. 57
      upb_struct.h
  7. 8
      upb_table.h

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

10
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

@ -4,6 +4,7 @@
* Copyright (c) 2008-2009 Joshua Haberman. See LICENSE for details.
*/
#define INLINE
#include "upb_parse.h"
#include <assert.h>
@ -262,4 +263,3 @@ upb_status_t upb_parse_value(uint8_t **b, upb_field_type_t ft,
}
#undef CASE
}

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

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

@ -29,6 +29,7 @@
#ifndef PBSTRUCT_H_
#define PBSTRUCT_H_
#include "upb.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -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);
}

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

Loading…
Cancel
Save