void test_dup() { // Create a realistic MethodContext // Is there a better way to do this? Task* task = Task::create(state); // create a target CM CompiledMethod* target = CompiledMethod::create(state); target->iseq(state, InstructionSequence::create(state, 1)); target->iseq()->opcodes()->put(state, 0, Fixnum::from(InstructionSequence::insn_ret)); target->total_args(state, Fixnum::from(0)); target->required_args(state, target->total_args()); target->stack_size(state, Fixnum::from(10)); target->formalize(state); // create a containing CM CompiledMethod* cm = CompiledMethod::create(state); cm->iseq(state, InstructionSequence::create(state, 10)); cm->stack_size(state, Fixnum::from(10)); cm->local_count(state, Fixnum::from(0)); cm->literals(state, Tuple::create(state, 10)); Symbol* name = state->symbol("blah"); G(true_class)->method_table()->store(state, name, target); SendSite* ss = SendSite::create(state, name); cm->literals()->put(state, 0, ss); cm->formalize(state); MethodContext* ctx = MethodContext::create(state, Qnil, cm); task->make_active(ctx); task->push(Qtrue); // Dup right before we run so we can compare later MethodContext* dup = ctx->dup(state); // Compare the dup'd with the original TS_ASSERT_EQUALS(ctx->sender(), dup->sender()); TS_ASSERT_EQUALS(dup, dup->home()); TS_ASSERT_EQUALS(ctx->self(), dup->self()); TS_ASSERT_EQUALS(ctx->cm(), dup->cm()); TS_ASSERT_EQUALS(ctx->module(), dup->module()); TS_ASSERT_EQUALS(ctx->block(), dup->block()); TS_ASSERT_EQUALS(ctx->name(), dup->name()); TS_ASSERT_EQUALS(ctx->vmm, dup->vmm); TS_ASSERT_EQUALS(ctx->ip, dup->ip); TS_ASSERT_EQUALS(ctx->args, dup->args); TS_ASSERT_EQUALS(ctx->stack_size, dup->stack_size); TS_ASSERT_SAME_DATA(&ctx->js, &dup->js, sizeof(dup->js)); }
Object* CompiledMethod::default_executor(STATE, CallFrame* call_frame, Dispatch& msg, Arguments& args) { CompiledMethod* cm = as<CompiledMethod>(msg.method); cm->formalize(state, false); // Refactor cm->backend_method_->find_super_instructions(); return cm->execute(state, call_frame, msg, args); }
CompiledMethod* CompiledMethod::dup_cm(STATE) { CompiledMethod* cm = CompiledMethod::create(state); cm->copy_object(state, this); cm->set_executor(CompiledMethod::default_executor); cm->jit_data_ = NULL; cm->backend_method_ = NULL; cm->formalize(state); return cm; }
CompiledMethod* CompiledMethod::generate_tramp(STATE, size_t stack_size) { CompiledMethod* cm = CompiledMethod::create(state); cm->stack_size(state, Fixnum::from(stack_size)); cm->required_args(state, Fixnum::from(0)); cm->total_args(state, cm->required_args()); cm->name(state, state->symbol("__halt__")); cm->iseq(state, InstructionSequence::create(state, 1)); cm->iseq()->opcodes()->put(state, 0, Fixnum::from(InstructionSequence::insn_halt)); StaticScope* ss = StaticScope::create(state); ss->module(state, G(object)); cm->scope(state, ss); cm->formalize(state, false); return cm; }
ExecuteStatus CompiledMethod::default_executor(STATE, Task* task, Message& msg) { CompiledMethod* cm = as<CompiledMethod>(msg.method); cm->formalize(state, false); return cm->execute(state, task, msg); }