Beispiel #1
0
  void PackedObject::Info::visit(Object* obj, ObjectVisitor& visit) {
    PackedObject* po = reinterpret_cast<PackedObject*>(obj);

    size_t fields = to_fields(object_size(obj));
    Object** body = po->body_as_array();

    for(size_t i = 0; i < fields; i++) {
      visit.call(body[i]);
    }
  }
Beispiel #2
0
  void PackedObject::Info::mark(Object* obj, ObjectMark& mark) {
    PackedObject* po = reinterpret_cast<PackedObject*>(obj);

    size_t fields = to_fields(object_size(obj));
    Object** body = po->body_as_array();

    for(size_t i = 0; i < fields; i++) {
      if(Object* tmp = mark.call(body[i])) {
        mark.set(obj, &body[i], tmp);
      }
    }
  }
Beispiel #3
0
  Object* Class::allocate(STATE) {
    if(type_info_->type == PackedObject::type) {
      assert(packed_size_ > 0);
      PackedObject* obj = reinterpret_cast<PackedObject*>(
          state->om->new_object_fast(this, packed_size_, type_info_->type));

      uintptr_t body = reinterpret_cast<uintptr_t>(obj->body_as_array());
      for(size_t i = 0; i < packed_size_ - sizeof(ObjectHeader);
          i += sizeof(Object*)) {
        Object** pos = reinterpret_cast<Object**>(body + i);
        *pos = Qundef;
      }

      return obj;
    } else {
      return state->om->new_object_fast(this,
          type_info_->instance_size, type_info_->type);
    }
  }
Beispiel #4
0
  Object* Class::allocate(STATE, CallFrame* calling_environment) {
    if(type_info_->type == PackedObject::type) {
use_packed:
      assert(packed_size_ > 0);

      // Pull the size out into a local to deal with this moving later on.
      uint32_t size = packed_size_;

      PackedObject* obj = state->local_slab().allocate(size).as<PackedObject>();

      if(likely(obj)) {
        obj->init_header(this, YoungObjectZone, PackedObject::type);
      } else {
        if(state->shared.om->refill_slab(state, state->local_slab())) {
          obj = state->local_slab().allocate(size).as<PackedObject>();

          if(likely(obj)) {
            obj->init_header(this, YoungObjectZone, PackedObject::type);
          } else {
            obj = reinterpret_cast<PackedObject*>(
                state->om->new_object_fast(state, this, size, PackedObject::type));
          }
        } else {
          state->shared.om->collect_young_now = true;

          Class* self = this;

          OnStack<1> os(state, self);

          state->collect_maybe(calling_environment);

          // Don't use 'this' after here! it's been moved! use 'self'!

          obj = state->local_slab().allocate(size).as<PackedObject>();

          if(likely(obj)) {
            obj->init_header(self, YoungObjectZone, PackedObject::type);
          } else {
            obj = reinterpret_cast<PackedObject*>(
                state->om->new_object_fast(state, self, size, PackedObject::type));
          }
        }
      }

      // Don't use 'this' !!! The above code might have GC'd

      uintptr_t body = reinterpret_cast<uintptr_t>(obj->body_as_array());
      for(size_t i = 0; i < size - sizeof(ObjectHeader);
          i += sizeof(Object*)) {
        Object** pos = reinterpret_cast<Object**>(body + i);
        *pos = Qundef;
      }

      return obj;
    } else if(!type_info_->allow_user_allocate || kind_of<SingletonClass>(this)) {
      Exception::type_error(state, "direct allocation disabled");
      return Qnil;
    } else if(type_info_->type == Object::type) {
      // transition all normal object classes to PackedObject
      auto_pack(state);
      goto use_packed;
    }

    // type_info_->type is neither PackedObject nor Object, so use the
    // generic path.
    return state->new_object_typed(this,
        type_info_->instance_size, type_info_->type);
  }