Factor is finally a real C++ project and has a custom assert macro. Assertion failures were still getting caught as exceptions and causing failure loops. Write our own macro that calls factor::abort on failure.
vm/words.o
MASTER_HEADERS = $(PLAF_MASTER_HEADERS) \
+ vm/assert.hpp \
vm/layouts.hpp \
vm/platform.hpp \
vm/primitives.hpp \
inline object *factor_vm::allot_object(cell type, cell size)
{
#ifdef FACTOR_DEBUG
- assert(!current_gc);
+ FACTOR_ASSERT(!current_gc);
#endif
/* If the object is smaller than the nursery, allocate it in the nursery,
inline cell array_nth(array *array, cell slot)
{
#ifdef FACTOR_DEBUG
- assert(slot < array_capacity(array));
- assert(array->type() == ARRAY_TYPE);
+ FACTOR_ASSERT(slot < array_capacity(array));
+ FACTOR_ASSERT(array->type() == ARRAY_TYPE);
#endif
return array->data()[slot];
}
inline void factor_vm::set_array_nth(array *array, cell slot, cell value)
{
#ifdef FACTOR_DEBUG
- assert(slot < array_capacity(array));
- assert(array->type() == ARRAY_TYPE);
+ FACTOR_ASSERT(slot < array_capacity(array));
+ FACTOR_ASSERT(array->type() == ARRAY_TYPE);
#endif
cell *slot_ptr = &array->data()[slot];
*slot_ptr = value;
--- /dev/null
+namespace factor
+{
+ void abort();
+}
+
+#ifndef NDEBUG
+#define FACTOR_ASSERT(condition) ((condition) \
+ ? (void)0 \
+ : ( \
+ ::fprintf(stderr, "assertion \"%s\" failed: file \"%s\", line %d\n", \
+ #condition, __FILE__, __LINE__), \
+ ::factor::abort() \
+ ))
+#else
+#define FACTOR_ASSERT(condition) ((void)0)
+#endif
{
#ifdef FACTOR_DEBUG
check_code_pointer((cell)frame->entry_point);
- assert(frame->size != 0);
+ FACTOR_ASSERT(frame->size != 0);
#endif
}
tagged<quotation> quot(owner.as<quotation>());
tagged<array> elements(quot->array);
#ifdef FACTOR_DEBUG
- assert(array_capacity(elements.untagged()) == 5);
- assert(array_nth(elements.untagged(),4) == special_objects[PIC_MISS_WORD]
+ FACTOR_ASSERT(array_capacity(elements.untagged()) == 5);
+ FACTOR_ASSERT(array_nth(elements.untagged(),4) == special_objects[PIC_MISS_WORD]
|| array_nth(elements.untagged(),4) == special_objects[PIC_MISS_TAIL_WORD]);
#endif
tagged<wrapper> word_wrapper(array_nth(elements.untagged(),0));
{
cell size = header & ~7;
#ifdef FACTOR_DEBUG
- assert(size > 0);
+ FACTOR_ASSERT(size > 0);
#endif
return size;
}
VM_C_API void undefined_symbol(void);
inline code_block *word::code() const {
- assert(entry_point != NULL);
+ FACTOR_ASSERT(entry_point != NULL);
return (code_block*)entry_point - 1;
}
inline code_block *quotation::code() const {
- assert(entry_point != NULL);
+ FACTOR_ASSERT(entry_point != NULL);
return (code_block*)entry_point - 1;
}
void code_heap::free(code_block *compiled)
{
- assert(!uninitialized_p(compiled));
+ FACTOR_ASSERT(!uninitialized_p(compiled));
points_to_nursery.erase(compiled);
points_to_aging.erase(compiled);
all_blocks.erase(compiled);
{
std::set<code_block*>::const_iterator blocki =
all_blocks.upper_bound((code_block*)address);
- assert(blocki != all_blocks.begin());
+ FACTOR_ASSERT(blocki != all_blocks.begin());
--blocki;
code_block* found_block = *blocki;
- assert((cell)found_block->entry_point() <= address
+ FACTOR_ASSERT((cell)found_block->entry_point() <= address
&& address - (cell)found_block->entry_point() < found_block->size());
return found_block;
}
if it were a fixnum, and have library code shift it to the
left by 4. */
cell entry_point = (cell)compiled->entry_point();
- assert((entry_point & (data_alignment - 1)) == 0);
- assert((entry_point & TAG_MASK) == FIXNUM_TYPE);
+ FACTOR_ASSERT((entry_point & (data_alignment - 1)) == 0);
+ FACTOR_ASSERT((entry_point & TAG_MASK) == FIXNUM_TYPE);
objects.push_back(entry_point);
}
};
~code_root()
{
#ifdef FACTOR_DEBUG
- assert(parent->code_roots.back() == this);
+ FACTOR_ASSERT(parent->code_roots.back() == this);
#endif
parent->code_roots.pop_back();
}
void factor_vm::delete_contexts()
{
- assert(!ctx);
+ FACTOR_ASSERT(!ctx);
std::list<context *>::const_iterator iter = unused_contexts.begin();
std::list<context *>::const_iterator end = unused_contexts.end();
while(iter != end)
{
u32 insn = *(u32 *)return_address;
/* Check that absolute bit is 0 */
- assert((insn & 0x2) == 0x0);
+ FACTOR_ASSERT((insn & 0x2) == 0x0);
/* Check that instruction is branch */
- assert((insn >> 26) == 0x12);
+ FACTOR_ASSERT((insn >> 26) == 0x12);
}
static const u32 b_mask = 0x3fffffc;
{
// Make a fake frame for the leaf procedure
code_block *leaf_block = code->code_block_for_address(*pc);
- assert(leaf_block != NULL);
+ FACTOR_ASSERT(leaf_block != NULL);
cell newsp = *sp - 4*sizeof(cell);
*(cell*)(newsp + 3*sizeof(cell)) = 4*sizeof(cell);
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
}
else
- assert(false);
+ FACTOR_ASSERT(false);
*pc = (cell)handler_word->entry_point;
}
-#include <assert.h>
-
namespace factor
{
inline static void check_call_site(cell return_address)
{
unsigned char opcode = call_site_opcode(return_address);
- assert(opcode == call_opcode || opcode == jmp_opcode);
+ FACTOR_ASSERT(opcode == call_opcode || opcode == jmp_opcode);
}
inline static void *get_call_target(cell return_address)
nursery = new nursery_space(young_size,aging_semispace->end);
- assert(seg->end - nursery->end <= deck_size);
+ FACTOR_ASSERT(seg->end - nursery->end <= deck_size);
}
data_heap::~data_heap()
~gc_bignum()
{
#ifdef FACTOR_DEBUG
- assert(parent->bignum_roots.back() == (cell)addr);
+ FACTOR_ASSERT(parent->bignum_roots.back() == (cell)addr);
#endif
parent->bignum_roots.pop_back();
}
{
exit_fep(this);
general_error(ERROR_INTERRUPT,false_object,false_object);
- assert(false);
+ FACTOR_ASSERT(false);
}
else if(strcmp(cmd,"data") == 0)
dump_objects(TYPE_COUNT);
{
cell size = header & ~7;
#ifdef FACTOR_DEBUG
- assert(size > 0);
+ FACTOR_ASSERT(size > 0);
#endif
return size;
}
void make_free(cell size)
{
#ifdef FACTOR_DEBUG
- assert(size > 0);
+ FACTOR_ASSERT(size > 0);
#endif
header = size | 1;
}
{
/* find size */
cell size = state.unmarked_block_size(start);
- assert(size > 0);
+ FACTOR_ASSERT(size > 0);
free_heap_block *free_block = (free_heap_block *)start;
free_block->make_free(size);
void factor_vm::gc(gc_op op, cell requested_size, bool trace_contexts_p)
{
- assert(!gc_off);
- assert(!current_gc);
+ FACTOR_ASSERT(!gc_off);
+ FACTOR_ASSERT(!current_gc);
/* Important invariant: tenured space must have enough contiguous free
space to fit the entire contents of the aging space and nursery. This is
because when doing a full collection, objects from younger generations
are promoted before any unreachable tenured objects are freed. */
- assert(!data->high_fragmentation_p());
+ FACTOR_ASSERT(!data->high_fragmentation_p());
current_gc = new gc_state(op,this);
atomic::store(¤t_gc_p, true);
current_gc = NULL;
/* Check the invariant again, just in case. */
- assert(!data->high_fragmentation_p());
+ FACTOR_ASSERT(!data->high_fragmentation_p());
}
/* primitive_minor_gc() is invoked by inline GC checks, and it needs to fill in
code_block *compiled = parent->frame_code(frame);
gc_info *info = compiled->block_gc_info();
- assert(return_address < compiled->size());
+ FACTOR_ASSERT(return_address < compiled->size());
cell index = info->return_address_index(return_address);
if(index != (cell)-1)
ctx->scrub_stacks(info,index);
template<typename Array> cell array_capacity(const Array *array)
{
#ifdef FACTOR_DEBUG
- assert(array->type() == Array::type_number);
+ FACTOR_ASSERT(array->type() == Array::type_number);
#endif
return array->capacity >> TAG_BITS;
}
parent(vm)
{
fixnum old_count = atomic::fetch_add(&parent->current_jit_count, 1);
- assert(old_count >= 0);
+ FACTOR_ASSERT(old_count >= 0);
}
jit::~jit()
{
fixnum old_count = atomic::fetch_subtract(&parent->current_jit_count, 1);
- assert(old_count >= 1);
+ FACTOR_ASSERT(old_count >= 1);
}
void jit::emit_relocation(cell relocation_template_)
case DLL_TYPE:
return "dll";
default:
- assert(false);
+ FACTOR_ASSERT(false);
return "";
}
}
inline static fixnum untag_fixnum(cell tagged)
{
#ifdef FACTOR_DEBUG
- assert(TAG(tagged) == FIXNUM_TYPE);
+ FACTOR_ASSERT(TAG(tagged) == FIXNUM_TYPE);
#endif
return ((fixnum)tagged) >> TAG_BITS;
}
handler = (cell)factor::synchronous_signal_handler_impl;
}
- assert(handler != 0);
+ FACTOR_ASSERT(handler != 0);
dispatch_signal_handler(
(cell*)&MACH_STACK_POINTER(thread_state),
{
/* Look up the VM instance involved */
THREADHANDLE thread_id = pthread_from_mach_thread_np(thread);
- assert(thread_id);
+ FACTOR_ASSERT(thread_id);
std::map<THREADHANDLE, factor_vm*>::const_iterator vm = thread_vms.find(thread_id);
/* Handle the exception */
abort ();
}
}
+ return NULL; // quiet warning
}
/* Initialize the Mach exception handler thread. */
else
{
#ifdef FACTOR_DEBUG
- assert(start.first < bits_size);
+ FACTOR_ASSERT(start.first < bits_size);
#endif
bits[start.first] |= ~start_mask;
if(end_mask != 0)
{
#ifdef FACTOR_DEBUG
- assert(end.first < bits_size);
+ FACTOR_ASSERT(end.first < bits_size);
#endif
bits[end.first] |= end_mask;
}
Block *forward_block(const Block *original)
{
#ifdef FACTOR_DEBUG
- assert(marked_p(original));
+ FACTOR_ASSERT(marked_p(original));
#endif
std::pair<cell,cell> position = bitmap_deref(original);
cell new_line_number = approx_popcount + popcount(marked[position.first] & mask);
Block *new_block = line_block(new_line_number);
#ifdef FACTOR_DEBUG
- assert(new_block <= original);
+ FACTOR_ASSERT(new_block <= original);
#endif
return new_block;
}
#include <errno.h>
#endif
-#ifdef FACTOR_DEBUG
-#include <assert.h>
-#endif
-
/* C headers */
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
-#include <assert.h>
/* C++ headers */
#include <algorithm>
}
/* Factor headers */
+#include "assert.hpp"
#include "layouts.hpp"
#include "platform.hpp"
#include "primitives.hpp"
void register_vm_with_thread(factor_vm *vm)
{
- assert(!global_vm);
+ FACTOR_ASSERT(!global_vm);
global_vm = vm;
}
inline factor_vm *current_vm()
{
factor_vm *vm = current_vm_p();
- assert(vm != NULL);
+ FACTOR_ASSERT(vm != NULL);
return vm;
}
{
#ifdef FACTOR_DEBUG
/* First card should start with an object */
- assert(card_index > 0);
+ FACTOR_ASSERT(card_index > 0);
#endif
card_index--;
}
void factor_vm::open_console()
{
- assert(!stdin_thread_initialized_p);
+ FACTOR_ASSERT(!stdin_thread_initialized_p);
safe_pipe(&control_read,&control_write);
safe_pipe(&size_read,&size_write);
safe_pipe(&stdin_read,&stdin_write);
void factor_vm::lock_console()
{
- assert(stdin_thread_initialized_p);
+ FACTOR_ASSERT(stdin_thread_initialized_p);
/* Lock the stdin_mutex and send the stdin_loop thread a signal to interrupt
any read() it has in progress. When the stdin loop iterates again, it will
try to lock the same mutex and wait until unlock_console() is called. */
void factor_vm::unlock_console()
{
- assert(stdin_thread_initialized_p);
+ FACTOR_ASSERT(stdin_thread_initialized_p);
pthread_mutex_unlock(&stdin_mutex);
}
sigaction_safe(SIGINT,&fep_sigaction,NULL);
}
-void factor_vm::abort()
+void abort()
{
sig_t ret;
do
}
while(ret == SIG_ERR && errno == EINTR);
- close_console();
+ factor_vm::close_console();
::abort();
}
Since in practice nobody uses the multi-VM stuff yet, we just grab the first
VM we can get. This will not be a good idea when we actually support native
threads. */
- assert(thread_vms.size() == 1);
+ FACTOR_ASSERT(thread_vms.size() == 1);
factor_vm *vm = thread_vms.begin()->second;
vm->safepoint.enqueue_fep(vm);
return TRUE;
DWORD ok;
ok = QueryPerformanceFrequency(&units_per_second);
- assert(ok);
+ FACTOR_ASSERT(ok);
ok = QueryPerformanceCounter(&counter);
- assert(ok);
+ FACTOR_ASSERT(ok);
counter.QuadPart *= samples_per_second;
while (atomic::load(&sampling_profiler_p))
{
SwitchToThread();
ok = QueryPerformanceCounter(&new_counter);
- assert(ok);
+ FACTOR_ASSERT(ok);
new_counter.QuadPart *= samples_per_second;
cell samples = 0;
while (new_counter.QuadPart - counter.QuadPart > units_per_second.QuadPart)
if (samples > 0)
{
DWORD suscount = SuspendThread(thread);
- assert(suscount == 0);
+ FACTOR_ASSERT(suscount == 0);
CONTEXT context;
memset((void*)&context, 0, sizeof(CONTEXT));
context.ContextFlags = CONTEXT_CONTROL;
BOOL context_ok = GetThreadContext(thread, &context);
- assert(context_ok);
+ FACTOR_ASSERT(context_ok);
suscount = ResumeThread(thread);
- assert(suscount == 1);
+ FACTOR_ASSERT(suscount == 1);
safepoint.enqueue_samples(this, samples, context.EIP, false);
}
sampler_thread = NULL;
}
-void factor_vm::abort()
+void abort()
{
::abort();
}
FALSE,
id
);
- assert(threadHandle != NULL);
+ FACTOR_ASSERT(threadHandle != NULL);
return threadHandle;
}
{
data_root<quotation> quot(quot_,this);
- assert(!quot_compiled_p(quot.untagged()));
+ FACTOR_ASSERT(!quot_compiled_p(quot.untagged()));
code_block *compiled = jit_compile_quot(quot.value(),quot.value(),true);
quot.untagged()->entry_point = compiled->entry_point();
exit((int)to_fixnum(ctx->pop()));
}
-void factor_vm::exit(int status)
+void exit(int status)
{
- close_console();
+ factor_vm::close_console();
::exit(status);
}
namespace factor
{
+void abort();
+void exit(int status);
+
}
}
else if (atomic::load(&parent->sampling_profiler_p))
{
- assert(parent->code->seg->in_segment_p(pc));
+ FACTOR_ASSERT(parent->code->seg->in_segment_p(pc));
code_block *block = parent->code->code_block_for_address(pc);
bool prolog_p = (cell)block->entry_point() == pc;
stack_frame *frame = ctx->bottom_frame();
if (prolog_p)
{
- assert(frame >= ctx->callstack_top);
+ FACTOR_ASSERT(frame >= ctx->callstack_top);
stack_frame *next_frame = frame_successor(frame);
while (next_frame >= ctx->callstack_top)
{
code_block *compiled = visitor->fixup.translate_code(parent->frame_code(frame));
gc_info *info = compiled->block_gc_info();
- assert(return_address < compiled->size());
+ FACTOR_ASSERT(return_address < compiled->size());
cell callsite = info->return_address_index(return_address);
if(callsite == (cell)-1)
return;
cell value() const
{
#ifdef FACTOR_DEBUG
- assert(type_p());
+ FACTOR_ASSERT(type_p());
#endif
return value_;
}
Type *untagged() const
{
#ifdef FACTOR_DEBUG
- assert(type_p());
+ FACTOR_ASSERT(type_p());
#endif
return (Type *)(UNTAG(value_));
}
void primitive_nano_count();
void primitive_sleep();
void primitive_set_slot();
- static void exit(int status);
// objects
void primitive_special_object();
{
#ifdef FACTOR_DEBUG
if(!(current_gc && current_gc->op == collect_growing_heap_op))
- assert(data->seg->in_segment_p((cell)pointer));
+ FACTOR_ASSERT(data->seg->in_segment_p((cell)pointer));
#endif
}
static void unlock_console();
static void ignore_ctrl_c();
static void handle_ctrl_c();
- static void abort();
- static void exit();
// os-windows
#if defined(WINDOWS)