void VM::update_profile(STATE) { timer::StopWatch<timer::nanoseconds> timer(metrics().machine.profile_ns); metrics().machine.profiles++; profile_sample_count_++; CompiledCode* code = state->vm()->call_frame()->compiled_code; code->machine_code()->sample_count++; Tuple* profile = profile_.get(); if(profile->nil_p()) { profile = Tuple::create(state, max_profile_entries_); profile_.set(profile); } ::qsort(reinterpret_cast<void*>(profile->field), profile->num_fields(), sizeof(intptr_t), profile_compare); for(native_int i = 0; i < profile->num_fields(); i++) { if(code == profile->at(i)) return; } CompiledCode* pcode = try_as<CompiledCode>(profile->at(0)); if(!pcode || (pcode && code->machine_code()->call_count > pcode->machine_code()->call_count)) { profile->put(state, 0, code); min_profile_call_count_ = code->machine_code()->call_count; } }
bool CompiledMethod::is_rescue_target(STATE, int ip) { Tuple* table = exceptions(); if(table->nil_p()) return false; for(size_t i = 0; i < table->num_fields(); i++) { Tuple* entry = as<Tuple>(table->at(state, i)); if(as<Fixnum>(entry->at(state, 2))->to_native() == ip) return true; } return false; }
/* * 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); }