Example #1
0
  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;
    }
  }
Example #2
0
  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;
  }
Example #3
0
  /*
   * 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);
  }