return frame_top + frame_size;
}
-struct stack_frame_accumulator {
- factor_vm* parent;
- growable_array frames;
-
- /* Allocates memory (frames is a growable_array, constructor allocates) */
- explicit stack_frame_accumulator(factor_vm* parent)
- : parent(parent), frames(parent) {}
-
-
- /* Allocates memory (frames.add()) */
- void operator()(cell frame_top, cell size, code_block* owner, cell addr) {
- data_root<object> executing_quot(owner->owner_quot(), parent);
- data_root<object> executing(owner->owner, parent);
- data_root<object> scan(owner->scan(parent, addr), parent);
-
- frames.add(executing.value());
- frames.add(executing_quot.value());
- frames.add(scan.value());
- }
-};
-
struct stack_frame_in_array {
cell cells[3];
};
/* Allocates memory (frames.trim()), iterate_callstack_object() */
void factor_vm::primitive_callstack_to_array() {
data_root<callstack> callstack(ctx->peek(), this);
+ /* Allocates memory here. */
+ growable_array frames(this);
- stack_frame_accumulator accum(this);
- iterate_callstack_object(callstack.untagged(), accum);
-
- /* The callstack iterator visits frames in reverse order (top to bottom) */
- std::reverse((stack_frame_in_array*)accum.frames.elements->data(),
- (stack_frame_in_array*)(accum.frames.elements->data() +
- accum.frames.count));
+ auto stack_frame_accumulator = [&](cell frame_top,
+ cell size,
+ code_block* owner,
+ cell addr) {
+ data_root<object> executing_quot(owner->owner_quot(), this);
+ data_root<object> executing(owner->owner, this);
+ data_root<object> scan(owner->scan(this, addr), this);
- accum.frames.trim();
+ frames.add(executing.value());
+ frames.add(executing_quot.value());
+ frames.add(scan.value());
+ };
+ iterate_callstack_object(callstack.untagged(), stack_frame_accumulator);
- ctx->replace(accum.frames.elements.value());
+ /* The callstack iterator visits frames in reverse order (top to bottom) */
+ std::reverse((stack_frame_in_array*)frames.elements->data(),
+ (stack_frame_in_array*)(frames.elements->data() +
+ frames.count));
+ frames.trim();
+ ctx->replace(frames.elements.value());
}
/* Some primitives implementing a limited form of callstack mutation.
: parent(parent), reset_inline_caches(reset_inline_caches) {}
void operator()(instruction_operand op) {
+ code_block* compiled = op.load_code_block();
switch (op.rel_type()) {
case RT_ENTRY_POINT: {
- code_block* compiled = op.load_code_block();
cell owner = compiled->owner;
if (to_boolean(owner))
op.store_value(parent->compute_entry_point_address(owner));
break;
}
case RT_ENTRY_POINT_PIC: {
- code_block* compiled = op.load_code_block();
if (reset_inline_caches || !compiled->pic_p()) {
cell owner = parent->code_block_owner(compiled);
if (to_boolean(owner))
break;
}
case RT_ENTRY_POINT_PIC_TAIL: {
- code_block* compiled = op.load_code_block();
if (reset_inline_caches || !compiled->pic_p()) {
cell owner = parent->code_block_owner(compiled);
if (to_boolean(owner))
return compiled;
}
-/* Find the RT_DLSYM relocation nearest to the given return address. */
-struct find_symbol_at_address_visitor {
- factor_vm* parent;
- cell return_address;
- cell symbol;
- cell library;
+/* References to undefined symbols are patched up to call this function on
+ image load. It finds the symbol and library, and throws an error. */
+void factor_vm::undefined_symbol() {
+ cell frame = ctx->callstack_top;
+ cell return_address = *(cell*)frame;
+ code_block* compiled = code->code_block_for_address(return_address);
- find_symbol_at_address_visitor(factor_vm* parent, cell return_address)
- : parent(parent),
- return_address(return_address),
- symbol(false_object),
- library(false_object) {}
+ /* Find the RT_DLSYM relocation nearest to the given return
+ address. */
+ cell symbol = false_object;
+ cell library = false_object;
- void operator()(instruction_operand op) {
+ auto find_symbol_at_address_visitor = [&](instruction_operand op) {
if (op.rel_type() == RT_DLSYM && op.pointer <= return_address) {
- code_block* compiled = op.compiled;
array* parameters = untag<array>(compiled->parameters);
cell index = op.index;
symbol = array_nth(parameters, index);
library = array_nth(parameters, index + 1);
}
- }
-};
+ };
+ compiled->each_instruction_operand(find_symbol_at_address_visitor);
-/* References to undefined symbols are patched up to call this function on
- image load. It finds the symbol and library, and throws an error. */
-void factor_vm::undefined_symbol() {
- cell frame = ctx->callstack_top;
- cell return_address = *(cell*)frame;
- code_block* compiled = code->code_block_for_address(return_address);
- find_symbol_at_address_visitor visitor(this, return_address);
- compiled->each_instruction_operand(visitor);
- if (!to_boolean(visitor.symbol))
+ if (!to_boolean(symbol))
critical_error("Can't find RT_DLSYM at return address", return_address);
else
- general_error(ERROR_UNDEFINED_SYMBOL, visitor.symbol, visitor.library);
+ general_error(ERROR_UNDEFINED_SYMBOL, symbol, library);
}
void undefined_symbol() { return current_vm()->undefined_symbol(); }
}
};
-struct object_grow_heap_updater {
- slot_visitor<code_compaction_fixup> forwarder;
-
- explicit object_grow_heap_updater(
- slot_visitor<code_compaction_fixup> forwarder)
- : forwarder(forwarder) {}
-
- void operator()(object* obj) { forwarder.visit_object_code_block(obj); }
-};
-
/* Compact just the code heap, after growing the data heap */
void factor_vm::collect_compact_code_impl() {
/* Figure out where blocks are going to go */
forwarder.visit_context_code_blocks();
/* Update code heap references in data heap */
- object_grow_heap_updater object_updater(forwarder);
- each_object(object_updater);
+ auto object_grow_heap_updater = [&](object* obj) {
+ forwarder.visit_object_code_block(obj);
+ };
+ each_object(object_grow_heap_updater);
/* Slide everything in the code heap up, and update code heap
pointers inside code blocks. */