0
@@ -66,7 +66,6 @@ void cpu_show_lookup_time(STATE) {
0
#include "shotgun/lib/instruction_funcs.gen"
0
#define NEXT_OP printf(" => %p\n", *ip_ptr); sassert(*ip_ptr); goto **ip_ptr++
0
@@ -407,6 +406,205 @@ static inline OBJECT cpu_check_serial(STATE, cpu c, OBJECT obj, OBJECT sym, int
0
+const char *cpu_op_to_name(STATE, uint32_t op) {
0
+#include "shotgun/lib/instruction_names.h"
0
+ return get_instruction_name(op);
0
+/* Functions to translating the bytecode into a macro op series. */
0
+/* the noop instruction contains NEXT_OP(), so we used it to copy
0
+ * the code to just move to the next instruction. */
0
+void calculate_macro_size(STATE, OBJECT comp, OBJECT exc_table,
0
+ int *out, struct ins2block *tbl) {
0
+ int args, total, i, size, cur_block;
0
+ /* Pull in jump targets from the exception table */
0
+ total = NUM_FIELDS(exc_table);
0
+ for(i = 0; i < total; i++) {
0
+ ent = tuple_at(state, exc_table, i);
0
+ native_int target = N2I(tuple_at(state, ent, 2));
0
+ tbl[target].jump_target = TRUE;
0
+ bytecode = (uint32_t*)BYTES_OF(comp);
0
+ total = NUM_FIELDS(comp);
0
+ /* Step 1: find all the jump targets and mark them. */
0
+ for(i = 0; i < total; i++) {
0
+ args = _ip_size(op) - 1;
0
+ if(ins_info[op].jump) {
0
+ uint32_t target = *bytecode;
0
+ tbl[target].jump_target = TRUE;
0
+ /* Step 2: calculate the block for each op */
0
+ bytecode = (uint32_t*)BYTES_OF(comp);
0
+ for(i = 0; i < total; i++) {
0
+ args = _ip_size(op) - 1;
0
+ size += ins_info[op].size;
0
+ if(tbl[i].jump_target) {
0
+ if(i > 0 && block_size == 0) tbl[i].first = TRUE;
0
+ tbl[i].block = cur_block;
0
+ if(ins_info[op].final) {
0
+ size += ins_info[INS_NEXT].size;
0
+OBJECT create_macro(STATE, OBJECT exc_tbl, OBJECT in) {
0
+ int cur_block, total, i;
0
+ struct ins2block *tbl;
0
+ uintptr_t *macro_bc, *bc_ptr;
0
+ int target_size = BYTEARRAY_SIZE(in) * sizeof(uintptr_t);
0
+ bc = bytearray_new(state, target_size);
0
+ iseq_flip(state, in, bc);
0
+ bytecode = (uint32_t*)BYTES_OF(bc);
0
+ total = NUM_FIELDS(bc);
0
+ tbl = (struct ins2block*)calloc(NUM_FIELDS(bc), sizeof(struct ins2block));
0
+ calculate_macro_size(state, bc, exc_tbl, ¯o_size, tbl);
0
+ /* we use one chunk of memory for both the new bytecode stream and the
0
+ * code for each macro. */
0
+ macro_size += sizeof(uintptr_t) * total;
0
+ macro_bc = (uintptr_t*)malloc(macro_size);
0
+ memset(macro_bc, 0, macro_size);
0
+ macro = (void*)(macro_bc + total);
0
+ /* macro_bc is the converted instruction sequence. It's a mix of addresses and
0
+ * ints. The addresses are the start of a basic block, then ints are argumens
0
+ * to the instructions that make up the basic block. */
0
+ macro_ptr = (uint8_t*)macro;
0
+ /* Initialize the first block. */
0
+ *bc_ptr++ = (uintptr_t)macro;
0
+ printf("macro size: %d\n", macro_size);
0
+ printf("block 0: %p\n", macro_ptr);
0
+ for(i = 0; i < total; i++) {
0
+ printf("[%3d] %3d (%20s), block %d (%d)\n", i, op, cpu_op_to_name(state, op), tbl[i].block, ins_info[op].size);
0
+ /* We've hit an instruction that must be the first instruction
0
+ * in a block. We fix up the current block and start a new one. */
0
+ /* Copy NEXT_OP into the end of the current block */
0
+ memcpy(macro_ptr, ins_info[INS_NEXT].start, ins_info[INS_NEXT].size);
0
+ macro_ptr += ins_info[INS_NEXT].size;
0
+ /* Stick the block number into instruction sequence. */
0
+ *bc_ptr++ = bc_offset;
0
+ *bc_ptr++ = (uintptr_t)macro_ptr;
0
+ printf("block %d: %p\n", tbl[i].block, macro_ptr);
0
+ /* Copy the code for this operation into the macro */
0
+ memcpy(macro_ptr, ins_info[op].start, ins_info[op].size);
0
+ macro_ptr += ins_info[op].size;
0
+ /* Copy the args to this op into the instruction stream */
0
+ switch(_ip_size(op) - 1) {
0
+ printf(" arg: %d\n", *bytecode);
0
+ *bc_ptr++ = (uintptr_t)(*bytecode++);
0
+ printf(" arg: %d\n", *bytecode);
0
+ *bc_ptr++ = (uintptr_t)(*bytecode++);
0
+ OBJECT ptr = ffi_new_pointer(state, macro_bc);
0
+ ffi_autorelease(ptr, 1);
0
OBJECT cpu_compile_method(STATE, OBJECT cm) {
0
@@ -428,22 +626,14 @@ OBJECT cpu_compile_method(STATE, OBJECT cm) {
0
ba = bytearray_new(state, target_size);
0
+ ba = create_macro(state, cmethod_get_exceptions(cm), bc);
0
+ cmethod_set_compiled(cm, ba);
0
cpu_compile_instructions(state, bc, ba);
0
cmethod_set_compiled(cm, ba);
0
- /* Allocate a tuple to hold the cache entries for method calls */
0
- cs = cmethod_get_cache(cm);
0
- native_int sz = N2I(cs);
0
- cs = tuple_new(state, sz);
0
- // Reserve field 0 for call sites that are not cached
0
- fast_unsafe_set(cs, 0, Qfalse);
0
- cmethod_set_cache(cm, cs);
0
@@ -484,7 +674,8 @@ static inline OBJECT _allocate_context(STATE, cpu c, OBJECT meth, int locals) {
0
fc->sender = c->active_context;
0
- fc->data = bytearray_byte_address(state, ins);
0
+ fc->data = *DATA_STRUCT(ins, void**);
0
+ // fc->data = bytearray_byte_address(state, ins);
0
fc->literals = fast_fetch(meth, CMETHOD_f_LITERALS);
0
@@ -1022,7 +1213,7 @@ inline void cpu_perform_hook(STATE, cpu c, OBJECT recv, OBJECT meth, OBJECT arg)
0
/* Layer 4: direct activation. Used for calling a method thats already
0
-
static inline void cpu_activate_method(STATE, cpu c, struct message *msg) {
0
+
inline void cpu_activate_method(STATE, cpu c, struct message *msg) {
0
@@ -1460,27 +1651,31 @@ void cpu_yield_debugger(STATE, cpu c) {
0
-const char *cpu_op_to_name(STATE, char op) {
0
-#include "shotgun/lib/instruction_names.h"
0
- return get_instruction_name(op);
0
void state_collect(STATE, cpu c);
0
void state_major_collect(STATE, cpu c);
0
void cpu_run(STATE, cpu c, int setup) {
0
+ OBJECT _lit, t1, t2, t3, t4, t5;
0
- IP_TYPE *ip_ptr
= NULL;
0
const char *firesuit_arg;
0
+ struct rubinius_globals *global;
0
+ struct inter_proxy *proxy;
0
+ global = state->global;
0
- struct rubinius_globals *global = state->global;
0
@@ -1544,8 +1739,14 @@ insn_start:
0
rbs_symbol_to_cstring(state, cmethod_get_name(cpu_current_method(state, c))),
0
+ #define WB_FUNC proxy->write_barrier
0
#include "shotgun/lib/instruction_dt.gen"
0
+ #define WB_FUNC object_memory_write_barrier