void test_fetch_returns_given_when_not_found() {
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 0);
    tbl->store(state, cNil, Fixnum::from(47));
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 1);

    Object* out = tbl->fetch(state, cTrue, cUndef);
    TS_ASSERT_EQUALS(cUndef, out);
  }
  void test_store_fetch() {
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 0);
    tbl->store(state, cNil, Fixnum::from(47));
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 1);

    Object* out = tbl->aref(state, cNil);
    TS_ASSERT_EQUALS(as<Integer>(out)->to_native(), 47);
  }
Beispiel #3
0
  void test_fetch_returns_found() {
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 0);
    tbl->store(state, Qnil, Fixnum::from(47));
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 1);

    Object* out = tbl->fetch(state, Qnil, Qundef);
    TS_ASSERT_EQUALS(as<Integer>(out)->to_native(), 47);
  }
Beispiel #4
0
  void test_store_overwrites_previous() {
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 0);
    tbl->store(state, Qnil, Fixnum::from(47));
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 1);

    Object* out = tbl->aref(state, Qnil);
    TS_ASSERT_EQUALS(as<Integer>(out)->to_native(), 47);

    tbl->store(state, Qnil, Fixnum::from(42));
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 1);

    out = tbl->aref(state, Qnil);
    TS_ASSERT_EQUALS(as<Integer>(out)->to_native(), 42);
  }
Beispiel #5
0
  /* Look at this class and it's superclass contents (which includes
   * included modules) and calculate out how to allocate the slots.
   *
   * This locks the class so that construction is serialized.
   */
  void Class::auto_pack(STATE, GCToken gct) {
    Class* self = this;
    OnStack<1> os(state, self);

    hard_lock(state, gct);

    // If another thread did this work while we were waiting on the lock,
    // don't redo it.
    if(self->type_info_->type == PackedObject::type) {
      hard_unlock(state, gct);
      return;
    }

    size_t slots = 0;

    LookupTable* lt = LookupTable::create(state);

    // If autopacking is enabled, figure out how many slots to use.
    if(state->shared().config.gc_autopack) {
      Module* mod = self;

      int slot = 0;

      while(!mod->nil_p()) {
        Array* info = 0;

        if(Class* cls = try_as<Class>(mod)) {
          info = cls->seen_ivars();
        } else if(IncludedModule* im = try_as<IncludedModule>(mod)) {
          info = im->module()->seen_ivars();
        }

        if(info && !info->nil_p()) {
          for(size_t i = 0; i < info->size(); i++) {
            if(Symbol* sym = try_as<Symbol>(info->get(state, i))) {
              bool found = false;
              lt->fetch(state, sym, &found);

              if(!found) {
                lt->store(state, sym, Fixnum::from(slot++));
              }
            }

            // Limit the number of packed ivars to 25.
            if(slot > 25) break;
          }
        }

        mod = mod->superclass();
      }
      slots = lt->entries()->to_native();
    }

    packed_size_ = sizeof(Object) + (slots * sizeof(Object*));
    self->packed_ivar_info(state, lt);

    self->set_object_type(state, PackedObject::type);

    self->hard_unlock(state, gct);
  }
  void test_remove_works_for_chained_bins() {
    Object* k1 = Fixnum::from((4 << 5)  | 31);
    Object* k2 = Fixnum::from((10 << 5) | 31);
    Object* k3 = Fixnum::from((11 << 5) | 31);
    tbl->store(state, k1, cNil);
    tbl->store(state, k2, cTrue);
    tbl->store(state, k3, cFalse);

    TS_ASSERT_EQUALS(tbl->remove(state, k3), cFalse);
    TS_ASSERT_EQUALS(tbl->remove(state, k2), cTrue);
    TS_ASSERT_EQUALS(tbl->remove(state, k1), cNil);

    TS_ASSERT_EQUALS(0, as<Integer>(tbl->entries())->to_native());
  }
  void test_remove() {
    Object* k = Fixnum::from(47);
    tbl->store(state, k, cTrue);

    Object* out = tbl->find(state, k);
    TS_ASSERT_EQUALS(out, cTrue);

    out = tbl->remove(state, k);
    TS_ASSERT_EQUALS(out, cTrue);
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 0);

    out = tbl->fetch(state, k);
    TS_ASSERT_EQUALS(out, cNil);
  }
  void test_store_resizes_table() {
    size_t i;
    size_t bins = tbl-> bins()->to_native();

    for(i = 0; i < bins; i++) {
      tbl->store(state, Fixnum::from(i), Fixnum::from(i));
    }

    TS_ASSERT_EQUALS(i, (size_t)as<Integer>(tbl->entries())->to_native());

    TS_ASSERT((size_t)(tbl-> bins()->to_native()) > bins);

    for(i = 0; i < bins; i++) {
      TS_ASSERT_EQUALS(Fixnum::from(i), tbl->aref(state, Fixnum::from(i)));
    }
  }
Beispiel #9
0
  void LookupTable::Info::show(STATE, Object* self, int level) {
    LookupTable* tbl = as<LookupTable>(self);
    size_t size = tbl->entries()->to_native();
    Array* keys = tbl->all_keys(state);

    if(size == 0) {
      class_info(state, self, true);
      return;
    }

    class_info(state, self);
    std::cout << ": " << size << std::endl;
    indent(++level);
    for(size_t i = 0; i < size; i++) {
      std::cout << ":" << as<Symbol>(keys->get(state, i))->c_str(state);
      if(i < size - 1) std::cout << ", ";
    }
    std::cout << std::endl;
    close_body(level);
  }
  void test_store_handles_entries_in_same_bin() {
    Object* k1 = Fixnum::from((4 << 4)  | 15);
    Object* k2 = Fixnum::from((10 << 4) | 15);
    Object* k3 = Fixnum::from((11 << 4) | 15);
    Object* v1 = cTrue;
    Object* v2 = cFalse;
    Object* v3 = cTrue;

    tbl->store(state, k1, v1);
    tbl->store(state, k2, v2);
    tbl->store(state, k3, v3);
    TS_ASSERT_EQUALS(as<Integer>(tbl->entries())->to_native(), 3);

    LookupTableBucket* entry = tbl->find_entry(state, k1);
    TS_ASSERT(entry != cNil);

    TS_ASSERT(entry->next() != cNil);
    TS_ASSERT_EQUALS(entry->next()->key(), k2);

    entry = tbl->find_entry(state, k3);
    TS_ASSERT(entry != cNil);
    TS_ASSERT_EQUALS(entry->key(), k3);
  }