diff --git a/bin/benchmark-parse.rb b/bin/benchmark-parse.rb index 64d4fd530..692538f6b 100644 --- a/bin/benchmark-parse.rb +++ b/bin/benchmark-parse.rb @@ -2,13 +2,37 @@ require "benchmark/ips" require "csv" +require "optparse" + +label = nil #: String? + +OptionParser.new do |opts| + opts.banner = "Usage: benchmark-parse.rb [options] [file|directory]..." + + opts.on("--label=LABEL", "Set the benchmark label") do |v| + label = v + end +end.parse!(ARGV) + +file_names = [] files = {} ARGV.each do |file| + path = Pathname(file) + if path.directory? + Pathname.glob(path.join("**", "*.rbs")).each do |p| + file_names << p.to_s + end + else + file_names << path.to_s + end +end + +file_names.uniq.each do |file| content = File.read(file) files[file] = RBS::Buffer.new(content: content, name: Pathname(file)) end -puts "Benchmarking parsing #{files.size} files..." +puts "Benchmarking RBS(#{RBS::VERSION} in #{Bundler.default_gemfile.basename}#{label ? " (#{label})" : ""}) parsing with #{files.size} files..." result = Benchmark.ips do |x| x.report("parsing") do diff --git a/ext/rbs_extension/extconf.rb b/ext/rbs_extension/extconf.rb index eb25ec562..713cf72aa 100644 --- a/ext/rbs_extension/extconf.rb +++ b/ext/rbs_extension/extconf.rb @@ -18,7 +18,11 @@ '-Wc++-compat', ] -append_cflags ['-O0', '-pg'] if ENV['DEBUG'] +if ENV['DEBUG'] + append_cflags ['-O0', '-pg'] +else + append_cflags ['-DNDEBUG'] +end if ENV["TEST_NO_C23"] puts "Adding -Wc2x-extensions to CFLAGS" $CFLAGS << " -Werror -Wc2x-extensions" diff --git a/ext/rbs_extension/main.c b/ext/rbs_extension/main.c index 6ad694550..7f21237d2 100644 --- a/ext/rbs_extension/main.c +++ b/ext/rbs_extension/main.c @@ -16,7 +16,7 @@ * ``` * */ static NORETURN(void) raise_error(rbs_error_t *error, VALUE buffer) { - rbs_assert(error != NULL, "raise_error() called with NULL error"); + RBS_ASSERT(error != NULL, "raise_error() called with NULL error"); if (!error->syntax_error) { rb_raise(rb_eRuntimeError, "Unexpected error"); diff --git a/include/rbs/defines.h b/include/rbs/defines.h index f193ab5f4..1f24e3c67 100644 --- a/include/rbs/defines.h +++ b/include/rbs/defines.h @@ -74,4 +74,13 @@ #define NODISCARD __attribute__((warn_unused_result)) #endif +/** + * Mark a function or variable as potentially unused to suppress compiler warnings. + */ +#if defined(__GNUC__) || defined(__clang__) +#define RBS_ATTRIBUTE_UNUSED __attribute__((unused)) +#else +#define RBS_ATTRIBUTE_UNUSED +#endif + #endif diff --git a/include/rbs/util/rbs_assert.h b/include/rbs/util/rbs_assert.h index 6a6201f92..647386783 100644 --- a/include/rbs/util/rbs_assert.h +++ b/include/rbs/util/rbs_assert.h @@ -4,6 +4,17 @@ #include "rbs/defines.h" #include -void rbs_assert(bool condition, const char *fmt, ...) RBS_ATTRIBUTE_FORMAT(2, 3); +/** + * RBS_ASSERT macro that calls rbs_assert in debug builds and is removed in release builds. + * In debug mode, it forwards all arguments to the rbs_assert function. + * In release mode, it expands to nothing. + */ +#ifdef NDEBUG +#define RBS_ASSERT(condition, ...) ((void) 0) +#else +#define RBS_ASSERT(condition, ...) rbs_assert_impl(condition, __VA_ARGS__) +#endif + +void rbs_assert_impl(bool condition, const char *fmt, ...) RBS_ATTRIBUTE_FORMAT(2, 3); #endif diff --git a/include/rbs/util/rbs_encoding.h b/include/rbs/util/rbs_encoding.h index 48f89f75a..59f99c7af 100644 --- a/include/rbs/util/rbs_encoding.h +++ b/include/rbs/util/rbs_encoding.h @@ -6,6 +6,8 @@ #ifndef RBS_RBS_ENCODING_H #define RBS_RBS_ENCODING_H +#include "rbs/defines.h" + #include #include #include diff --git a/src/lexstate.c b/src/lexstate.c index d2241eb42..b6f370daa 100644 --- a/src/lexstate.c +++ b/src/lexstate.c @@ -143,7 +143,7 @@ bool rbs_next_char(rbs_lexer_t *lexer, unsigned int *codepoint, size_t *byte_len } void rbs_skip(rbs_lexer_t *lexer) { - rbs_assert(lexer->current_character_bytes > 0, "rbs_skip called with current_character_bytes == 0"); + RBS_ASSERT(lexer->current_character_bytes > 0, "rbs_skip called with current_character_bytes == 0"); if (RBS_UNLIKELY(lexer->current_code_point == '\0')) { return; diff --git a/src/location.c b/src/location.c index ad75a4ad0..c741537f1 100644 --- a/src/location.c +++ b/src/location.c @@ -6,7 +6,7 @@ #define RBS_LOC_CHILDREN_SIZE(cap) (sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * ((cap) - 1)) void rbs_loc_alloc_children(rbs_allocator_t *allocator, rbs_location_t *loc, size_t capacity) { - rbs_assert(capacity <= sizeof(rbs_loc_entry_bitmap) * 8, "Capacity %zu is too large. Max is %zu", capacity, sizeof(rbs_loc_entry_bitmap) * 8); + RBS_ASSERT(capacity <= sizeof(rbs_loc_entry_bitmap) * 8, "Capacity %zu is too large. Max is %zu", capacity, sizeof(rbs_loc_entry_bitmap) * 8); loc->children = rbs_allocator_malloc_impl(allocator, RBS_LOC_CHILDREN_SIZE(capacity), rbs_alignof(rbs_loc_children)); @@ -16,8 +16,8 @@ void rbs_loc_alloc_children(rbs_allocator_t *allocator, rbs_location_t *loc, siz } void rbs_loc_add_optional_child(rbs_location_t *loc, rbs_constant_id_t name, rbs_range_t r) { - rbs_assert(loc->children != NULL, "All children should have been pre-allocated with rbs_loc_alloc_children()"); - rbs_assert((loc->children->len + 1 <= loc->children->cap), "Not enough space was pre-allocated for the children. Children: %hu, Capacity: %hu", loc->children->len, loc->children->cap); + RBS_ASSERT(loc->children != NULL, "All children should have been pre-allocated with rbs_loc_alloc_children()"); + RBS_ASSERT((loc->children->len + 1 <= loc->children->cap), "Not enough space was pre-allocated for the children. Children: %hu, Capacity: %hu", loc->children->len, loc->children->cap); unsigned short i = loc->children->len++; loc->children->entries[i].name = name; diff --git a/src/parser.c b/src/parser.c index a68eb869d..2e83b3074 100644 --- a/src/parser.c +++ b/src/parser.c @@ -233,7 +233,7 @@ error_handling: { ids = "class/module/constant name"; } - rbs_assert(ids != NULL, "Unknown kind of type: %i", kind); + RBS_ASSERT(ids != NULL, "Unknown kind of type: %i", kind); rbs_parser_set_error(parser, parser->current_token, true, "expected one of %s", ids); return false; diff --git a/src/util/rbs_allocator.c b/src/util/rbs_allocator.c index a9ec8b7f0..f0be8097f 100644 --- a/src/util/rbs_allocator.c +++ b/src/util/rbs_allocator.c @@ -64,7 +64,7 @@ static rbs_allocator_page_t *rbs_allocator_page_new(size_t payload_size) { return page; } -rbs_allocator_t *rbs_allocator_init() { +rbs_allocator_t *rbs_allocator_init(void) { rbs_allocator_t *allocator = malloc(sizeof(rbs_allocator_t)); const size_t system_page_size = get_system_page_size(); @@ -98,7 +98,7 @@ void *rbs_allocator_realloc_impl(rbs_allocator_t *allocator, void *ptr, size_t o // Allocates `size` bytes from `allocator`, aligned to an `alignment`-byte boundary. void *rbs_allocator_malloc_impl(rbs_allocator_t *allocator, size_t size, size_t alignment) { - rbs_assert(size % alignment == 0, "size must be a multiple of the alignment. size: %zu, alignment: %zu", size, alignment); + RBS_ASSERT(size % alignment == 0, "size must be a multiple of the alignment. size: %zu, alignment: %zu", size, alignment); if (allocator->default_page_payload_size < size) { // Big allocation, give it its own page. rbs_allocator_page_t *new_page = rbs_allocator_page_new(size); diff --git a/src/util/rbs_assert.c b/src/util/rbs_assert.c index 63f17b09a..5998e99ff 100644 --- a/src/util/rbs_assert.c +++ b/src/util/rbs_assert.c @@ -5,7 +5,9 @@ #include #include -void rbs_assert(bool condition, const char *fmt, ...) { +void rbs_assert_impl(bool condition, const char *fmt, ...) { + printf("RBS_ASSERT called\n"); + if (condition) { return; } diff --git a/src/util/rbs_buffer.c b/src/util/rbs_buffer.c index 71421b975..d4eebda22 100644 --- a/src/util/rbs_buffer.c +++ b/src/util/rbs_buffer.c @@ -25,7 +25,7 @@ void rbs_buffer_append_string(rbs_allocator_t *allocator, rbs_buffer_t *buffer, if (next_length > buffer->capacity) { size_t old_capacity = buffer->capacity; - rbs_assert(old_capacity != 0, "Precondition: capacity must be at least 1. Got %zu", old_capacity); + RBS_ASSERT(old_capacity != 0, "Precondition: capacity must be at least 1. Got %zu", old_capacity); size_t new_capacity = buffer->capacity * 2; @@ -34,7 +34,7 @@ void rbs_buffer_append_string(rbs_allocator_t *allocator, rbs_buffer_t *buffer, } char *new_value = rbs_allocator_realloc(allocator, buffer->value, old_capacity, new_capacity, char); - rbs_assert(new_value != NULL, "Failed to append to buffer. Old capacity: %zu, new capacity: %zu", old_capacity, new_capacity); + RBS_ASSERT(new_value != NULL, "Failed to append to buffer. Old capacity: %zu, new capacity: %zu", old_capacity, new_capacity); buffer->value = new_value; buffer->capacity = new_capacity; diff --git a/src/util/rbs_constant_pool.c b/src/util/rbs_constant_pool.c index 27ef9cd7e..cb2b92b9a 100644 --- a/src/util/rbs_constant_pool.c +++ b/src/util/rbs_constant_pool.c @@ -37,7 +37,7 @@ next_power_of_two(uint32_t v) { return v; } -static bool is_power_of_two(uint32_t size) { +RBS_ATTRIBUTE_UNUSED static bool is_power_of_two(uint32_t size) { return (size & (size - 1)) == 0; } @@ -46,7 +46,7 @@ static bool is_power_of_two(uint32_t size) { */ static inline bool rbs_constant_pool_resize(rbs_constant_pool_t *pool) { - rbs_assert(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity); + RBS_ASSERT(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity); uint32_t next_capacity = pool->capacity * 2; if (next_capacity < pool->capacity) return false; @@ -123,7 +123,7 @@ bool rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) { */ rbs_constant_t * rbs_constant_pool_id_to_constant(const rbs_constant_pool_t *pool, rbs_constant_id_t constant_id) { - rbs_assert(constant_id != RBS_CONSTANT_ID_UNSET && constant_id <= pool->size, "constant_id is not valid. Got %i, pool->size: %i", constant_id, pool->size); + RBS_ASSERT(constant_id != RBS_CONSTANT_ID_UNSET && constant_id <= pool->size, "constant_id is not valid. Got %i, pool->size: %i", constant_id, pool->size); return &pool->constants[constant_id - 1]; } @@ -133,7 +133,7 @@ rbs_constant_pool_id_to_constant(const rbs_constant_pool_t *pool, rbs_constant_i */ rbs_constant_id_t rbs_constant_pool_find(const rbs_constant_pool_t *pool, const uint8_t *start, size_t length) { - rbs_assert(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity); + RBS_ASSERT(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity); const uint32_t mask = pool->capacity - 1; uint32_t hash = rbs_constant_pool_hash(start, length); @@ -161,7 +161,7 @@ rbs_constant_pool_insert(rbs_constant_pool_t *pool, const uint8_t *start, size_t if (!rbs_constant_pool_resize(pool)) return RBS_CONSTANT_ID_UNSET; } - rbs_assert(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity); + RBS_ASSERT(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity); const uint32_t mask = pool->capacity - 1; uint32_t hash = rbs_constant_pool_hash(start, length); @@ -202,7 +202,7 @@ rbs_constant_pool_insert(rbs_constant_pool_t *pool, const uint8_t *start, size_t // IDs are allocated starting at 1, since the value 0 denotes a non-existent // constant. uint32_t id = ++pool->size; - rbs_assert(pool->size < ((uint32_t) (1 << 30)), "pool->size is too large. Got %i", pool->size); + RBS_ASSERT(pool->size < ((uint32_t) (1 << 30)), "pool->size is too large. Got %i", pool->size); *bucket = (rbs_constant_pool_bucket_t) { .id = (unsigned int) (id & 0x3fffffff), diff --git a/src/util/rbs_encoding.c b/src/util/rbs_encoding.c index b8c5e58a5..175651993 100644 --- a/src/util/rbs_encoding.c +++ b/src/util/rbs_encoding.c @@ -3,12 +3,6 @@ #include -#if defined(__GNUC__) -#define RBS_ATTRIBUTE_UNUSED __attribute__((unused)) -#else -#define RBS_ATTRIBUTE_UNUSED -#endif - typedef uint32_t rbs_unicode_codepoint_t; #define UNICODE_ALPHA_CODEPOINTS_LENGTH 1450 @@ -5001,7 +4995,7 @@ static const uint8_t rbs_utf_8_dfa[] = { */ static rbs_unicode_codepoint_t rbs_utf_8_codepoint(const uint8_t *b, ptrdiff_t n, size_t *width) { - rbs_assert(n >= 0, "[rbs_unicode_codepoint_t] n must be greater than or equal to 0. Got %ti", n); + RBS_ASSERT(n >= 0, "[rbs_unicode_codepoint_t] n must be greater than or equal to 0. Got %ti", n); size_t maximum = (n > 4) ? 4 : ((size_t) n); uint32_t codepoint; @@ -5031,7 +5025,7 @@ rbs_utf_8_codepoint(const uint8_t *b, ptrdiff_t n, size_t *width) { */ size_t rbs_encoding_utf_8_char_width(const uint8_t *b, ptrdiff_t n) { - rbs_assert(n >= 0, "[rbs_encoding_utf_8_char_width] n must be greater than or equal to 0. Got %ti", n); + RBS_ASSERT(n >= 0, "[rbs_encoding_utf_8_char_width] n must be greater than or equal to 0. Got %ti", n); size_t maximum = (n > 4) ? 4 : ((size_t) n); uint32_t state = 0;