void GarbageCollector::clean_weakrefs(bool check_forwards) { if(!weak_refs_) return; for(ObjectArray::iterator i = weak_refs_->begin(); i != weak_refs_->end(); i++) { WeakRef* ref = try_as<WeakRef>(*i); if(!ref) continue; // WTF. Object* obj = ref->object(); if(!obj->reference_p()) continue; if(check_forwards) { if(obj->young_object_p()) { if(!obj->forwarded_p()) { ref->set_object(object_memory_, Qnil); } else { ref->set_object(object_memory_, obj->forward()); } } } else if(!obj->marked_p(object_memory_->mark())) { ref->set_object(object_memory_, Qnil); } } delete weak_refs_; weak_refs_ = NULL; }
SEXP R_WeakRefKey(SEXP w) { if (w->sexptype() != WEAKREFSXP) Rf_error(_("not a weak reference")); WeakRef* wr = static_cast<WeakRef*>(w); return wr->key(); }
void GarbageCollector::clean_weakrefs(bool check_forwards) { if(!weak_refs_) return; for(ObjectArray::iterator i = weak_refs_->begin(); i != weak_refs_->end(); ++i) { if(!*i) continue; // Object was removed during young gc. WeakRef* ref = try_as<WeakRef>(*i); if(!ref) continue; // Other type for some reason? Object* obj = ref->object(); if(!obj->reference_p()) continue; if(check_forwards) { if(obj->young_object_p()) { if(!obj->forwarded_p()) { ref->set_object(object_memory_, cNil); } else { ref->set_object(object_memory_, obj->forward()); } } } else if(!obj->marked_p(object_memory_->mark())) { ref->set_object(object_memory_, cNil); } } delete weak_refs_; weak_refs_ = NULL; }
bool WeakRef::runFinalizers() { WeakRef::check(); bool finalizer_run = !s_f10n_pending->empty(); WRList::iterator lit = s_f10n_pending->begin(); while (lit != s_f10n_pending->end()) { WeakRef* wr = *lit++; GCStackRoot<> topExp(R_CurrentExpr); size_t savestack = ProtectStack::size(); { // An Evaluator is declared for the finalizer to // insure that any errors that might occur do not spill into // the call that triggered the collection: Evaluator evalr; try { wr->finalize(); } catch (CommandTerminated) { } // Expose WeakRef to reference-counting collection: wr->m_self = 0; } ProtectStack::restoreSize(savestack); R_CurrentExpr = topExp; } return finalizer_run; }
SEXP R_WeakRefValue(SEXP w) { if (w->sexptype() != WEAKREFSXP) Rf_error(_("not a weak reference")); WeakRef* wr = static_cast<WeakRef*>(w); SEXP v = wr->value(); if (v && NAMED(v) != 2) SET_NAMED(v, 2); return v; }
void WeakRef::runExitFinalizers() { WeakRef::check(); WRList::iterator lit = s_live->begin(); while (lit != s_live->end()) { WeakRef* wr = *lit++; if (wr->m_finalize_on_exit) { wr->m_ready_to_finalize = true; wr->transfer(s_live, s_f10n_pending); } } runFinalizers(); }
void WeakRef::markThru() { WeakRef::check(); WRList newlive; // Step 2-3 of algorithm. Mark the value and R finalizer if the // key is marked. { unsigned int marks_applied; do { GCNode::Marker marker; WRList::iterator lit = s_live->begin(); while (lit != s_live->end()) { WeakRef* wr = *lit++; RObject* key = wr->key(); if (key->isMarked()) { RObject* value = wr->value(); if (value) marker(value); FunctionBase* Rfinalizer = wr->m_Rfinalizer; if (Rfinalizer) marker(Rfinalizer); wr->transfer(s_live, &newlive); } } marks_applied = marker.marksApplied(); } while (marks_applied > 0); } // Step 4 of algorithm. Process references with unmarked keys. { GCNode::Marker marker; WRList::iterator lit = s_live->begin(); while (lit != s_live->end()) { WeakRef* wr = *lit++; FunctionBase* Rfinalizer = wr->m_Rfinalizer; if (Rfinalizer) marker(Rfinalizer); if (Rfinalizer || wr->m_Cfinalizer) { marker(wr); marker(wr->m_key); wr->m_ready_to_finalize = true; wr->transfer(s_live, s_f10n_pending); } else { wr->tombstone(); // Expose to reference-counting collection: wr->m_self = 0; } } } // Step 5 of algorithm. Mark all live references with reachable keys. { GCNode::Marker marker; s_live->splice(s_live->end(), newlive); for (WRList::iterator lit = s_live->begin(); lit != s_live->end(); ++lit) { WeakRef* wr = *lit; marker(wr); } } }
Object* Module::reset_method_cache(STATE, Symbol* name) { if(Class* self = try_as<Class>(this)) { self->increment_serial(); } if(!name->nil_p()) { if(MethodTableBucket* b = method_table_->find_entry(state, name)) { Executable* exec = b->method(); if(!exec->nil_p()) { exec->clear_inliners(state); } } } if(!hierarchy_subclasses_->nil_p()) { for(native_int i = 0; i < hierarchy_subclasses_->size(); ++i) { WeakRef* ref = try_as<WeakRef>(hierarchy_subclasses_->get(state, i)); if(ref && ref->alive_p()) { Module* mod = as<Module>(ref->object()); mod->reset_method_cache(state, name); } } } return cNil; }
void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); if (!obj) return; typedef Pair<PropertyInfo, Variant> PropertyDesc; List<PropertyDesc> properties; if (ScriptInstance *si = obj->get_script_instance()) { if (!si->get_script().is_null()) { typedef Map<const Script *, Set<StringName> > ScriptMemberMap; typedef Map<const Script *, Map<StringName, Variant> > ScriptConstantsMap; ScriptMemberMap members; members[si->get_script().ptr()] = Set<StringName>(); si->get_script()->get_members(&(members[si->get_script().ptr()])); ScriptConstantsMap constants; constants[si->get_script().ptr()] = Map<StringName, Variant>(); si->get_script()->get_constants(&(constants[si->get_script().ptr()])); Ref<Script> base = si->get_script()->get_base_script(); while (base.is_valid()) { members[base.ptr()] = Set<StringName>(); base->get_members(&(members[base.ptr()])); constants[base.ptr()] = Map<StringName, Variant>(); base->get_constants(&(constants[base.ptr()])); base = base->get_base_script(); } for (ScriptMemberMap::Element *sm = members.front(); sm; sm = sm->next()) { for (Set<StringName>::Element *E = sm->get().front(); E; E = E->next()) { Variant m; if (si->get(E->get(), m)) { String script_path = sm->key() == si->get_script().ptr() ? "" : sm->key()->get_path().get_file() + "/"; PropertyInfo pi(m.get_type(), "Members/" + script_path + E->get()); properties.push_back(PropertyDesc(pi, m)); } } } for (ScriptConstantsMap::Element *sc = constants.front(); sc; sc = sc->next()) { for (Map<StringName, Variant>::Element *E = sc->get().front(); E; E = E->next()) { String script_path = sc->key() == si->get_script().ptr() ? "" : sc->key()->get_path().get_file() + "/"; if (E->value().get_type() == Variant::OBJECT) { Variant id = ((Object *)E->value())->get_instance_id(); PropertyInfo pi(id.get_type(), "Constants/" + E->key(), PROPERTY_HINT_OBJECT_ID, "Object"); properties.push_back(PropertyDesc(pi, id)); } else { PropertyInfo pi(E->value().get_type(), "Constants/" + script_path + E->key()); properties.push_back(PropertyDesc(pi, E->value())); } } } } } if (Node *node = Object::cast_to<Node>(obj)) { PropertyInfo pi(Variant::NODE_PATH, String("Node/path")); properties.push_front(PropertyDesc(pi, node->get_path())); } else if (Resource *res = Object::cast_to<Resource>(obj)) { if (Script *s = Object::cast_to<Script>(res)) { Map<StringName, Variant> constants; s->get_constants(&constants); for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { if (E->value().get_type() == Variant::OBJECT) { Variant id = ((Object *)E->value())->get_instance_id(); PropertyInfo pi(id.get_type(), "Constants/" + E->key(), PROPERTY_HINT_OBJECT_ID, "Object"); properties.push_front(PropertyDesc(pi, E->value())); } else { PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key()); properties.push_front(PropertyDesc(pi, E->value())); } } } } List<PropertyInfo> pinfo; obj->get_property_list(&pinfo, true); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) { properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name))); } } Array send_props; for (int i = 0; i < properties.size(); i++) { const PropertyInfo &pi = properties[i].first; Variant &var = properties[i].second; WeakRef *ref = Object::cast_to<WeakRef>(var); if (ref) { var = ref->get_ref(); } RES res = var; Array prop; prop.push_back(pi.name); prop.push_back(pi.type); //only send information that can be sent.. int len = 0; //test how big is this to encode encode_variant(var, NULL, len); if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size prop.push_back(PROPERTY_HINT_OBJECT_TOO_BIG); prop.push_back(""); prop.push_back(pi.usage); prop.push_back(Variant()); } else { prop.push_back(pi.hint); prop.push_back(pi.hint_string); prop.push_back(pi.usage); if (!res.is_null()) { var = res->get_path(); } prop.push_back(var); } send_props.push_back(prop); } packet_peer_stream->put_var("message:inspect_object"); packet_peer_stream->put_var(3); packet_peer_stream->put_var(p_id); packet_peer_stream->put_var(obj->get_class()); packet_peer_stream->put_var(send_props); }
void GC::Heap::mark(void) { #if defined(MINIZINC_GC_STATS) std::cerr << "================= mark =================: "; gc_stats.clear(); #endif for (KeepAlive* e = _roots; e != NULL; e = e->next()) { if ((*e)() && (*e)()->_gc_mark==0) { Expression::mark((*e)()); #if defined(MINIZINC_GC_STATS) gc_stats[(*e)()->_id].keepalive++; #endif } } #if defined(MINIZINC_GC_STATS) std::cerr << "+"; #endif Model* m = _rootset; if (m==NULL) return; do { for (unsigned int j=0; j<m->_items.size(); j++) { Item* i = m->_items[j]; if (i->_gc_mark==0) { i->_gc_mark = 1; i->loc().mark(); switch (i->iid()) { case Item::II_INC: i->cast<IncludeI>()->f().mark(); break; case Item::II_VD: Expression::mark(i->cast<VarDeclI>()->e()); #if defined(MINIZINC_GC_STATS) gc_stats[i->cast<VarDeclI>()->e()->Expression::eid()].inmodel++; #endif break; case Item::II_ASN: i->cast<AssignI>()->id().mark(); Expression::mark(i->cast<AssignI>()->e()); Expression::mark(i->cast<AssignI>()->decl()); break; case Item::II_CON: Expression::mark(i->cast<ConstraintI>()->e()); #if defined(MINIZINC_GC_STATS) gc_stats[i->cast<ConstraintI>()->e()->Expression::eid()].inmodel++; #endif break; case Item::II_SOL: { SolveI* si = i->cast<SolveI>(); for (ExpressionSetIter it = si->ann().begin(); it != si->ann().end(); ++it) { Expression::mark(*it); } } Expression::mark(i->cast<SolveI>()->e()); break; case Item::II_OUT: Expression::mark(i->cast<OutputI>()->e()); break; case Item::II_FUN: { FunctionI* fi = i->cast<FunctionI>(); fi->id().mark(); Expression::mark(fi->ti()); for (ExpressionSetIter it = fi->ann().begin(); it != fi->ann().end(); ++it) { Expression::mark(*it); } Expression::mark(fi->e()); fi->params().mark(); for (unsigned int k=0; k<fi->params().size(); k++) { Expression::mark(fi->params()[k]); } } break; } } } m = m->_roots_next; } while (m != _rootset); for (unsigned int i=trail.size(); i--;) { Expression::mark(trail[i].v); } for (WeakRef* wr = _weakRefs; wr != NULL; wr = wr->next()) { if ((*wr)() && (*wr)()->_gc_mark==0) { wr->_e = NULL; wr->_valid = false; } } #if defined(MINIZINC_GC_STATS) std::cerr << "+"; std::cerr << "\n"; #endif }
void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); if (!obj) return; typedef Pair<PropertyInfo, Variant> PropertyDesc; List<PropertyDesc> properties; if (ScriptInstance *si = obj->get_script_instance()) { if (!si->get_script().is_null()) { Set<StringName> members; si->get_script()->get_members(&members); for (Set<StringName>::Element *E = members.front(); E; E = E->next()) { Variant m; if (si->get(E->get(), m)) { PropertyInfo pi(m.get_type(), String("Members/") + E->get()); properties.push_back(PropertyDesc(pi, m)); } } Map<StringName, Variant> constants; si->get_script()->get_constants(&constants); for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { PropertyInfo pi(E->value().get_type(), (String("Constants/") + E->key())); properties.push_back(PropertyDesc(pi, E->value())); } } } if (Node *node = Object::cast_to<Node>(obj)) { PropertyInfo pi(Variant::NODE_PATH, String("Node/path")); properties.push_front(PropertyDesc(pi, node->get_path())); } else if (Resource *res = Object::cast_to<Resource>(obj)) { if (Script *s = Object::cast_to<Script>(res)) { Map<StringName, Variant> constants; s->get_constants(&constants); for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key()); properties.push_front(PropertyDesc(pi, E->value())); } } } List<PropertyInfo> pinfo; obj->get_property_list(&pinfo, true); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) { properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name))); } } Array send_props; for (int i = 0; i < properties.size(); i++) { const PropertyInfo &pi = properties[i].first; Variant &var = properties[i].second; WeakRef *ref = Object::cast_to<WeakRef>(var); if (ref) { var = ref->get_ref(); } RES res = var; Array prop; prop.push_back(pi.name); prop.push_back(pi.type); //only send information that can be sent.. int len = 0; //test how big is this to encode encode_variant(var, NULL, len); if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size prop.push_back(PROPERTY_HINT_OBJECT_TOO_BIG); prop.push_back(""); prop.push_back(pi.usage); prop.push_back(Variant()); } else { prop.push_back(pi.hint); if (res.is_null()) prop.push_back(pi.hint_string); else prop.push_back(String("RES:") + res->get_path()); prop.push_back(pi.usage); prop.push_back(var); } send_props.push_back(prop); } packet_peer_stream->put_var("message:inspect_object"); packet_peer_stream->put_var(3); packet_peer_stream->put_var(p_id); packet_peer_stream->put_var(obj->get_class()); packet_peer_stream->put_var(send_props); }
void WeakRef::Info::mark(Object* obj, ObjectMark& mark) { WeakRef* ref = as<WeakRef>(obj); if(ref->alive_p()) { mark.gc->add_weak_ref(obj); } }
WeakRef* WeakRef::create(STATE, Object* obj) { WeakRef* ref = state->new_object<WeakRef>(G(cls_weakref)); ref->set_object(state, obj); return ref; }
void ReflectedProperty::ToString( const void * object, AString & buffer ) const { switch ( m_Type ) { case PT_FLOAT: { float f; GetProperty( object, &f ); buffer.Format( "%1.1f", f ); // TODO: Find a good format specifier return; } case PT_UINT8: { uint8_t u; GetProperty( object, &u ); buffer.Format( "%u", u ); return; } case PT_UINT16: { uint16_t u; GetProperty( object, &u ); buffer.Format( "%u", u ); return; } case PT_UINT32: { uint32_t u; GetProperty( object, &u ); buffer.Format( "%u", u ); return; } case PT_UINT64: { uint64_t u; GetProperty( object, &u ); buffer.Format( "%" PRIu64, u ); return; } case PT_INT8: { int8_t i; GetProperty( object, &i ); buffer.Format( "%i", i ); return; } case PT_INT16: { int16_t i; GetProperty( object, &i ); buffer.Format( "%i", i ); return; } case PT_INT32: { int32_t i; GetProperty( object, &i ); buffer.Format( "%i", i ); return; } case PT_INT64: { int64_t i; GetProperty( object, &i ); buffer.Format( "%" PRIi64, i ); return; } case PT_BOOL: { bool b; GetProperty( object, &b ); buffer.Format( "%s", b ? "true" : "false" ); return; } case PT_ASTRING: { AStackString<> str; GetProperty( object, &str ); buffer.Format( "%s", str.Get() ); // TODO: Think about escaping break; } case PT_VEC2: { Vec2 v; GetProperty( object, &v ); buffer.Format( "%.1f, %.1f", v.x, v.y ); // TODO: Find a good format specifier return; } case PT_VEC3: { Vec3 v; GetProperty( object, &v ); buffer.Format( "%.1f, %.1f, %.1f", v.x, v.y, v.z ); // TODO: Find a good format specifier return; } case PT_VEC4: { Vec4 v; GetProperty( object, &v ); buffer.Format( "%.1f, %.1f, %.1f, %.1f", v.x, v.y, v.z, v.w ); // TODO: Find a good format specifier return; } case PT_MAT44: { Mat44 m; GetProperty( object, &m ); buffer.Format( "%.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f", // TODO: Find a good format specifier m.col0.x, m.col0.y, m.col0.z, m.col0.z, m.col1.x, m.col1.y, m.col1.z, m.col1.z, m.col2.x, m.col2.y, m.col2.z, m.col2.z, m.col3.x, m.col3.y, m.col3.z, m.col3.z ); return; } case PT_WEAKREF: { WeakRef< Object > w; GetProperty( object, &w ); if ( w.Get() == nullptr ) { buffer.Format( "null" ); } else { w->GetScopedName( buffer ); } return; } case PT_REF: case PT_STRUCT: { ASSERT( false ); // Unsupported } case PT_NONE: { ASSERT( false ); // Should be impossible } } }