Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Working on macro threaded ops

  • Loading branch information...
commit 142b22e149f4b48bb090969e574b20809b91d3c9 1 parent 886c3fe
Evan Phoenix authored
View
16 kernel/core/iseq.rb
@@ -63,12 +63,12 @@ class InstructionSet
{:opcode => :push_ivar, :args => [:literal], :stack => [0,1]},
{:opcode => :goto_if_defined, :args => [:ip], :stack => [1,0],
:flow => :goto},
- {:opcode => :push_const, :args => [:literal], :stack => [0,1]},
+ {:opcode => :push_const, :args => [:literal], :stack => [0,1], :flow => :send},
{:opcode => :set_const, :args => [:literal], :stack => [1,1],
:vm_flags => []},
{:opcode => :set_const_at, :args => [:literal], :stack => [2,0],
:vm_flags => []},
- {:opcode => :find_const, :args => [:literal], :stack => [1,1]},
+ {:opcode => :find_const, :args => [:literal], :stack => [1,1], :flow => :send},
{:opcode => :attach_method, :args => [:literal], :stack => [2,1],
:vm_flags => [:check_interrupts]},
{:opcode => :add_method, :args => [:literal], :stack => [2,1],
@@ -288,6 +288,18 @@ def flow
@opcode_info[:flow] || :sequential
end
+ # Indicates if this instruction terminates a basic block. Used
+ # for translating the bytecode into macro ops.
+ def final?
+ [:send, :return].include? @opcode_info[:flow]
+ end
+
+ # Indicates that this is a goto, and thus the target must be
+ # the first instruction in a basic block.
+ def goto?
+ @opcode_info[:flow] == :goto
+ end
+
def to_s
@opcode_info[:opcode].to_s
end
View
4 shotgun/lib/cpu.h
@@ -159,6 +159,10 @@ int cpu_simple_return(STATE, cpu c, OBJECT val);
void cpu_save_registers(STATE, cpu c, int offset);
void cpu_yield_debugger_check(STATE, cpu c);
+void cpu_activate_method(STATE, cpu c, struct message *msg);
+OBJECT cpu_open_module(STATE, cpu c, OBJECT under, OBJECT sym);
+void cpu_send_message(STATE, cpu c, struct message *msg);
+
OBJECT cpu_const_get_in_context(STATE, cpu c, OBJECT sym);
OBJECT cpu_const_get_from(STATE, cpu c, OBJECT sym, OBJECT under);
View
247 shotgun/lib/cpu_instructions.c
@@ -66,7 +66,6 @@ void cpu_show_lookup_time(STATE) {
#if DIRECT_THREADED
#include "shotgun/lib/instruction_funcs.gen"
-DT_ADDRESSES;
#ifdef SHOW_OPS
#define NEXT_OP printf(" => %p\n", *ip_ptr); sassert(*ip_ptr); goto **ip_ptr++
@@ -407,6 +406,205 @@ static inline OBJECT cpu_check_serial(STATE, cpu c, OBJECT obj, OBJECT sym, int
return Qfalse;
}
+const char *cpu_op_to_name(STATE, uint32_t op) {
+#include "shotgun/lib/instruction_names.h"
+ return get_instruction_name(op);
+}
+
+
+/* Functions to translating the bytecode into a macro op series. */
+#if DIRECT_THREADED
+
+struct ins2block {
+ int block;
+ int jump_target;
+ int first;
+};
+
+/* the noop instruction contains NEXT_OP(), so we used it to copy
+ * the code to just move to the next instruction. */
+#define INS_NEXT 0
+
+void calculate_macro_size(STATE, OBJECT comp, OBJECT exc_table,
+ int *out, struct ins2block *tbl) {
+ OBJECT ent;
+ uint32_t *bytecode;
+ uint32_t op;
+ int args, total, i, size, cur_block;
+ int block_size;
+
+ /* Pull in jump targets from the exception table */
+ total = NUM_FIELDS(exc_table);
+ for(i = 0; i < total; i++) {
+ ent = tuple_at(state, exc_table, i);
+ native_int target = N2I(tuple_at(state, ent, 2));
+ tbl[target].jump_target = TRUE;
+ }
+
+ bytecode = (uint32_t*)BYTES_OF(comp);
+ total = NUM_FIELDS(comp);
+
+ size = 0;
+
+ /* Step 1: find all the jump targets and mark them. */
+
+ for(i = 0; i < total; i++) {
+ op = *bytecode++;
+ if(!op) continue;
+ args = _ip_size(op) - 1;
+
+ if(ins_info[op].jump) {
+ uint32_t target = *bytecode;
+ tbl[target].jump_target = TRUE;
+ }
+
+ i += args;
+ bytecode += args;
+ }
+
+ /* Step 2: calculate the block for each op */
+ bytecode = (uint32_t*)BYTES_OF(comp);
+
+ cur_block = 0;
+ block_size = 0;
+
+ for(i = 0; i < total; i++) {
+ op = *bytecode++;
+ if(!op) continue;
+ args = _ip_size(op) - 1;
+ size += ins_info[op].size;
+
+ if(tbl[i].jump_target) {
+ if(block_size > 1) {
+ cur_block++;
+ block_size = 0;
+ }
+ }
+
+ if(i > 0 && block_size == 0) tbl[i].first = TRUE;
+
+ block_size++;
+
+ tbl[i].block = cur_block;
+
+ if(ins_info[op].final) {
+ size += ins_info[INS_NEXT].size;
+ cur_block++;
+ block_size = 0;
+ }
+
+ i += args;
+ bytecode += args;
+ }
+
+ *out = size;
+}
+
+OBJECT create_macro(STATE, OBJECT exc_tbl, OBJECT in) {
+ OBJECT bc;
+ int macro_size;
+ int cur_block, total, i;
+
+ void *macro;
+ uint8_t *macro_ptr;
+ struct ins2block *tbl;
+ uint32_t *bytecode;
+ uint32_t op;
+ uintptr_t *macro_bc, *bc_ptr;
+
+ int bc_offset = 0;
+
+#if !CONFIG_BIG_ENDIAN
+ int target_size = BYTEARRAY_SIZE(in) * sizeof(uintptr_t);
+ bc = bytearray_new(state, target_size);
+ iseq_flip(state, in, bc);
+#else
+ bc = in;
+#endif
+
+ bytecode = (uint32_t*)BYTES_OF(bc);
+ total = NUM_FIELDS(bc);
+
+ tbl = (struct ins2block*)calloc(NUM_FIELDS(bc), sizeof(struct ins2block));
+
+ calculate_macro_size(state, bc, exc_tbl, &macro_size, tbl);
+
+ /* we use one chunk of memory for both the new bytecode stream and the
+ * code for each macro. */
+
+ macro_size += sizeof(uintptr_t) * total;
+
+ macro_bc = (uintptr_t*)malloc(macro_size);
+ memset(macro_bc, 0, macro_size);
+
+ macro = (void*)(macro_bc + total);
+
+ cur_block = 0;
+
+ /* macro_bc is the converted instruction sequence. It's a mix of addresses and
+ * ints. The addresses are the start of a basic block, then ints are argumens
+ * to the instructions that make up the basic block. */
+
+ bc_ptr = macro_bc;
+ macro_ptr = (uint8_t*)macro;
+
+ /* Initialize the first block. */
+ *bc_ptr++ = (uintptr_t)macro;
+ bc_offset++;
+
+ printf("macro size: %d\n", macro_size);
+ printf("block 0: %p\n", macro_ptr);
+
+ for(i = 0; i < total; i++) {
+ op = *bytecode++;
+ if(!op) continue;
+
+ printf("[%3d] %3d (%20s), block %d (%d)\n", i, op, cpu_op_to_name(state, op), tbl[i].block, ins_info[op].size);
+
+ /* We've hit an instruction that must be the first instruction
+ * in a block. We fix up the current block and start a new one. */
+ if(tbl[i].first) {
+ /* Copy NEXT_OP into the end of the current block */
+ memcpy(macro_ptr, ins_info[INS_NEXT].start, ins_info[INS_NEXT].size);
+ macro_ptr += ins_info[INS_NEXT].size;
+
+ /* Stick the block number into instruction sequence. */
+ bc_offset += 2;
+ *bc_ptr++ = bc_offset;
+ *bc_ptr++ = (uintptr_t)macro_ptr;
+
+ printf("block %d: %p\n", tbl[i].block, macro_ptr);
+ }
+
+ /* Copy the code for this operation into the macro */
+ memcpy(macro_ptr, ins_info[op].start, ins_info[op].size);
+ macro_ptr += ins_info[op].size;
+
+ /* Copy the args to this op into the instruction stream */
+
+ switch(_ip_size(op) - 1) {
+ case 2:
+ printf(" arg: %d\n", *bytecode);
+ *bc_ptr++ = (uintptr_t)(*bytecode++);
+ bc_offset++;
+ i++;
+ /* fallow through */
+ case 1:
+ printf(" arg: %d\n", *bytecode);
+ *bc_ptr++ = (uintptr_t)(*bytecode++);
+ bc_offset++;
+ i++;
+ break;
+ }
+ }
+
+ OBJECT ptr = ffi_new_pointer(state, macro_bc);
+ ffi_autorelease(ptr, 1);
+ return ptr;
+}
+
+#endif
+
OBJECT cpu_compile_method(STATE, OBJECT cm) {
OBJECT ba, bc;
int target_size;
@@ -428,22 +626,14 @@ OBJECT cpu_compile_method(STATE, OBJECT cm) {
ba = bytearray_new(state, target_size);
}
+#if DIRECT_THREADED
+ ba = create_macro(state, cmethod_get_exceptions(cm), bc);
+ cmethod_set_compiled(cm, ba);
+#else
cpu_compile_instructions(state, bc, ba);
+#endif
cmethod_set_compiled(cm, ba);
- /* Allocate a tuple to hold the cache entries for method calls */
- OBJECT cs;
- cs = cmethod_get_cache(cm);
- if(FIXNUM_P(cs)) {
- native_int sz = N2I(cs);
- if(sz > 0) {
- cs = tuple_new(state, sz);
- // Reserve field 0 for call sites that are not cached
- fast_unsafe_set(cs, 0, Qfalse);
- cmethod_set_cache(cm, cs);
- }
- }
-
return ba;
}
@@ -484,7 +674,8 @@ static inline OBJECT _allocate_context(STATE, cpu c, OBJECT meth, int locals) {
fc->sender = c->active_context;
fc->method = meth;
- fc->data = bytearray_byte_address(state, ins);
+ fc->data = *DATA_STRUCT(ins, void**);
+ // fc->data = bytearray_byte_address(state, ins);
fc->literals = fast_fetch(meth, CMETHOD_f_LITERALS);
if(locals > 0) {
@@ -1022,7 +1213,7 @@ inline void cpu_perform_hook(STATE, cpu c, OBJECT recv, OBJECT meth, OBJECT arg)
/* Layer 4: direct activation. Used for calling a method thats already
been looked up. */
-static inline void cpu_activate_method(STATE, cpu c, struct message *msg) {
+inline void cpu_activate_method(STATE, cpu c, struct message *msg) {
OBJECT ctx;
c->depth++;
@@ -1460,27 +1651,31 @@ void cpu_yield_debugger(STATE, cpu c) {
}
}
-const char *cpu_op_to_name(STATE, char op) {
-#include "shotgun/lib/instruction_names.h"
- return get_instruction_name(op);
-}
-
void state_collect(STATE, cpu c);
void state_major_collect(STATE, cpu c);
void cpu_run(STATE, cpu c, int setup) {
+ uint32_t _int;
+ native_int j, k, m;
+ OBJECT _lit, t1, t2, t3, t4, t5;
+ struct message msg;
IP_TYPE op;
- IP_TYPE *ip_ptr = NULL;
+ IP_TYPE *ip_ptr;
const char *firesuit_arg;
+ struct rubinius_globals *global;
+ struct inter_proxy *proxy;
+ ip_ptr = NULL;
+ proxy = state->proxy;
+ global = state->global;
c->ip_ptr = &ip_ptr;
- struct rubinius_globals *global = state->global;
if(setup) {
(void)op;
#if DIRECT_THREADED
SETUP_DT_ADDRESSES;
+ _populate_ins_info();
return;
#else
return;
@@ -1544,8 +1739,14 @@ void cpu_run(STATE, cpu c, int setup) {
rbs_symbol_to_cstring(state, cmethod_get_name(cpu_current_method(state, c))),
(void*)*ip_ptr);
}
+jump_next:
NEXT_OP;
+jump_next_end:
+ #undef WB_FUNC
+ #define WB_FUNC proxy->write_barrier
#include "shotgun/lib/instruction_dt.gen"
+ #undef WB_FUNC
+ #define WB_FUNC object_memory_write_barrier
#else
next_op:
View
127 shotgun/lib/instructions.rb
@@ -32,6 +32,7 @@ def generate_threaded(fd, op="op")
if code
fd.puts " insn_#{ins.bytecode}: {"
fd.puts code
+ fd.puts " insn_#{ins.bytecode}_end:"
if ins.check_interrupts?
fd.puts " goto check_interrupts;"
elsif ins.terminator?
@@ -66,14 +67,37 @@ def generate_dter
code << "}\nreturn 1;\n}\n\n"
- code << "#define DT_ADDRESSES static void* _dt_addresses[#{InstructionSet::OpCodes.size + 1}]; static int _dt_size = #{InstructionSet::OpCodes.size};\n"
+ code << "struct ins_info_t { int bytecode; uintptr_t size; void *start; int final; int jump; };\n"
+ code << "static void* _dt_addresses[#{InstructionSet::OpCodes.size + 1}];\n"
+ code << "static int _dt_size = #{InstructionSet::OpCodes.size};\n"
+ code << "static void *_dt_ends[#{InstructionSet::OpCodes.size + 1}];\n"
+ code << "static struct ins_info_t ins_info[#{InstructionSet::OpCodes.size + 1}];\n"
code << "#define SETUP_DT_ADDRESSES "
InstructionSet::OpCodes.each do |ins|
- code << "_dt_addresses[#{ins.bytecode}] = &&insn_#{ins.bytecode}; "
+ if ins.bytecode == 0
+ code << "_dt_addresses[0] = &&jump_next; "
+ code << "_dt_ends[0] = &&jump_next_end; "
+ else
+ code << "_dt_addresses[#{ins.bytecode}] = &&insn_#{ins.bytecode}; "
+ code << "_dt_ends[#{ins.bytecode}] = &&insn_#{ins.bytecode}_end; "
+ end
end
code << "\n"
+ code << "static void _populate_ins_info() {\n"
+ InstructionSet::OpCodes.each do |ins|
+ idx = ins.bytecode
+
+ code << "ins_info[#{idx}].bytecode = #{idx};\n"
+ code << "ins_info[#{idx}].size = (uintptr_t)_dt_ends[#{idx}] - (uintptr_t)_dt_addresses[#{idx}];\n"
+ code << "ins_info[#{idx}].start = _dt_addresses[#{idx}];\n"
+ code << "ins_info[#{idx}].final = #{ins.final? ? 'TRUE' : 'FALSE'};\n"
+ code << "ins_info[#{idx}].jump = #{ins.goto? ? 'TRUE' : 'FALSE'};\n"
+ end
+
+ code << "}\n"
+
code << <<-CODE
static inline uint32_t read_int_from_be(uint8_t *str) {
@@ -131,7 +155,7 @@ def generate_declarations(fd)
end
def generate_names
- str = "static const char instruction_names[] = {\n"
+ str = "#include <stdint.h>\nstatic const char instruction_names[] = {\n"
InstructionSet::OpCodes.each do |ins|
str << " \"#{ins.opcode.to_s}\\0\"\n"
end
@@ -145,14 +169,14 @@ def generate_names
end
str << "\n};\n\n"
str << <<CODE
-const char *get_instruction_name(int op) {
+const char *get_instruction_name(uint32_t op) {
return instruction_names + instruction_name_offsets[op];
}
CODE
end
def generate_names_header
- str = "const char *get_instruction_name(int op);\n"
+ str = "const char *get_instruction_name(uint32_t op);\n"
InstructionSet::OpCodes.each do |ins|
str << "#define CPU_INSTRUCTION_#{ins.opcode.to_s.upcase} #{ins.bytecode}\n"
@@ -179,7 +203,8 @@ def generate_names_header
# * pop
def noop
- ""
+ <<-CODE
+ CODE
end
# [Operation]
@@ -205,7 +230,14 @@ def noop
def push_int
<<-CODE
next_int;
- stack_push(I2N(_int));
+ /* hand inlined version of rbs_int_numeric. Don't remove this. */
+ t1 = APPLY_TAG((native_int)_int, TAG_FIXNUM);
+
+ if((native_int)STRIP_TAG(t1) != (native_int)_int) {
+ t1 = proxy->bignum_new(state, (native_int)_int);
+ }
+
+ stack_push(t1);
CODE
end
@@ -226,7 +258,7 @@ def push_int
def meta_push_neg_1
<<-CODE
- stack_push(I2N(-1));
+ stack_push(APPLY_TAG(-1, TAG_FIXNUM));
CODE
end
@@ -247,7 +279,7 @@ def meta_push_neg_1
def meta_push_0
<<-CODE
- stack_push(I2N(0));
+ stack_push(APPLY_TAG(0, TAG_FIXNUM));
CODE
end
@@ -268,7 +300,7 @@ def meta_push_0
def meta_push_1
<<-CODE
- stack_push(I2N(1));
+ stack_push(APPLY_TAG(1, TAG_FIXNUM));
CODE
end
@@ -289,7 +321,7 @@ def meta_push_1
def meta_push_2
<<-CODE
- stack_push(I2N(2));
+ stack_push(APPLY_TAG(2, TAG_FIXNUM));
CODE
end
@@ -356,7 +388,7 @@ def push_false
def push_context
<<-CODE
- methctx_reference(state, c->active_context);
+ proxy->methctx_reference(state, c->active_context);
stack_push(c->active_context);
CODE
end
@@ -379,10 +411,8 @@ def push_context
def push_literal
<<-CODE
- next_int;
- t1 = cpu_current_literals(state, c);
- t2 = fast_fetch(t1, _int);
- stack_push(t2);
+ next_literal;
+ stack_push(_lit);
CODE
end
@@ -410,7 +440,7 @@ def push_literal
def set_literal
<<-CODE
next_int;
- tuple_put(state, cpu_current_literals(state, c), _int, stack_top());
+ SET_FIELD_DIRECT(cpu_current_literals(state, c), _int, stack_top());
CODE
end
@@ -483,7 +513,7 @@ def push_local_depth
t2 = blokctx_env(state, t1);
t1 = blokenv_get_home_block(t2);
}
- stack_push(tuple_at(state, blokctx_locals(state, t1), _int));
+ stack_push(fast_fetch(blokctx_locals(state, t1), _int));
CODE
end
@@ -572,7 +602,7 @@ def push_block
def push_ivar
<<-CODE
next_literal;
- stack_push(object_get_ivar(state, c->self, _lit));
+ stack_push(proxy->get_ivar(state, c->self, _lit));
CODE
end
@@ -594,8 +624,7 @@ def push_ivar
def allocate
<<-CODE
- _lit = stack_pop();
- stack_push(NEW_OBJECT(Qnil, N2I(_lit)));
+ sassert(0);
CODE
end
@@ -747,24 +776,7 @@ def store_my_field
def send_primitive
<<-CODE
- next_int;
- j = (native_int)_int; // primitive index
- next_int;
- k = (native_int)_int; // num_args
-
- // Should the OBJECT parameter be removed since a primitive is not necesarily
- // performed on an object? Or should we state that the semantics of a primitive
- // will always have an object or else it needs to be an opcode... ?
- // If the primitive fails raise an exception
-
- msg.name = Qnil;
- msg.args = k;
- msg.method = Qnil;
- msg.module = Qnil;
- if(!cpu_perform_system_primitive(state, c, j, &msg))
- {
- cpu_raise_primitive_failure(state, c, j);
- }
+ sassert(0);
CODE
end
@@ -1568,7 +1580,7 @@ def push_cpath_top
def set_encloser
<<-CODE
t1 = stack_pop();
- cpu_set_encloser_path(state, c, t1);
+ proxy->set_encloser(state, c, t1);
CODE
end
@@ -1596,7 +1608,7 @@ def set_encloser
def push_encloser
<<-CODE
- cpu_push_encloser(state, c);
+ proxy->push_encloser(state, c);
CODE
end
@@ -1743,7 +1755,8 @@ def open_module_under
def open_module
<<-CODE
next_literal;
- stack_push(cpu_open_module(state, c, c->enclosing_class, _lit));
+ t1 = proxy->open_module(state, c, c->enclosing_class, _lit);
+ stack_push(t1);
CODE
end
@@ -1805,9 +1818,9 @@ def attach_method
next_literal;
t1 = stack_pop();
t2 = stack_pop();
- cpu_attach_method(state, c, t1, _lit, t2);
+ proxy->attach_method(state, c, t1, _lit, t2);
stack_push(t2);
- cpu_perform_hook(state, c, t1, global->sym_s_method_added, _lit);
+ proxy->perform_hook(state, c, t1, global->sym_s_method_added, _lit);
CODE
end
@@ -1839,9 +1852,9 @@ def add_method
next_literal;
t1 = stack_pop();
t2 = stack_pop();
- cpu_add_method(state, c, t1, _lit, t2);
+ proxy->add_method(state, c, t1, _lit, t2);
stack_push(t2);
- cpu_perform_hook(state, c, t1, global->sym_method_added, _lit);
+ proxy->perform_hook(state, c, t1, global->sym_method_added, _lit);
CODE
end
@@ -1891,7 +1904,7 @@ def activate_method
t3 = stack_pop(); /* locals */
msg.block = stack_pop();
- cpu_activate_method(state, c, &msg);
+ proxy->activate_method(state, c, &msg);
if(RTEST(t3)) {
if(NIL_P(cpu_current_locals(state, c)) || NUM_FIELDS(t3) >= NUM_FIELDS(cpu_current_locals(state, c))) {
cpu_set_locals(state, c, t3);
@@ -1928,10 +1941,20 @@ def activate_method
def send_method
<<-CODE
next_literal_into(msg.send_site);
- msg.recv = stack_pop();
+ t1 = msg.recv = stack_pop();
msg.block = Qnil;
msg.args = 0;
- goto perform_send;
+
+ if(REFERENCE_P(t1)) {
+ msg.klass = t1->klass;
+ } else {
+ msg.klass = proxy->object_class(state, t1);
+ }
+
+ msg.priv = c->call_flags;
+ c->call_flags = 0;
+
+ proxy->send_message(state, c, &msg);
CODE
end
@@ -2752,7 +2775,7 @@ def ret
def sret
<<-CODE
t1 = stack_pop();
- cpu_simple_return(state, c, t1);
+ proxy->simple_return(state, c, t1);
CODE
end
@@ -3085,7 +3108,7 @@ def set_args
def get_args
<<-CODE
- stack_push(I2N(c->args));
+ stack_push(APPLY_TAG(c->args, TAG_FIXNUM));
CODE
end
@@ -3697,7 +3720,6 @@ def check_serial
end
si = ShotgunInstructions.new
-si.generate_declarations(STDOUT)
si.generate_switch(STDOUT)
File.open("instruction_names.c","w") do |f|
@@ -3713,7 +3735,6 @@ def check_serial
end
File.open("instruction_dt.gen", "w") do |f|
- si.generate_declarations(f)
si.generate_threaded(f)
end
View
21 shotgun/lib/state.c
@@ -7,6 +7,8 @@
#include "shotgun/lib/cleanup_hash.h"
#include "shotgun/lib/config_hash.h"
#include "shotgun/lib/machine.h"
+#include "shotgun/lib/bignum.h"
+#include "shotgun/lib/methctx.h"
#ifdef TIME_LOOKUP
#include <mach/mach_time.h>
@@ -54,6 +56,24 @@ rstate rubinius_state_new() {
st->system_start = mach_absolute_time();
st->lookup_time = 0;
#endif
+
+ st->proxy = (struct inter_proxy*)calloc(1, sizeof(struct inter_proxy));
+ st->proxy->bignum_new = bignum_new;
+ st->proxy->methctx_reference = methctx_reference;
+ st->proxy->open_module = cpu_open_module;
+ st->proxy->attach_method = cpu_attach_method;
+ st->proxy->add_method = cpu_add_method;
+ st->proxy->perform_hook = cpu_perform_hook;
+ st->proxy->activate_method = cpu_activate_method;
+ st->proxy->object_class = object_class;
+ st->proxy->send_message = cpu_send_message;
+ st->proxy->get_ivar = object_get_ivar;
+ st->proxy->set_ivar = object_set_ivar;
+ st->proxy->write_barrier = object_memory_write_barrier;
+ st->proxy->simple_return = cpu_simple_return;
+ st->proxy->set_encloser = cpu_set_encloser_path;
+ st->proxy->push_encloser = cpu_push_encloser;
+
return st;
}
@@ -64,6 +84,7 @@ void state_destroy(STATE) {
ht_cleanup_destroy(state->cleanup);
ht_config_destroy(state->config);
+ free(state->proxy);
free(state);
}
View
51 shotgun/lib/state.h
@@ -101,6 +101,8 @@ struct type_info {
#include "shotgun/lib/object_memory.h"
#include "shotgun/lib/subtend/handle.h"
+struct inter_proxy;
+
struct rubinius_state {
object_memory om;
@@ -152,6 +154,29 @@ struct rubinius_state {
uint64_t system_start;
uint64_t lookup_time;
#endif
+
+ struct inter_proxy *proxy;
+};
+
+struct inter_proxy {
+ OBJECT (*bignum_new)(STATE, native_int);
+ void (*methctx_reference)(STATE, OBJECT);
+ OBJECT (*open_module)(STATE, cpu, OBJECT, OBJECT);
+ void (*attach_method)(STATE, cpu, OBJECT, OBJECT, OBJECT);
+ void (*add_method)(STATE, cpu, OBJECT, OBJECT, OBJECT);
+
+ void (*perform_hook)(STATE, cpu, OBJECT, OBJECT, OBJECT);
+ void (*activate_method)(STATE, cpu, struct message*);
+ OBJECT (*object_class)(STATE, OBJECT);
+ void (*send_message)(STATE, cpu, struct message*);
+ OBJECT (*get_ivar)(STATE, OBJECT, OBJECT);
+ OBJECT (*set_ivar)(STATE, OBJECT, OBJECT, OBJECT);
+ int (*send_primitive)(STATE, cpu, int, struct message*);
+
+ void (*write_barrier)(object_memory, OBJECT, OBJECT);
+ int (*simple_return)(STATE, cpu, OBJECT);
+ void (*push_encloser)(STATE, cpu);
+ void (*set_encloser)(STATE, cpu, OBJECT);
};
#ifdef TIME_LOOKUP
@@ -311,10 +336,12 @@ static inline void object_memory_write_barrier(object_memory om, OBJECT target,
#define SET_FIELD(obj, fel, val) rbs_set_field(state->om, obj, fel, val)
#define NTH_FIELD(obj, fel) rbs_get_field(obj, fel)
-#define IS_REF_P(val) REFERENCE_P(val)
-#define RUN_WB(obj, val) if(IS_REF_P(val)) object_memory_write_barrier(state->om, obj, val)
+#define WB_FUNC object_memory_write_barrier
+
+#define RUN_WB2(om, obj, val) if(REFERENCE_P(val)) WB_FUNC(om, obj, val)
+#define RUN_WB(obj, val) RUN_WB2(state->om, obj, val)
-#define rbs_set_class(om, obj, cls) ({ if(IS_REF_P(cls)) object_memory_write_barrier(om, obj, cls); obj->klass = cls; })
+#define rbs_set_class(om, obj, cls) ({ RUN_WB2(om, obj, cls); obj->klass = cls; })
#define SET_CLASS(obj, cls) ({ RUN_WB(obj, cls); obj->klass = cls; })
void machine_handle_fire(int);
@@ -330,7 +357,7 @@ void machine_handle_type_error(OBJECT, const char *message);
/* Only ever call this with constant arguments! */
#define fast_set(obj, idx, val) ({ \
- if(REFERENCE_P(val)) object_memory_write_barrier(state->om, obj, val); \
+ RUN_WB(obj, val); \
SET_FIELD_DIRECT(obj, idx, val); \
val; \
})
@@ -349,9 +376,7 @@ void machine_handle_type_error(OBJECT, const char *message);
#define rbs_set_field(om, obj, fel, val) ({ \
OBJECT _v = (val), _o = (obj); \
- if(REFERENCE_P(_v)) { \
- object_memory_write_barrier(om, _o, _v); \
- } \
+ RUN_WB2(om, _o, _v); \
SET_FIELD_DIRECT(_o, fel, _v); })
#define rbs_get_field(obj, fel) NTH_FIELD_DIRECT(obj, fel)
@@ -380,9 +405,7 @@ static void _bad_reference(OBJECT in) {
OBJECT _v = (val), _o = (obj); \
if(!REFERENCE_P(obj)) _bad_reference(obj); \
if(fel >= obj->field_count) _bad_reference2(obj, fel); \
- if(REFERENCE_P(_v)) { \
- object_memory_write_barrier(om, _o, _v); \
- } \
+ RUN_WB2(om, _o, _v); \
*(OBJECT*)ADDRESS_OF_FIELD(_o, fel) = _v; })
#define rbs_get_field(i_in, i_fel) ({ \
@@ -399,9 +422,7 @@ static void _bad_reference(OBJECT in) {
#define rbs_set_field(om, obj, fel, val) ({ \
OBJECT _v = (val), _o = (obj); \
if(fel >= obj->field_count) _bad_reference2(obj, fel); \
- if(REFERENCE_P(_v)) { \
- object_memory_write_barrier(om, _o, _v); \
- } \
+ RUN_WB2(om, _o, _v); \
*(OBJECT*)ADDRESS_OF_FIELD(_o, fel) = _v; })
#define rbs_get_field(i_in, i_fel) ({ \
@@ -476,9 +497,7 @@ static inline OBJECT rbs_set_field(object_memory om, OBJECT obj, int fel, OBJECT
OBJECT *slot = (OBJECT*)ADDRESS_OF_FIELD(obj, fel);
#if INTERNAL_DEBUG
/* Check that it's even, ie a ref, and above the special range. */
- if(IS_REF_P(val)) {
- object_memory_write_barrier(om, obj, val);
- }
+ RUN_WB2(om, obj, val);
CHECK_PTR(val);
#endif
*slot = val;
Please sign in to comment.
Something went wrong with that request. Please try again.