From 39ce914bf9ed8d011c64365837669ad7287f6f2b Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Fri, 6 May 2022 20:00:32 -0700 Subject: [PATCH] Optimize error checks in hot functions Use `unlikely` (__builtin_expect) to help the compiler optimize error checks in some hot functions (in my testing, stack_pop_var was one of the hottest functions, right behind execute_instruction). --- src/heap.c | 24 ++++++++++++------------ src/vm.c | 6 +++--- subprojects/libsys4 | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/heap.c b/src/heap.c index f4e3668..70f541f 100644 --- a/src/heap.c +++ b/src/heap.c @@ -121,7 +121,7 @@ void heap_ref(int32_t slot) void heap_unref(int slot) { - if (heap[slot].ref <= 0) { + if (unlikely(heap[slot].ref <= 0)) { #ifdef DEBUG_HEAP VM_ERROR("double free of slot %d (%s)\nOriginally allocated at %X\nOriginally freed at %X", slot, vm_ptrtype_string(heap[slot].type), heap[slot].alloc_addr, heap[slot].free_addr); @@ -210,14 +210,14 @@ bool string_index_valid(int index) struct page *heap_get_page(int index) { - if (!page_index_valid(index)) + if (unlikely(!page_index_valid(index))) VM_ERROR("Invalid page index: %d", index); return heap[index].page; } struct string *heap_get_string(int index) { - if (!string_index_valid(index)) + if (unlikely(!string_index_valid(index))) VM_ERROR("Invalid string index: %d", index); return heap[index].s; } @@ -225,7 +225,7 @@ struct string *heap_get_string(int index) struct page *heap_get_delegate_page(int index) { struct page *page = heap_get_page(index); - if (page && page->type != DELEGATE_PAGE) + if (unlikely(page && page->type != DELEGATE_PAGE)) VM_ERROR("Not a delegate page: %d", index); return page; } @@ -233,7 +233,7 @@ struct page *heap_get_delegate_page(int index) void heap_set_page(int slot, struct page *page) { #ifdef DEBUG_HEAP - if (!page_index_valid(slot)) + if (unlikely(!page_index_valid(slot))) VM_ERROR("Invalid page index: %d", index); #endif heap[slot].page = page; @@ -242,7 +242,7 @@ void heap_set_page(int slot, struct page *page) void heap_string_assign(int slot, struct string *string) { #ifdef DEBUG_HEAP - if (!string_index_valid(slot)) + if (unlikely(!string_index_valid(slot))) VM_ERROR("Tried to assign string to non-string slot"); #endif if (heap[slot].s) { @@ -253,20 +253,20 @@ void heap_string_assign(int slot, struct string *string) void heap_struct_assign(int lval, int rval) { - if (lval == -1) + if (unlikely(lval == -1)) VM_ERROR("Assignment to null-pointer"); if (lval == rval) return; #ifdef DEBUG_HEAP - if (!page_index_valid(lval)) + if (unlikely(!page_index_valid(lval))) VM_ERROR("Invalid page index: %d", lval); - if (!page_index_valid(rval)) + if (unlikely(!page_index_valid(rval))) VM_ERROR("Invalid page index: %d", rval); - if (heap[lval].page && heap[lval].page->type != STRUCT_PAGE) + if (unlikely(heap[lval].page && heap[lval].page->type != STRUCT_PAGE)) VM_ERROR("SR_ASSIGN to non-struct page"); - if (heap[rval].page && heap[rval].page->type != STRUCT_PAGE) + if (unlikely(heap[rval].page && heap[rval].page->type != STRUCT_PAGE)) VM_ERROR("SR_ASSIGN from non-struct page"); - if (heap[lval].page && heap[rval].page && heap[lval].page->index != heap[rval].page->index) + if (unlikely(heap[lval].page && heap[rval].page && heap[lval].page->index != heap[rval].page->index)) VM_ERROR("SR_ASSIGN with different struct types"); #endif if (heap[lval].page) { diff --git a/src/vm.c b/src/vm.c index 1177db3..74f6e45 100644 --- a/src/vm.c +++ b/src/vm.c @@ -208,9 +208,9 @@ static union vm_value *stack_pop_var(void) { int32_t page_index = stack_pop().i; int32_t heap_index = stack_pop().i; - if (!heap_index_valid(heap_index)) + if (unlikely(!heap_index_valid(heap_index))) VM_ERROR("Out of bounds heap index: %d/%d", heap_index, page_index); - if (!heap[heap_index].page || page_index >= heap[heap_index].page->nr_vars) + if (unlikely(!heap[heap_index].page || page_index >= heap[heap_index].page->nr_vars)) VM_ERROR("Out of bounds page index: %d/%d", heap_index, page_index); return &heap[heap_index].page->values[page_index]; } @@ -2224,7 +2224,7 @@ static void vm_execute(void) uint16_t opcode; if (instr_ptr == VM_RETURN) return; - if (instr_ptr >= ain->code_size) { + if (unlikely(instr_ptr >= ain->code_size)) { VM_ERROR("Illegal instruction pointer: 0x%08lX", instr_ptr); } opcode = get_opcode(instr_ptr); diff --git a/subprojects/libsys4 b/subprojects/libsys4 index 1763ea7..27f3d3a 160000 --- a/subprojects/libsys4 +++ b/subprojects/libsys4 @@ -1 +1 @@ -Subproject commit 1763ea77afed7a1baa4739d6d053d9282f8b5e5b +Subproject commit 27f3d3a0024132e081b5167a321ac768cc8c48db