void test_specialize_transforms_ivars_to_slots() { 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(InstructionSequence::insn_push_nil)); cm->iseq(state, iseq); VMMethod* vmm = new VMMethod(state, cm); Object::Info ti(ObjectType); ti.slots[state->symbol("@blah")->index()] = 5; ti.slot_locations.resize(6); ti.slot_locations[5] = 33; vmm->specialize(state, cm, &ti); TS_ASSERT_EQUALS(vmm->total, 3U); TS_ASSERT_EQUALS(vmm->opcodes[0], static_cast<unsigned int>(InstructionSequence::insn_push_my_offset)); TS_ASSERT_EQUALS(vmm->opcodes[1], 33U); TS_ASSERT_EQUALS(vmm->opcodes[2], static_cast<unsigned int>(InstructionSequence::insn_push_nil)); }
void test_set_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(InstructionSequence::insn_push_nil)); cm->iseq(state, iseq); VMMethod* vmm = new VMMethod(state, cm); vmm->set_breakpoint_flags(state, 0, 1 << 24); TS_ASSERT_EQUALS(vmm->opcodes[0], (1U << 24) | static_cast<unsigned int>(InstructionSequence::insn_push_ivar)); vmm->set_breakpoint_flags(state, 0, 7 << 24); TS_ASSERT_EQUALS(vmm->opcodes[0], (7U << 24) | static_cast<unsigned int>(InstructionSequence::insn_push_ivar)); vmm->set_breakpoint_flags(state, 0, 0); TS_ASSERT_EQUALS(vmm->opcodes[0], static_cast<unsigned int>(InstructionSequence::insn_push_ivar)); vmm->set_breakpoint_flags(state, 1, 1); TS_ASSERT_EQUALS(vmm->opcodes[1], 0U); }
void test_iseq() { mar->sstream.str(std::string("i\n1\n0\n")); Object* obj = mar->unmarshal(); TS_ASSERT(kind_of<InstructionSequence>(obj)); InstructionSequence* seq = as<InstructionSequence>(obj); TS_ASSERT(kind_of<Tuple>(seq->opcodes())); TS_ASSERT_EQUALS(seq->opcodes()->num_fields(), 1); TS_ASSERT_EQUALS(seq->opcodes()->at(state, 0), Fixnum::from(0)); }
void InstructionSequence::Info::show(STATE, Object* self, int level) { InstructionSequence* iseq = as<InstructionSequence>(self); class_header(state, self); indent_attribute(++level, "opcodes"); iseq->opcodes()->show(state, level); close_body(level); }
InstructionSequence* InstructionSequence::create(STATE, size_t instructions) { InstructionSequence* is = InstructionSequence::allocate(state, G(iseq)); is->opcodes(state, Tuple::create(state, instructions)); return is; }
void test_iseq() { InstructionSequence* iseq = InstructionSequence::create(state, 1); iseq->opcodes()->put(state, 0, Fixnum::from(0)); mar->marshal(iseq); TS_ASSERT_EQUALS(mar->sstream.str(), std::string("i\n1\n0\n")); }
void test_validate_ip() { 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(InstructionSequence::insn_push_nil)); cm->iseq(state, iseq); VMMethod* vmm = new VMMethod(state, cm); TS_ASSERT_EQUALS(vmm->validate_ip(state, 0), true); TS_ASSERT_EQUALS(vmm->validate_ip(state, 1), false); TS_ASSERT_EQUALS(vmm->validate_ip(state, 2), true); }
void test_validate_ip() { CompiledCode* code = CompiledCode::create(state); Tuple* tup = Tuple::from(state, 1, state->symbol("@blah")); code->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(InstructionSequence::insn_push_nil)); code->iseq(state, iseq); MachineCode* mcode = new MachineCode(state, code); TS_ASSERT_EQUALS(mcode->validate_ip(state, 0), true); TS_ASSERT_EQUALS(mcode->validate_ip(state, 1), false); TS_ASSERT_EQUALS(mcode->validate_ip(state, 2), true); }
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); }
void test_create() { CompiledMethod* cm = CompiledMethod::create(state); Tuple* tup = Tuple::from(state, 1, state->symbol("blah")); cm->literals(state, tup); InstructionSequence* iseq = InstructionSequence::create(state, 1); iseq->opcodes()->put(state, 0, Fixnum::from(0)); cm->iseq(state, iseq); VMMethod* vmm = new VMMethod(state, cm); TS_ASSERT_EQUALS(vmm->total, 1U); TS_ASSERT_EQUALS(vmm->opcodes[0], 0U); }
void test_create() { CompiledCode* code = CompiledCode::create(state); Tuple* tup = Tuple::from(state, 1, state->symbol("blah")); code->literals(state, tup); InstructionSequence* iseq = InstructionSequence::create(state, 1); iseq->opcodes()->put(state, 0, Fixnum::from(0)); code->iseq(state, iseq); MachineCode* mcode = new MachineCode(state, code); TS_ASSERT_EQUALS(mcode->total, 1U); TS_ASSERT_EQUALS(mcode->opcodes[0], 0U); }
InstructionSequence* UnMarshaller::get_iseq() { size_t count; long op; stream >> count; InstructionSequence* iseq = InstructionSequence::create(state, count); Tuple* ops = iseq->opcodes(); for(size_t i = 0; i < count; i++) { stream >> op; ops->put(state, i, Fixnum::from(op)); } iseq->post_marshal(state); return iseq; }
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; }
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; }