예제 #1
0
  Data* Data::create(STATE, void* data_ptr, Data::MarkFunctor mark, Data::FreeFunctor free) {
    Data* data;

    data = state->new_object<Data>(G(data));

    // Data is just a heap alias for the handle, so go ahead and create
    // the handle and populate it as an RData now.
    InflatedHeader* ih = state->om->inflate_header(data);
    capi::Handle* handle = ih->handle();

    assert(!handle && "can't already have a handle, it's brand new!");

    handle = new capi::Handle(state, data);
    ih->set_handle(handle);

    // Don't call ->ref() on handle! We don't want the handle to keep the object
    // alive by default. The handle needs to have the lifetime of the object.

    state->shared.global_handles()->add(handle);

    RDataShadow* rdata = reinterpret_cast<RDataShadow*>(handle->as_rdata(0));

    rdata->data = data_ptr;
    rdata->dmark = mark;
    rdata->dfree = free;

    // If this Data requires a free function, register this object
    // as needing finalization.
    if(free) {
      state->om->needs_finalization(data, (FinalizerFunction)&Data::finalize);
    }

    return data;
  }
예제 #2
0
  VALUE NativeMethodFrame::get_handle(STATE, Object* obj) {
    InflatedHeader* ih = state->om->inflate_header(obj);

    capi::Handle* handle = ih->handle();

    if(handle) {
      // ref() ONLY if it's not already in there!
      // otherwise the refcount is wrong and we leak handles.
      capi::HandleSet::iterator pos = handles_.find(handle);
      if(pos == handles_.end()) {
        // We're seeing this object for the first time in this function.
        // Be sure that it's updated.
        handle->ref();
        handles_.insert(handle);
        handle->update(NativeMethodEnvironment::get());
      }
    } else {
      handle = new capi::Handle(state, obj);
      ih->set_handle(handle);

      state->shared.global_handles()->add(handle);

      handle->ref();
      handles_.insert(handle);
    }

    return handle->as_value();
  }
예제 #3
0
  VALUE NativeMethodFrame::get_handle(STATE, Object* obj) {
    InflatedHeader* ih = state->om->inflate_header(obj);

    capi::Handle* handle = ih->handle();

    if(handle) {
      // ref() ONLY if it's not already in there!
      // otherwise the refcount is wrong and we leak handles.
      capi::HandleSet::iterator pos = handles_.find(handle);
      if(pos == handles_.end()) {
        handle->ref();
        handles_.insert(handle);
      }
    } else {
      handle = new capi::Handle(state, obj);
      ih->set_handle(handle);

      state->shared.global_handles()->add(handle);

      handle->ref();
      handles_.insert(handle);
    }

    return handle->as_value();
  }
예제 #4
0
  RDataShadow* Data::rdata(STATE) {
    InflatedHeader* ih = state->om->inflate_header(this);
    capi::Handle* handle = ih->handle();

    assert(handle && handle->is_rdata() && "invalid initialized Data object");

    return reinterpret_cast<RDataShadow*>(handle->as_rdata(0));
  }
예제 #5
0
  void ObjectMemory::run_finalizers(STATE, CallFrame* call_frame) {
    if(running_finalizers_) return;
    running_finalizers_ = true;

    for(std::list<FinalizeObject*>::iterator i = to_finalize_.begin();
        i != to_finalize_.end(); ) {
      FinalizeObject* fi = *i;

      if(fi->finalizer) {
        (*fi->finalizer)(state, fi->object);
        // Unhook any handle used by fi->object so that we don't accidentally
        // try and mark it later (after we've finalized it)
        if(fi->object->inflated_header_p()) {
          InflatedHeader* ih = fi->object->inflated_header();

          if(capi::Handle* handle = ih->handle()) {
            handle->forget_object();
            ih->set_handle(0);
          }
        }

        // If the object was remembered, unremember it.
        if(fi->object->remembered_p()) {
          unremember_object(fi->object);
        }
      } else if(fi->ruby_finalizer) {
        // Rubinius specific code. If the finalizer is Qtrue, then
        // send the object the finalize message
        if(fi->ruby_finalizer == Qtrue) {
          fi->object->send(state, call_frame, state->symbol("__finalize__"), true);
        } else {
          Array* ary = Array::create(state, 1);
          ary->set(state, 0, fi->object->id(state));

          OnStack<1> os(state, ary);

          fi->ruby_finalizer->send(state, call_frame, state->symbol("call"), ary, Qnil, true);
        }
      } else {
        std::cerr << "Unsupported object to be finalized: "
                  << fi->object->to_s(state)->c_str() << "\n";
      }

      fi->status = FinalizeObject::eFinalized;

      i = to_finalize_.erase(i);
    }

    running_finalizers_ = false;
  }
예제 #6
0
  void ObjectMemory::validate_handles(capi::Handles* handles) {
    capi::Handle* handle = handles->front();
    capi::Handle* current;

    while(handle) {
      current = handle;
      handle = static_cast<capi::Handle*>(handle->next());

      Object* obj = current->object();

      assert(obj->inflated_header_p());
      InflatedHeader* ih = obj->inflated_header();

      assert(ih->handle() == current);
      assert(ih->object() == obj);
    }
  }
예제 #7
0
  VALUE NativeMethodFrame::get_handle(STATE, Object* obj) {
    InflatedHeader* ih = state->memory()->inflate_header(state, obj);

    capi::Handle* handle = ih->handle();

    if(handle) {
      if(handles_.add_if_absent(handle)) {
        // We're seeing this object for the first time in this function.
        // Be sure that it's updated.
        handle->update(NativeMethodEnvironment::get());
      }
    } else {
      handle = new capi::Handle(state, obj);
      ih->set_handle(handle);

      state->shared().add_global_handle(state, handle);

      handles_.add_if_absent(handle);
    }

    return handle->as_value();
  }