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; }
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(); }
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(); }
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)); }
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; }
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); } }
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(); }