BlockEnvironment* BlockEnvironment::under_call_frame(STATE, CompiledMethod* cm, VMMethod* caller, CallFrame* call_frame, size_t index) { BlockEnvironment* be = state->new_object<BlockEnvironment>(G(blokenv)); VMMethod* vmm = caller->blocks.at(index); if(!vmm) { vmm = cm->formalize(state); if(caller->type) { vmm->specialize(state, caller->type); } caller->blocks[index] = vmm; vmm->set_parent(caller); } be->scope(state, call_frame->promote_scope(state)); be->top_scope(state, call_frame->top_scope(state)); be->method(state, cm); be->module(state, call_frame->module()); be->local_count(state, cm->local_count()); be->vmm = vmm; BlockExecutor native = reinterpret_cast<BlockExecutor>(vmm->native_function); if(native) { be->execute = native; } else { be->execute = &BlockEnvironment::execute_interpreter; } return be; }
void test_specialize_transforms_ivars_to_slots() { CompiledMethod* cm = CompiledMethod::create(state); Tuple* tup = Tuple::from(state, 1, state->symbol("@blah")); cm->literals(state, tup); InstructionSequence* iseq = InstructionSequence::create(state, 3); iseq->opcodes()->put(state, 0, Fixnum::from(InstructionSequence::insn_push_ivar)); iseq->opcodes()->put(state, 1, Fixnum::from(0)); iseq->opcodes()->put(state, 2, Fixnum::from(InstructionSequence::insn_push_nil)); cm->iseq(state, iseq); VMMethod* vmm = new VMMethod(state, cm); Object::Info ti(ObjectType); ti.slots[state->symbol("@blah")->index()] = 5; ti.slot_locations.resize(6); ti.slot_locations[5] = 33; vmm->specialize(state, cm, &ti); TS_ASSERT_EQUALS(vmm->total, 3U); TS_ASSERT_EQUALS(vmm->opcodes[0], static_cast<unsigned int>(InstructionSequence::insn_push_my_offset)); TS_ASSERT_EQUALS(vmm->opcodes[1], 33U); TS_ASSERT_EQUALS(vmm->opcodes[2], static_cast<unsigned int>(InstructionSequence::insn_push_nil)); }
BlockEnvironment* BlockEnvironment::under_context(STATE, CompiledMethod* cm, MethodContext* parent, MethodContext* active, size_t index) { BlockEnvironment* be = (BlockEnvironment*)state->new_object(G(blokenv)); VMMethod* vmm; if((vmm = active->vmm->blocks[index]) == NULL) { vmm = new VMMethod(state, cm); if(active->vmm->type) { vmm->specialize(state, active->vmm->type); } active->vmm->blocks[index] = vmm; } be->home(state, parent); be->home_block(state, active); be->method(state, cm); be->local_count(state, cm->local_count()); be->vmm = vmm; return be; }