/* * Turns a CompiledMethod's InstructionSequence into a C array of opcodes. */ VMMethod::VMMethod(STATE, CompiledMethod* meth) : parent_(NULL) , run(standard_interpreter) , type(NULL) , number_of_caches_(0) , caches(0) #ifdef ENABLE_LLVM , llvm_function_(NULL) , jitted_impl_(NULL) #endif , name_(meth->name()) { meth->set_executor(&VMMethod::execute); total = meth->iseq()->opcodes()->num_fields(); opcodes = new opcode[total]; addresses = new void*[total]; fill_opcodes(state, meth); stack_size = meth->stack_size()->to_native(); number_of_locals = meth->number_of_locals(); total_args = meth->total_args()->to_native(); required_args = meth->required_args()->to_native(); if(meth->splat()->nil_p()) { splat_position = -1; } else { splat_position = as<Integer>(meth->splat())->to_native(); } setup_argument_handler(meth); // Disable JIT for large methods if(meth->primitive()->nil_p() && !state->shared.config.jit_disabled && total < (size_t)state->shared.config.jit_max_method_size) { call_count = 0; } else { call_count = -1; } state->shared.om->add_code_resource(this); }
void VMMethod::deoptimize(STATE, CompiledMethod* original) { #ifdef ENABLE_LLVM // This resets execute to use the interpreter setup_argument_handler(original); // Don't call LLVMState::get(state)->remove(llvm_function_) // here. We let the CodeManager do that later, when we're sure // the llvm function is no longer used. llvm_function_ = 0; // Remove any JIT data, which will be cleanup by the CodeManager // later. original->set_jit_data(0); // Don't reset call_count if it's -1 // (why would it be -1, it shouldn't be if we got this far) if(call_count >= 0) call_count = 0; #endif }
/* * Turns a CompiledMethod's InstructionSequence into a C array of opcodes. */ VMMethod::VMMethod(STATE, CompiledMethod* meth) : original(state, meth), type(NULL) { meth->set_executor(VMMethod::execute); total = meth->iseq()->opcodes()->num_fields(); if(Tuple* tup = try_as<Tuple>(meth->literals())) { blocks.resize(tup->num_fields(), NULL); } opcodes = new opcode[total]; Tuple* literals = meth->literals(); if(literals->nil_p()) { sendsites = NULL; } else { sendsites = new TypedRoot<SendSite*>[literals->num_fields()]; } Tuple* ops = meth->iseq()->opcodes(); Object* val; for(size_t index = 0; index < total;) { val = ops->at(state, index); if(val->nil_p()) { opcodes[index++] = 0; } else { opcodes[index] = as<Fixnum>(val)->to_native(); size_t width = InstructionSequence::instruction_width(opcodes[index]); switch(width) { case 2: opcodes[index + 1] = as<Fixnum>(ops->at(state, index + 1))->to_native(); break; case 3: opcodes[index + 1] = as<Fixnum>(ops->at(state, index + 1))->to_native(); opcodes[index + 2] = as<Fixnum>(ops->at(state, index + 2))->to_native(); break; } switch(opcodes[index]) { case InstructionSequence::insn_send_method: case InstructionSequence::insn_send_stack: case InstructionSequence::insn_send_stack_with_block: case InstructionSequence::insn_send_stack_with_splat: case InstructionSequence::insn_send_super_stack_with_block: case InstructionSequence::insn_send_super_stack_with_splat: native_int which = opcodes[index + 1]; sendsites[which].set(as<SendSite>(literals->at(state, which)), &state->globals.roots); } index += width; } } stack_size = meth->stack_size()->to_native(); number_of_locals = meth->number_of_locals(); total_args = meth->total_args()->to_native(); required_args = meth->required_args()->to_native(); if(meth->splat()->nil_p()) { splat_position = -1; } else { splat_position = as<Integer>(meth->splat())->to_native(); } setup_argument_handler(meth); }