void test_get_breakpoint_flags() {
    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(4 << 24 | InstructionSequence::insn_push_nil));

    cm->iseq(state, iseq);

    VMMethod* vmm = new VMMethod(state, cm);

    TS_ASSERT_EQUALS(vmm->get_breakpoint_flags(state, 0), 0U);
    TS_ASSERT_EQUALS(vmm->get_breakpoint_flags(state, 2), (4U << 24));
    TS_ASSERT_EQUALS(vmm->get_breakpoint_flags(state, 1), 0U);
  }
Exemple #2
0
  InstructionSequence* UnMarshaller::get_iseq() {
    size_t count;
    char data[OPCODE_LENGTH];
    stream >> count;

    // Read off newline
    stream.get();

    InstructionSequence* iseq = InstructionSequence::create(state, count);
    Tuple* ops = iseq->opcodes();

    for(size_t i = 0; i < count; i++) {
      stream.getline(data, OPCODE_LENGTH);
      long op = strtol(data, NULL, 10);
      ops->put(state, i, Fixnum::from(op));
    }

    iseq->post_marshal(state);

    return iseq;
  }
Exemple #3
0
 InstructionSequence* InstructionSequence::create(STATE, size_t instructions) {
   InstructionSequence* is = state->new_object<InstructionSequence>(G(iseq));
   is->opcodes(state, Tuple::create(state, instructions));
   return is;
 }
  bool BytecodeVerification::verify(STATE) {
    // Do this setup here instead of the constructor so we can do
    // some validation of the CompiledCode's fields we read them.

    // Double check the method itself, since it might be a nil
    if(!kind_of<CompiledCode>(method_)) {
      fail("invalid method", -1);
      return false;
    }

    if(Fixnum* fix = try_as<Fixnum>(method_->local_count())) {
      locals_ = fix->to_native();
    } else {
      fail("method not initialized properly", -1);
      return false;
    }

    InstructionSequence* iseq = try_as<InstructionSequence>(method_->iseq());
    if(!iseq) {
      fail("method not initialized properly", -1);
      return false;
    }

    if(Tuple* tup = try_as<Tuple>(iseq->opcodes())) {
      ops_ = tup;
    } else {
      fail("method not initialized properly", -1);
      return false;
    }

    if(Fixnum* fix = try_as<Fixnum>(method_->stack_size())) {
      max_stack_allowed_ = fix->to_native();
    } else {
      fail("method not initialized properly", -1);
      return false;
    }

    if(Fixnum* fix = try_as<Fixnum>(method_->splat())) {
      if(fix->to_native() >= locals_) {
        fail("invalid splat position", -1);
        return false;
      }
    }

    Fixnum* tot = try_as<Fixnum>(method_->total_args());
    Fixnum* req = try_as<Fixnum>(method_->required_args());
    Fixnum* post = try_as<Fixnum>(method_->post_args());

    if(!tot || !req || !post) {
      fail("method not initialized properly (missing arg counts)", -1);
      return false;
    }

    if(tot->to_native() > locals_) {
      fail("more arguments than local slots", -1);
      return false;
    }

    if(req->to_native() > tot->to_native()) {
      fail("more required arguments than total", -1);
      return false;
    }

    if(post->to_native() > req->to_native()) {
      fail("more post arguments than required", -1);
      return false;
    }

    if(post->to_native() > tot->to_native()) {
      fail("more post arguments than total", -1);
      return false;
    }

    total_ = ops_->num_fields();
    stack_ = new int32_t[total_];

    for(native_int i = 0; i < total_; i++) {
      stack_[i] = -1;
    }

    std::list<Section> ips;
    ips.push_back(Section(0, 0));

    while(!ips.empty()) {
      Section& section = ips.front();

      int ip = section.ip;
      int sp = section.sp;

      ips.pop_front();

      if(!verify_from(state, sp, ip, ips)) return false;
    }

    // Now, check there is a enough space for the stack locals.
    if(max_stack_seen_ + max_stack_local_ >= max_stack_allowed_) {
      fail("not enough space for stack locals", -1);
      return false;
    }

    return true;
  }