VM: refactor the immediate_p check out of visit_pointer()

This avoids reassigning to slots that are never changed. It makes the minor-gc pass 2% faster.
locals-and-roots
Björn Lindqvist 2016-06-07 14:42:06 +02:00
parent 33d5ecefd5
commit 6b95813dbc
1 changed files with 15 additions and 13 deletions

View File

@ -162,15 +162,14 @@ template <typename Fixup> struct slot_visitor {
template <typename Fixup> template <typename Fixup>
cell slot_visitor<Fixup>::visit_pointer(cell pointer) { cell slot_visitor<Fixup>::visit_pointer(cell pointer) {
if (immediate_p(pointer))
return pointer;
object* untagged = fixup.fixup_data(untag<object>(pointer)); object* untagged = fixup.fixup_data(untag<object>(pointer));
return RETAG(untagged, TAG(pointer)); return RETAG(untagged, TAG(pointer));
} }
template <typename Fixup> void slot_visitor<Fixup>::visit_handle(cell* handle) { template <typename Fixup> void slot_visitor<Fixup>::visit_handle(cell* handle) {
if (!immediate_p(*handle)) {
*handle = visit_pointer(*handle); *handle = visit_pointer(*handle);
}
} }
template <typename Fixup> template <typename Fixup>
@ -386,9 +385,11 @@ void slot_visitor<Fixup>::visit_embedded_literals(code_block* compiled) {
auto update_literal_refs = [&](instruction_operand op) { auto update_literal_refs = [&](instruction_operand op) {
if (op.rel.type() == RT_LITERAL) { if (op.rel.type() == RT_LITERAL) {
fixnum value = op.load_value(op.pointer); cell value = op.load_value(op.pointer);
if (!immediate_p(value)) {
op.store_value(visit_pointer(value)); op.store_value(visit_pointer(value));
} }
}
}; };
compiled->each_instruction_operand(update_literal_refs); compiled->each_instruction_operand(update_literal_refs);
} }
@ -505,28 +506,29 @@ void slot_visitor<Fixup>::visit_instruction_operands(code_block* block,
cell rel_base) { cell rel_base) {
auto visit_func = [&](instruction_operand op){ auto visit_func = [&](instruction_operand op){
cell old_offset = rel_base + op.rel.offset(); cell old_offset = rel_base + op.rel.offset();
cell value = op.load_value(old_offset); cell old_value = op.load_value(old_offset);
switch (op.rel.type()) { switch (op.rel.type()) {
case RT_LITERAL: { case RT_LITERAL: {
value = visit_pointer(value); if (!immediate_p(old_value)) {
op.store_value(visit_pointer(old_value));
}
break; break;
} }
case RT_ENTRY_POINT: case RT_ENTRY_POINT:
case RT_ENTRY_POINT_PIC: case RT_ENTRY_POINT_PIC:
case RT_ENTRY_POINT_PIC_TAIL: case RT_ENTRY_POINT_PIC_TAIL:
case RT_HERE: { case RT_HERE: {
cell offset = TAG(value); cell offset = TAG(old_value);
code_block* compiled = (code_block*)UNTAG(value); code_block* compiled = (code_block*)UNTAG(old_value);
value = RETAG(fixup.fixup_code(compiled), offset); op.store_value(RETAG(fixup.fixup_code(compiled), offset));
break; break;
} }
case RT_UNTAGGED: case RT_UNTAGGED:
break; break;
default: default:
value = parent->compute_external_address(op); op.store_value(parent->compute_external_address(op));
break; break;
} }
op.store_value(value);
}; };
block->each_instruction_operand(visit_func); block->each_instruction_operand(visit_func);
} }