From 673f00b55795ad48e5fbfe9a4332cdfbcfcb93de Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 10 Dec 2024 13:19:30 -0500 Subject: [PATCH 01/39] Redo weak pointers Move the important code into gctools where it belongs, add support for "weak pointers" of immediate objects (because whether something is immediate is an implementation detail we shouldn't expose). --- include/clasp/core/weakPointer.h | 24 ++++++------------------ include/clasp/gctools/gcweak.h | 29 +++++++++++++++++++++++++++++ src/analysis/clasp_gc.sif | 10 ++++++---- src/analysis/clasp_gc_cando.sif | 10 ++++++---- src/core/weakPointer.cc | 26 ++++++-------------------- src/gctools/gcweak.cc | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 46 deletions(-) diff --git a/include/clasp/core/weakPointer.h b/include/clasp/core/weakPointer.h index 8eccbe06ac..fb9ce70d49 100644 --- a/include/clasp/core/weakPointer.h +++ b/include/clasp/core/weakPointer.h @@ -28,10 +28,13 @@ THE SOFTWARE. #include #include +#include template <> struct gctools::GCInfo { static bool const NeedsInitialization = false; - static bool const NeedsFinalization = true; + static bool const NeedsFinalization = false; + // the atomic policy means this object is not scanned by the GC, which is the + // actual reason the pointer is weak! static GCInfo_policy constexpr Policy = atomic; }; @@ -39,28 +42,13 @@ namespace core { FORWARD(WeakPointer); class WeakPointer_O : public General_O { LISP_CLASS(core, CorePkg, WeakPointer_O, "WeakPointer", General_O); - WeakPointer_O() : _Link(NULL), _Object(NULL){}; - WeakPointer_O(T_sp ptr) : _Link(ptr.raw_()), _Object(ptr.raw_()) { -#ifdef USE_BOEHM - GC_general_register_disappearing_link((void**)&this->_Link, &*ptr); -#else - SIMPLE_ERROR("WeakPointer_O not supported"); -#endif - }; - ~WeakPointer_O() { -#ifdef USE_BOEHM - GC_unregister_disappearing_link((void**)&this->_Link); -#else - SIMPLE_ERROR("WeakPointer_O not supported"); -#endif - } + WeakPointer_O(T_sp ptr) : _Link(ptr) {} public: static WeakPointer_sp make(T_sp obj); public: - void* _Link; // Use a boehm disappearing link - void* _Object; + gctools::WeakPointer _Link; // Use a boehm disappearing link public: // Functions here /*! Value of the reference to the object. If the object was destroyed then return nil. */ diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index 3c60a91157..da564239d8 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -71,6 +71,7 @@ THE SOFTWARE. */ #include +#include namespace gctools { @@ -378,4 +379,32 @@ struct TaggedCast, gctools::s } }; +// This structure is meant to be included directly (not as a pointer) in +// a weak pointer object, e.g. WeakPointer_O. In order to ensure the pointer +// is not scanned, this should be allocated with the "atomic" GC policy. +struct WeakPointer { +public: + WeakPointer(core::T_sp o); + std::optional value() const; +public: // has to be public for precise GC reasons even though it's not scanned? + // This is a Tagged rather than a T_sp because something in gc_boot seems to + // check for T_sps in atomic (pointerless) objects. Rather than lie harder we + // can just do this and build a T_sp from it as required. + Tagged _value; + // flag needed to disambiguate fixnum 0 from splatted pointer + // not sure if other GCs need this, but i'd like to keep the structure + // consistent regardless of build parameters if possible. + bool _splattablep = false; +#ifdef USE_BOEHM +private: + // private stuff needed to get everything done within a callback + struct value_helper_s { + value_helper_s(const WeakPointer* w) : wp(w), result() {} + const WeakPointer* wp; + std::optional result; + }; + static void* value_helper(void*); +#endif // lacking real support, we have not-actually-weak pointers. +}; + }; // namespace gctools diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index 29f06bf0cf..e45d656e66 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -838,10 +838,12 @@ {class-kind :stamp-name "STAMPWTAG_core__WeakPointer_O" :stamp-key "core::WeakPointer_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "RAW_POINTER_OFFSET" :offset-ctype "UnknownType" - :offset-base-ctype "core::WeakPointer_O" :layout-offset-field-names ("_Link")} -{fixed-field :offset-type-cxx-identifier "RAW_POINTER_OFFSET" :offset-ctype "UnknownType" - :offset-base-ctype "core::WeakPointer_O" :layout-offset-field-names ("_Object")} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakPointer_O" + :layout-offset-field-names ("_Link" "._value")} +{fixed-field :offset-type-cxx-identifier "ctype__Bool" :offset-ctype "_Bool" + :offset-base-ctype "core::WeakPointer_O" + :layout-offset-field-names ("_Link" "._splattablep")} {class-kind :stamp-name "STAMPWTAG_llvmo__DebugLoc_O" :stamp-key "llvmo::DebugLoc_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index 3e1b5041ab..9c68cce100 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -6524,10 +6524,12 @@ {class-kind :stamp-name "STAMPWTAG_core__WeakPointer_O" :stamp-key "core::WeakPointer_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "RAW_POINTER_OFFSET" :offset-ctype "UnknownType" - :offset-base-ctype "core::WeakPointer_O" :layout-offset-field-names ("_Link")} -{fixed-field :offset-type-cxx-identifier "RAW_POINTER_OFFSET" :offset-ctype "UnknownType" - :offset-base-ctype "core::WeakPointer_O" :layout-offset-field-names ("_Object")} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakPointer_O" + :layout-offset-field-names ("_Link" "._value")} +{fixed-field :offset-type-cxx-identifier "ctype__Bool" :offset-ctype "_Bool" + :offset-base-ctype "core::WeakPointer_O" + :layout-offset-field-names ("_Link" "._splattablep")} {class-kind :stamp-name "STAMPWTAG_llvmo__DebugLoc_O" :stamp-key "llvmo::DebugLoc_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/core/weakPointer.cc b/src/core/weakPointer.cc index d96a75f800..0eb4934f88 100644 --- a/src/core/weakPointer.cc +++ b/src/core/weakPointer.cc @@ -38,34 +38,20 @@ namespace core { CL_LISPIFY_NAME(make-weak-pointer); DOCGROUP(clasp); CL_DEFUN WeakPointer_sp WeakPointer_O::make(T_sp obj) { - if (obj.objectp()) { - auto me = gctools::GC::allocate(obj); - return me; - } - SIMPLE_ERROR("You cannot make a weak pointer to an immediate"); + return gctools::GC::allocate(obj); }; CL_LISPIFY_NAME("weakPointerValid"); CL_DEFMETHOD bool WeakPointer_O::valid() const { -#if defined(USE_BOEHM) - return this->_Link != NULL; -#else - SIMPLE_ERROR("WeakPointer_O not supported in this GC"); -#endif + return _Link.value().has_value(); } -/*! Return (values value t) or (values nil nil) */ +/*! Return the value if it's live, or NIL if it's dead. */ CL_LISPIFY_NAME("weakPointerValue"); CL_DEFMETHOD T_sp WeakPointer_O::value() const { -#if defined(USE_BOEHM) - if (this->_Link != NULL) { - T_sp obj((gctools::Tagged)this->_Object); - return obj; - } - return nil(); -#else - SIMPLE_ERROR("WeakPointer_O not supported by this GC"); -#endif + auto r = _Link.value(); + if (r) return *r; + else return nil(); } }; // namespace core diff --git a/src/gctools/gcweak.cc b/src/gctools/gcweak.cc index fca1f72fd5..bff223f707 100644 --- a/src/gctools/gcweak.cc +++ b/src/gctools/gcweak.cc @@ -33,6 +33,7 @@ THE SOFTWARE. */ /* -^- */ #include +#include #include #include #include @@ -359,4 +360,35 @@ core::Vector_sp WeakKeyHashTable::pairs() const { } return keyvalues; }; + +#ifdef USE_BOEHM +WeakPointer::WeakPointer(core::T_sp o) : _value(o.tagged_()) { + if (o.objectp()) { // pointer, so we're actually weak + _splattablep = true; + // note: deregistered automatically if the weak pointer itself is dealloc'd + GC_general_register_disappearing_link((void**)&_value, &*o); + } +} + +void* WeakPointer::value_helper(void* data) { + value_helper_s* vhsp = (value_helper_s*)data; + if (vhsp->wp->_value || !vhsp->wp->_splattablep) // not splatted + // construct a T_sp in the result + vhsp->result.emplace(vhsp->wp->_value); + // otherwise, leave the result default constructed (no T_sp) + return nullptr; // unused +} + +std::optional WeakPointer::value() const { + value_helper_s vhs(this); + // TODO: Use GC_call_with_reader_lock, but it's too new + GC_call_with_alloc_lock(value_helper, &vhs); + return vhs.result; +} +#else // not-actually-weak pointers - TODO for your other GC! +WeakPointer::WeakPointer(core::T_sp o) : _value(o.tagged_()) {} + +// always valid +std::optional WeakPointer::value() const { return core::T_sp(_value); } +#endif } // namespace gctools From 6e10aa10219c2a3245957b0e2a0478379f712e78 Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 16 Dec 2024 13:11:33 -0500 Subject: [PATCH 02/39] Add "ephemerons" with many caveats. --- include/clasp/core/weakPointer.h | 18 ++++++++++++++ include/clasp/gctools/gcweak.h | 39 +++++++++++++++++++++++++++++ src/analysis/clasp_gc.sif | 15 +++++++++--- src/analysis/clasp_gc_cando.sif | 11 ++++++++- src/core/weakPointer.cc | 23 +++++++++++++++++ src/gctools/gcweak.cc | 42 ++++++++++++++++++++++++++++++++ 6 files changed, 144 insertions(+), 4 deletions(-) diff --git a/include/clasp/core/weakPointer.h b/include/clasp/core/weakPointer.h index fb9ce70d49..032b923a4c 100644 --- a/include/clasp/core/weakPointer.h +++ b/include/clasp/core/weakPointer.h @@ -58,4 +58,22 @@ class WeakPointer_O : public General_O { bool valid() const; }; +// WARNING: Not a real ephemeron on some GCs (boehm). See notes in gcweak.h. +FORWARD(Ephemeron); +class Ephemeron_O : public General_O { + LISP_CLASS(core, CorePkg, Ephemeron_O, "Ephemeron", General_O); + Ephemeron_O(T_sp key, T_sp value) : _ephemeron(key, value) {} + +public: + static Ephemeron_sp make(T_sp key, T_sp value); + +public: + gctools::Ephemeron _ephemeron; + +public: + T_sp key() const; + T_sp value() const; + bool valid() const; +}; + }; // namespace core diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index da564239d8..ecfa240b5d 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -407,4 +407,43 @@ struct WeakPointer { #endif // lacking real support, we have not-actually-weak pointers. }; +// On Boehm this is not a real ephemeron - it's a weak pointer to the key, +// and a strong pointer to the value that happens to get wiped with the key. +// To see the difference, imagine having two inverse ephemerons {V1, V2} and +// {V2, V1}, where V1 and V2 are some otherwise inaccessible objects. With real +// ephemerons, the ephemeron values (V2 and V1) will not be scanned unless the +// keys (V1 and V2) are otherwise inaccessible, which they are not, and so both +// ephemerons can be wiped by the GC. With these boehm "ephemerons" V1 and V2 +// will be kept alive by the strong pointers and so both will be alive forever. +// Another issue comes up when an ephemeron's value contains the only strong +// references to the ephemeron's key; in a real ephemeron this will not keep the +// ephemeron alive, but it will in these. + +// TL;DR: The Boehm interface does not seem to allow real ephemerons. +// These pseudo ephemerons can at least handle some basic cases of weak hash +// tables without entailing too bad of a memory leak. +struct Ephemeron { +public: + Ephemeron(core::T_sp key, core::T_sp value); + std::optional key() const; + std::optional value() const; +public: +#ifdef USE_BOEHM + GC_hidden_pointer _key; +#else // FIXME for other GCs! + core::T_sp _key; +#endif + core::T_sp _value; +#ifdef USE_BOEHM +private: + struct result_helper_s { + result_helper_s(const Ephemeron* e) : eph(e), result() {} + const Ephemeron* eph; + std::optional result; + }; + static void* key_helper(void*); + static void* value_helper(void*); +#endif +}; + }; // namespace gctools diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index e45d656e66..dcf0035392 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -58,9 +58,9 @@ "comp::GlobalMacroInfo_O" "core::MDArray_int64_t_O" "core::SimpleMDArray_size_t_O" "comp::VariableCellInfo_O" "core::SmallMultimap_O" "core::Fixnum_dummy_O" "core::AuxArgument" - "core::MDArray_int8_t_O" "llvmo::ConstantFP_O" "core::BytecodeDebugVar_O" - "core::BlockDynEnv_O" "core::Cons_O" "clbind::detail::vertex" - "llvmo::LLVMContext_O" "core::MDArray_int4_t_O" + "core::MDArray_int8_t_O" "core::Ephemeron_O" "core::BytecodeDebugVar_O" + "llvmo::ConstantFP_O" "core::BlockDynEnv_O" "core::Cons_O" + "clbind::detail::vertex" "llvmo::LLVMContext_O" "core::MDArray_int4_t_O" "core::WeakKeyHashTable_O" "core::Rack_O" "core::MDArrayBaseChar_O" "core::UserData_O" "core::ExternalObject_O" "llvmo::DINode_O" "llvmo::GlobalVariable_O" "core::SimpleVector_short_float_O" @@ -4701,6 +4701,15 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::BytecodeDebugVar_O" :layout-offset-field-names ("_decls")} +{class-kind :stamp-name "STAMPWTAG_core__Ephemeron_O" :stamp-key "core::Ephemeron_O" + :parent-class "core::General_O" :lisp-class-base "core::General_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::Ephemeron_O" + :layout-offset-field-names ("_ephemeron" "._key")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Ephemeron_O" + :layout-offset-field-names ("_ephemeron" "._value")} {class-kind :stamp-name "STAMPWTAG_core__SmallMultimap_O" :stamp-key "core::SmallMultimap_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index 9c68cce100..1f9fa8cb09 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -102,7 +102,7 @@ "comp::GlobalMacroInfo_O" "core::SimpleMDArray_size_t_O" "core::MDArray_int64_t_O" "core::SmallMultimap_O" "comp::VariableCellInfo_O" "core::Fixnum_dummy_O" "core::AuxArgument" - "core::MDArray_int8_t_O" "core::BytecodeDebugVar_O" + "core::MDArray_int8_t_O" "core::BytecodeDebugVar_O" "core::Ephemeron_O" "chem::ZMatrixBondInternal_O" "llvmo::ConstantFP_O" "core::BlockDynEnv_O" "core::Cons_O" "clbind::detail::vertex" "chem::ImproperTorsion_O" "chem::ZMatrixAngleInternal_O" "chem::Rotamer_O" "llvmo::LLVMContext_O" @@ -5853,6 +5853,15 @@ :offset-base-ctype "mpip::Mpi_O" :layout-offset-field-names ("_Source")} {fixed-field :offset-type-cxx-identifier "ctype_int" :offset-ctype "int" :offset-base-ctype "mpip::Mpi_O" :layout-offset-field-names ("_Tag")} +{class-kind :stamp-name "STAMPWTAG_core__Ephemeron_O" :stamp-key "core::Ephemeron_O" + :parent-class "core::General_O" :lisp-class-base "core::General_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::Ephemeron_O" + :layout-offset-field-names ("_ephemeron" "._key")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Ephemeron_O" + :layout-offset-field-names ("_ephemeron" "._value")} {class-kind :stamp-name "STAMPWTAG_comp__VariableCellInfo_O" :stamp-key "comp::VariableCellInfo_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/core/weakPointer.cc b/src/core/weakPointer.cc index 0eb4934f88..9773b39b1d 100644 --- a/src/core/weakPointer.cc +++ b/src/core/weakPointer.cc @@ -54,4 +54,27 @@ CL_DEFMETHOD T_sp WeakPointer_O::value() const { else return nil(); } +CL_LISPIFY_NAME(make-ephemeron); +CL_DEFUN Ephemeron_sp Ephemeron_O::make(T_sp key, T_sp value) { + return gctools::GC::allocate(key, value); +} + +CL_LISPIFY_NAME("ephemeron/key"); +CL_DEFMETHOD T_sp Ephemeron_O::key() const { + auto r = _ephemeron.key(); + if (r) return *r; + else return nil(); +} +CL_LISPIFY_NAME("ephemeron/value"); +CL_DEFMETHOD T_sp Ephemeron_O::value() const { + auto r = _ephemeron.value(); + if (r) return *r; + else return nil(); +} + +CL_LISPIFY_NAME("ephemeron/validp"); +CL_DEFMETHOD bool Ephemeron_O::valid() const { + return _ephemeron.key().has_value(); +} + }; // namespace core diff --git a/src/gctools/gcweak.cc b/src/gctools/gcweak.cc index bff223f707..e7fb6863f3 100644 --- a/src/gctools/gcweak.cc +++ b/src/gctools/gcweak.cc @@ -391,4 +391,46 @@ WeakPointer::WeakPointer(core::T_sp o) : _value(o.tagged_()) {} // always valid std::optional WeakPointer::value() const { return core::T_sp(_value); } #endif + +#ifdef USE_BOEHM +Ephemeron::Ephemeron(core::T_sp k, core::T_sp v) + : _key(GC_HIDE_POINTER(k.tagged_())), _value(v) { + GCTOOLS_ASSERT(_key); // basically asserts that ~0 is never passed in, + // since if it was there'd be no way to tell if it's splatted + if (k.objectp()) { + GC_general_register_disappearing_link((void**)&_key, &*k); + GC_general_register_disappearing_link((void**)&_value, &*k); + } +} + +void* Ephemeron::key_helper(void* data) { + result_helper_s* rhsp = (result_helper_s*)data; + if (rhsp->eph->_key) // not splatted + rhsp->result.emplace((Tagged)GC_REVEAL_POINTER(rhsp->eph->_key)); + return nullptr; +} +void* Ephemeron::value_helper(void* data) { + result_helper_s* rhsp = (result_helper_s*)data; + if (rhsp->eph->_value) + rhsp->result.emplace(rhsp->eph->_value); + return nullptr; +} + +std::optional Ephemeron::key() const { + result_helper_s rhs(this); + // same TODO with GC_call_with_reader_lock. + GC_call_with_alloc_lock(key_helper, &rhs); + return rhs.result; +} +std::optional Ephemeron::value() const { + result_helper_s rhs(this); + GC_call_with_alloc_lock(value_helper, &rhs); + return rhs.result; +} +#else // not-actually-weak ephemeron default - FIXME for your GC! +Ephemeron::Ephemeron(core::T_sp key, core::T_sp value) : _key(key), _value(value) {} + +std::optional Ephemeron::key() const { return _key; } +std::optional Ephemeron::value() const { return _value; } +#endif } // namespace gctools From 76105d59d04e7b962b1a5bb4932f13ee058c6d07 Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 12:47:52 -0500 Subject: [PATCH 03/39] delete unused hash table functions --- include/clasp/core/hashTable.h | 19 +------ include/clasp/core/hashTableEq.h | 1 - src/core/hashTable.cc | 77 ----------------------------- src/core/instance.cc | 2 - src/lisp/kernel/lsp/foundation.lisp | 2 +- 5 files changed, 3 insertions(+), 98 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index 737ad379a3..bad74bf18f 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -125,11 +125,9 @@ class HashTable_O : public HashTableBase_O { uint calculateHashTableCount() const; public: - List_sp hash_table_bucket(size_t index); /*! If findKey is defined then search it as you rehash and return resulting keyValuePair CONS */ KeyValuePair* rehash_no_lock(bool expandTable, T_sp findKey); - CL_LISPIFY_NAME("hash-table-buckets"); - // CL_DEFMETHOD ComplexVector_T_sp hash_table_buckets() const { return this->_HashTable; }; + CL_LISPIFY_NAME("hash-table-shared-mutex"); CL_DEFMETHOD T_sp hash_table_shared_mutex() const { if (this->_Mutex) @@ -137,9 +135,8 @@ class HashTable_O : public HashTableBase_O { else return nil(); }; - // void set_thread_safe(bool thread_safe); + public: // Functions here - virtual bool is_eq_hashtable() const { return false; } virtual bool equalp(T_sp other) const override; /*! See CLHS */ @@ -160,9 +157,6 @@ class HashTable_O : public HashTableBase_O { /*! I'm not sure I need this and bucketsFind */ virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); KeyValuePair* tableRef_no_read_lock(T_sp key, cl_index index); - // List_sp findAssoc_no_lock(gc::Fixnum index, T_sp searchKey) const; - - T_sp hash_table_average_search_length(); /*! Return true if the key is within the hash table */ bool contains(T_sp key); @@ -188,8 +182,6 @@ class HashTable_O : public HashTableBase_O { string __repr__() const override; string hash_table_dump(); - void hash_table_pointers_dump(); - void hash_table_early_dump(); void lowLevelMapHash(KeyValueMapper* mapper) const; @@ -201,11 +193,6 @@ class HashTable_O : public HashTableBase_O { /*! maps function across a hash table until the function returns false */ bool /*terminatingMapHash*/ map_while_true(std::function const& fn) const; - /*! Return the number of entries in the HashTable Vector0 */ - int hashTableNumberOfHashes() const; - /*! Return the start of the alist in the HashTable Vector0 at hash value */ - // List_sp hashTableAlistAtHash(int hash) const; - string keysAsString(); /*! Look like a set */ @@ -214,8 +201,6 @@ class HashTable_O : public HashTableBase_O { List_sp keysAsCons(); }; -// HashTable_mv af_make_hash_table(T_sp test, Fixnum_sp size, Number_sp rehash_size, DoubleFloat_sp orehash_threshold); - T_mv clasp_gethash_safe(T_sp key, T_sp hashTable, T_sp default_); }; // namespace core diff --git a/include/clasp/core/hashTableEq.h b/include/clasp/core/hashTableEq.h index c2afc9c697..467579b7d8 100644 --- a/include/clasp/core/hashTableEq.h +++ b/include/clasp/core/hashTableEq.h @@ -48,7 +48,6 @@ class HashTableEq_O : public HashTable_O { static int sxhash_eq(T_sp obj); public: // Functions here - virtual bool is_eq_hashtable() const { return true; } virtual T_sp hashTableTest() const { return cl::_sym_eq; }; virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); bool keyTest(T_sp entryKey, T_sp searchKey) const; diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 4ee39679fc..edbb0fb710 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -218,20 +218,6 @@ CL_DEFUN Vector_sp core__hash_table_pairs(HashTableBase_sp hash_table_base) { // ---------------------------------------------------------------------- // -#if 0 -void HashTable_O::set_thread_safe(bool thread_safe) -{ -#ifdef CLASP_THREADS - if (thread_safe) { - SimpleBaseString_sp sbs = SimpleBaseString_O::make("HASHTABL"); - this->_Mutex = mp::SharedMutex_O::make_shared_mutex(sbs); - } else { - this->_Mutex.reset_(); - } -#endif -} -#endif - CL_LAMBDA(&key (test (function eql)) (size 0) (rehash-size 2.0) (rehash-threshold 0.7) weakness debug (thread-safe t) hash-function); CL_DECLARE(); CL_DOCSTRING( @@ -1132,42 +1118,6 @@ void dump_one_entry(HashTable_sp ht, size_t it, stringstream& ss, KeyValuePair& #endif }; -CL_DEFMETHOD List_sp HashTable_O::hash_table_bucket(size_t index) { - KeyValuePair& entry = this->_Table[index]; - if (!entry._Key.no_keyp() && !entry._Value.deletedp()) { - T_sp result = Cons_O::create(entry._Key, entry._Value); - return result; - } - return nil(); -} - -CL_DEFMETHOD T_sp HashTable_O::hash_table_average_search_length() { - HT_READ_LOCK(this); - gc::Fixnum iend(this->_Table.size()); - double sum = 0.0; - gc::Fixnum count = 0; - for (gc::Fixnum it(0), itEnd(iend); it < itEnd; ++it) { - const KeyValuePair& entry = this->_Table[it]; - if (!(entry._Key.no_keyp() || entry._Key.deletedp())) { - HashGenerator hg; - gc::Fixnum index = this->sxhashKey(entry._Key, this->_Table.size(), hg); - gc::Fixnum delta; - if (index > it) { - delta = (it + iend) - index; - } else { - delta = (it - index); - } - // printf("%s:%d index = %lld it = %lld delta=%lld\n", __FILE__, __LINE__, index, it, delta ); - sum = sum + delta; - count++; - } - } - if (count > 0) { - return core::clasp_make_double_float(sum / count); - } - return nil(); -} - CL_DEFMETHOD string HashTable_O::hash_table_dump() { stringstream ss; HT_READ_LOCK(this); @@ -1175,22 +1125,6 @@ CL_DEFMETHOD string HashTable_O::hash_table_dump() { return ss.str(); } -void HashTable_O::hash_table_pointers_dump() { - HASH_TABLE_ITER(this, key, value) { - printf("%s:%d key@%p: %s value@%p: %s\n", __FILE__, __LINE__, key.raw_(), _rep_(key).c_str(), value.raw_(), - _rep_(value).c_str()); - } - HASH_TABLE_ITER_END; -} - -void HashTable_O::hash_table_early_dump() { - HASH_TABLE_ITER(this, key, value) { - printf("%s:%d key@%p: %s value@%p: %s\n", __FILE__, __LINE__, key.raw_(), _rep_(key).c_str(), value.raw_(), - _rep_(value).c_str()); - } - HASH_TABLE_ITER_END; -} - void HashTable_O::mapHash(std::function const& fn) { HASH_TABLE_ITER(this, key, value) { fn(key, value); } HASH_TABLE_ITER_END; @@ -1216,12 +1150,6 @@ void HashTable_O::lowLevelMapHash(KeyValueMapper* mapper) const { return; } -CL_LISPIFY_NAME("core:hashTableNumberOfHashes"); -CL_DEFMETHOD int HashTable_O::hashTableNumberOfHashes() const { - HT_READ_LOCK(this); - return this->_Table.size(); -} - string HashTable_O::keysAsString() { stringstream ss; this->mapHash([&ss, this](T_sp key, T_sp val) { ss << _rep_(key) << " "; }); @@ -1263,11 +1191,6 @@ T_mv clasp_gethash_safe(T_sp key, T_sp thashTable, T_sp default_) { return hashTable->gethash(key, default_); } -CL_DEFUN void core__dont_ever_use_mangle_hash_table(HashTable_sp ht) { - uintptr_t* ptr = (uintptr_t*)&(ht->_Table); - *ptr = 41; -} - SYMBOL_EXPORT_SC_(ClPkg, make_hash_table); SYMBOL_EXPORT_SC_(ClPkg, maphash); SYMBOL_EXPORT_SC_(ClPkg, clrhash); diff --git a/src/core/instance.cc b/src/core/instance.cc index fdbdf0c83e..b2e9184324 100644 --- a/src/core/instance.cc +++ b/src/core/instance.cc @@ -442,8 +442,6 @@ void Instance_O::accumulateSuperClasses(HashTableEq_sp supers, ComplexVector_T_s // printf("%s:%d arraySuperLength = %ld\n", __FILE__, __LINE__, arraySuperLength); T_sp index = clasp_make_fixnum(arraySuperLength); supers->setf_gethash(mc, index); - // printf("%s:%d dumping supers hash-table\n", __FILE__, __LINE__ ); - // supers->hash_table_early_dump(); // printf("%s:%d associating %s with %s\n", __FILE__, __LINE__, _rep_(mc).c_str(), _rep_(index).c_str()); arrayedSupers->vectorPushExtend(mc); List_sp directSuperclasses = mc->directSuperclasses(); diff --git a/src/lisp/kernel/lsp/foundation.lisp b/src/lisp/kernel/lsp/foundation.lisp index ddbd9a4f48..4cd129a8e5 100644 --- a/src/lisp/kernel/lsp/foundation.lisp +++ b/src/lisp/kernel/lsp/foundation.lisp @@ -228,7 +228,7 @@ the corresponding VAR. Returns NIL." #+(or) (defun hash-table-iterator (hash-table) - (let ((number-of-buckets (hash-table-number-of-hashes hash-table)) + (let ((number-of-buckets (hash-table-size hash-table)) (hash 0)) (labels ((advance-hash-table-iterator () (declare (core:lambda-name advance-hash-table-iterator)) From d64b9a92be07f4c7e6b3f96e7fd75b43b8cc592a Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 13:06:38 -0500 Subject: [PATCH 04/39] simplify rehash function this looking for a key simultaneously thing is unused and unclean. --- include/clasp/core/hashTable.h | 5 ++-- src/core/hashTable.cc | 54 +++++++--------------------------- 2 files changed, 13 insertions(+), 46 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index bad74bf18f..0d75082e51 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -124,9 +124,10 @@ class HashTable_O : public HashTableBase_O { uint resizeEmptyTable_no_lock(size_t sz); uint calculateHashTableCount() const; + void rehash_no_lock(bool expandTable); + public: - /*! If findKey is defined then search it as you rehash and return resulting keyValuePair CONS */ - KeyValuePair* rehash_no_lock(bool expandTable, T_sp findKey); + void rehash(bool expandTable); CL_LISPIFY_NAME("hash-table-shared-mutex"); CL_DEFMETHOD T_sp hash_table_shared_mutex() const { diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index edbb0fb710..658047bff5 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -798,8 +798,7 @@ CL_DECLARE(); CL_DOCSTRING(R"dx(hashTableForceRehash)dx"); DOCGROUP(clasp); CL_DEFUN void core__hash_table_force_rehash(HashTable_sp ht) { - HT_WRITE_LOCK(&*ht); - ht->rehash_no_lock(false, no_key()); + ht->rehash(false); } T_mv HashTable_O::gethash(T_sp key, T_sp default_value) { @@ -954,7 +953,7 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { VERIFY_HASH_TABLE_VA(this, write, key); if (this->_HashTableCount > this->_RehashThreshold * this->_Table.size()) { LOG("Expanding hash table"); - this->rehash_no_lock(true, no_key()); + this->rehash_no_lock(true); VERIFY_HASH_TABLE(this); } return value; @@ -970,7 +969,7 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { __FILE__, __LINE__, this->_RehashThreshold, this->_HashTableCount, this->_Table.size()); verifyHashTable(true, std::cerr, this, __FILE__, __LINE__); printf("%s:%d ---- done verify\n", __FILE__, __LINE__); - this->rehash_no_lock(true, no_key()); + this->rehash_no_lock(true); VERIFY_HASH_TABLE_VA(this, cur); return this->setf_gethash_no_write_lock(key, value); // ------------ @@ -992,13 +991,12 @@ CL_DEFUN_SETF T_sp setf_gethash(T_sp value, T_sp key, HashTableBase_sp hash_tabl return hash_table->hash_table_setf_gethash(key, value); } -KeyValuePair* HashTable_O::rehash_no_lock(bool expandTable, T_sp findKey) { - // printf("%s:%d rehash of hash-table@%p\n", __FILE__, __LINE__, this ); +void HashTable_O::rehash_no_lock(bool expandTable) { DEBUG_HASH_TABLE1({ core::clasp_write_string(fmt::format("{}:{} rehash_no_lock\n", __FILE__, __LINE__)); }); ASSERTF(!Number_O::zerop(this->_RehashSize), "RehashSize is zero - it shouldn't be"); #ifdef DEBUG_HASH_TABLE_DEBUG if (this->_Debug) { - core::T_sp info = Cons_O::createList(INTERN_(kw, rehash), findKey); + core::T_sp info = INTERN_(kw, rehash); T_sp expected; Cons_sp cell = core::Cons_O::create(info, nil()); do { @@ -1011,7 +1009,6 @@ KeyValuePair* HashTable_O::rehash_no_lock(bool expandTable, T_sp findKey) { gc::Fixnum curSize = this->_Table.size(); ASSERTF(this->_Table.size() != 0, "HashTable is empty in expandHashTable curSize={} this->_Table.size()= {} this shouldn't be", curSize, this->_Table.size()); - KeyValuePair* foundKeyValuePair = nullptr; LOG("At start of expandHashTable current hash table size: {}", this->_Table.size()); gc::Fixnum newSize = 0; if (expandTable) { @@ -1034,19 +1031,6 @@ KeyValuePair* HashTable_O::rehash_no_lock(bool expandTable, T_sp findKey) { T_sp value = entry._Value; if (!key.no_keyp() && !key.deletedp()) { // key/value represent a valid entry in the hash table - // - // If findKey is not no_key and we haven't already found - // the value that it points to. - // then while we are rehashing the hash table we are also looking - // for the key it points to. - // Check if the current key matches findKey and if it does - // set foundKeyValuePair so that it will be returned when - // the rehash is complete. - if (foundKeyValuePair == nullptr && !findKey.no_keyp()) { - if (this->keyTest(key, findKey)) { - foundKeyValuePair = &entry; - } - } this->setf_gethash_no_write_lock(key, value); } } @@ -1057,29 +1041,11 @@ KeyValuePair* HashTable_O::rehash_no_lock(bool expandTable, T_sp findKey) { this->_HashTableId % this->_InitialSize % this->_RehashCount % newSize % oldHashTableCount % this->_HashTableCount); #endif VERIFY_HASH_TABLE(this); - // - // The following lookup is important for (setf (gethash key ht) val) when using MPS - // If the lookup of a reference for the key failed because of a stale pointer - // then that triggers a rehash and rehash searches for the key/value - // in the OLD table as it rehashes. So we can't return that reference - // because setf will then write into the OLD table! So below - // we lookup the reference again with tableRef_no_read_lock because - // it is guaranteed to return a reference to the current table of the hash-table. - if (foundKeyValuePair != nullptr) { - // Return the foundKeyValuePair in the latest table - T_sp key = foundKeyValuePair->_Key; - HashGenerator hg; - cl_index index = this->sxhashKey(key, this->_Table.size(), hg); - foundKeyValuePair = this->tableRef_no_read_lock(foundKeyValuePair->_Key, index); - } - DEBUG_HASH_TABLE({ - if (foundKeyValuePair) { - core::clasp_write_string(fmt::format("{}:{}:{} Returning foundKeyValuePair: {},{} at {} \n", __FILE__, __LINE__, - __FUNCTION__, _rep_(foundKeyValuePair->_Key), _rep_(foundKeyValuePair->_Value), - (void*)&*foundKeyValuePair)); - } - }); - return foundKeyValuePair; +} + +void HashTable_O::rehash(bool expandTable) { + HT_WRITE_LOCK(this); + rehash_no_lock(expandTable); } string HashTable_O::__repr__() const { From f24ade0f4625a42de80961600447d253391c31ea Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 13:39:27 -0500 Subject: [PATCH 05/39] mark a slew of hash table functions const but not gethash, yet, because it gets complicated --- include/clasp/core/hashTable.h | 14 +++++++------- include/clasp/core/hashTableBase.h | 8 ++++---- include/clasp/core/weakHashTable.h | 8 ++++---- include/clasp/gctools/gcweak.h | 4 ++-- src/core/hashTable.cc | 12 ++++++------ src/core/weakHashTable.cc | 8 ++++---- src/gctools/gcweak.cc | 4 ++-- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index 0d75082e51..fa2f502361 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -172,9 +172,9 @@ class HashTable_O : public HashTableBase_O { T_sp setf_gethash_no_write_lock(T_sp key, T_sp value); void setf_gethash(T_sp key, T_sp val) { this->hash_table_setf_gethash(key, val); }; - Number_sp rehash_size() override; - double rehash_threshold() override; - T_sp hash_table_test() override; + Number_sp rehash_size() const override; + double rehash_threshold() const override; + T_sp hash_table_test() const override; T_sp clrhash() override; @@ -186,15 +186,15 @@ class HashTable_O : public HashTableBase_O { void lowLevelMapHash(KeyValueMapper* mapper) const; - void maphash(T_sp fn) override; + void maphash(T_sp fn) const override; - void mapHash(std::function const& fn); - void maphash(std::function const& fn) { this->mapHash(fn); }; + void mapHash(std::function const& fn) const; + void maphash(std::function const& fn) const { this->mapHash(fn); }; /*! maps function across a hash table until the function returns false */ bool /*terminatingMapHash*/ map_while_true(std::function const& fn) const; - string keysAsString(); + string keysAsString() const; /*! Look like a set */ void insert(T_sp obj) { this->setf_gethash(obj, nil()); }; diff --git a/include/clasp/core/hashTableBase.h b/include/clasp/core/hashTableBase.h index 57d1c16d24..9cb66a2563 100644 --- a/include/clasp/core/hashTableBase.h +++ b/include/clasp/core/hashTableBase.h @@ -39,10 +39,10 @@ class HashTableBase_O : public General_O { virtual T_sp hash_table_setf_gethash(T_sp key, T_sp value) = 0; virtual T_mv gethash(T_sp key, T_sp default_value) = 0; virtual bool remhash(T_sp key) = 0; - virtual Number_sp rehash_size() = 0; - virtual double rehash_threshold() = 0; - virtual T_sp hash_table_test() = 0; - virtual void maphash(T_sp function_desig) = 0; + virtual Number_sp rehash_size() const = 0; + virtual double rehash_threshold() const = 0; + virtual T_sp hash_table_test() const = 0; + virtual void maphash(T_sp function_desig) const = 0; virtual T_sp clrhash() = 0; virtual size_t hashTableCount() const = 0; virtual size_t hashTableSize() const = 0; diff --git a/include/clasp/core/weakHashTable.h b/include/clasp/core/weakHashTable.h index 63f199f860..bc612be790 100644 --- a/include/clasp/core/weakHashTable.h +++ b/include/clasp/core/weakHashTable.h @@ -79,14 +79,14 @@ class WeakKeyHashTable_O : public HashTableBase_O { gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, bool willAddKey) const; void maphashLowLevel(std::function const& fn); - void maphash(T_sp functionDesig) override; + void maphash(T_sp functionDesig) const override; T_mv gethash(T_sp key, T_sp defaultValue = nil()) override; bool remhash(T_sp key) override; T_sp clrhash() override; - Number_sp rehash_size() override; - double rehash_threshold() override; - T_sp hash_table_test() override; + Number_sp rehash_size() const override; + double rehash_threshold() const override; + T_sp hash_table_test() const override; string __repr__() const override; }; diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index ecfa240b5d..463b0a45d6 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -306,8 +306,8 @@ class WeakKeyHashTable { core::T_mv gethash(core::T_sp tkey, core::T_sp defaultValue); void set(core::T_sp key, core::T_sp value); - void maphash(std::function const& fn); - void maphashFn(core::T_sp fn); + void maphash(std::function const& fn) const; + void maphashFn(core::T_sp fn) const; bool remhash(core::T_sp tkey); void clrhash(); core::Vector_sp pairs() const; diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 658047bff5..ee6a8bfaf9 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -331,7 +331,7 @@ HashTable_sp HashTable_O::create_thread_safe(T_sp test, SimpleBaseString_sp read #define HASH_TABLE_ITER_END } -void HashTable_O::maphash(T_sp function_desig) { +void HashTable_O::maphash(T_sp function_desig) const { Function_sp func = coerce::functionDesignator(function_desig); HASH_TABLE_ITER(this, key, value) { eval::funcall(func, key, value); } HASH_TABLE_ITER_END; @@ -1091,7 +1091,7 @@ CL_DEFMETHOD string HashTable_O::hash_table_dump() { return ss.str(); } -void HashTable_O::mapHash(std::function const& fn) { +void HashTable_O::mapHash(std::function const& fn) const { HASH_TABLE_ITER(this, key, value) { fn(key, value); } HASH_TABLE_ITER_END; } @@ -1116,23 +1116,23 @@ void HashTable_O::lowLevelMapHash(KeyValueMapper* mapper) const { return; } -string HashTable_O::keysAsString() { +string HashTable_O::keysAsString() const { stringstream ss; this->mapHash([&ss, this](T_sp key, T_sp val) { ss << _rep_(key) << " "; }); return ss.str(); } -Number_sp HashTable_O::rehash_size() { +Number_sp HashTable_O::rehash_size() const { HT_READ_LOCK(this); return this->_RehashSize; } -double HashTable_O::rehash_threshold() { +double HashTable_O::rehash_threshold() const { HT_READ_LOCK(this); return this->_RehashThreshold; } -T_sp HashTable_O::hash_table_test() { return this->hashTableTest(); } +T_sp HashTable_O::hash_table_test() const { return this->hashTableTest(); } CL_LAMBDA(arg); CL_DECLARE(); diff --git a/src/core/weakHashTable.cc b/src/core/weakHashTable.cc index c5f087528e..2a42cb0dca 100644 --- a/src/core/weakHashTable.cc +++ b/src/core/weakHashTable.cc @@ -41,11 +41,11 @@ void WeakKeyHashTable_O::initialize() { this->_HashTable.initialize(); } namespace core { -Number_sp WeakKeyHashTable_O::rehash_size() { return this->_HashTable._RehashSize; } +Number_sp WeakKeyHashTable_O::rehash_size() const { return this->_HashTable._RehashSize; } -double WeakKeyHashTable_O::rehash_threshold() { return this->_HashTable._RehashThreshold; } +double WeakKeyHashTable_O::rehash_threshold() const { return this->_HashTable._RehashThreshold; } -T_sp WeakKeyHashTable_O::hash_table_test() { return cl::_sym_eq; } +T_sp WeakKeyHashTable_O::hash_table_test() const { return cl::_sym_eq; } void WeakKeyHashTable_O::describe(T_sp stream) { KeyBucketsType& keys = *this->_HashTable._Keys; @@ -100,7 +100,7 @@ T_mv WeakKeyHashTable_O::gethash(T_sp key, T_sp defaultValue) { return this->_Ha void WeakKeyHashTable_O::maphashLowLevel(std::function const& fn) { this->_HashTable.maphash(fn); } -void WeakKeyHashTable_O::maphash(T_sp func) { this->_HashTable.maphashFn(func); } +void WeakKeyHashTable_O::maphash(T_sp func) const { this->_HashTable.maphashFn(func); } bool WeakKeyHashTable_O::remhash(T_sp tkey) { return this->_HashTable.remhash(tkey); } diff --git a/src/gctools/gcweak.cc b/src/gctools/gcweak.cc index e7fb6863f3..b0b195fb64 100644 --- a/src/gctools/gcweak.cc +++ b/src/gctools/gcweak.cc @@ -295,14 +295,14 @@ void WeakKeyHashTable::set(core::T_sp key, core::T_sp value) { #define HASH_TABLE_ITER_END } -void WeakKeyHashTable::maphash(std::function const& fn) { +void WeakKeyHashTable::maphash(std::function const& fn) const { safeRun([fn, this]() { HASH_TABLE_ITER(WeakKeyHashTable, this, key, value) { fn(key, value); } HASH_TABLE_ITER_END; }); } -void WeakKeyHashTable::maphashFn(core::T_sp fn) { +void WeakKeyHashTable::maphashFn(core::T_sp fn) const { safeRun([fn, this]() { HASH_TABLE_ITER(WeakKeyHashTable, this, key, value) { core::eval::funcall(fn, key, value); } HASH_TABLE_ITER_END; From 08be93f8f959a33079c2659bc3523cae38753c78 Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 14:05:50 -0500 Subject: [PATCH 06/39] Remove some internal aliases in hash table code --- include/clasp/core/hashTable.h | 9 +++------ include/clasp/core/hashTableEq.h | 4 ++-- src/core/hashTable.cc | 19 ++++--------------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index fa2f502361..daa84fd0c4 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -137,6 +137,9 @@ class HashTable_O : public HashTableBase_O { return nil(); }; +public: + virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); + public: // Functions here virtual bool equalp(T_sp other) const override; @@ -153,12 +156,6 @@ class HashTable_O : public HashTableBase_O { virtual gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, HashGenerator& hg) const; virtual bool keyTest(T_sp entryKey, T_sp searchKey) const; - /*! I'm not sure I need this and tableRef */ - List_sp bucketsFind_no_lock(T_sp key) const; - /*! I'm not sure I need this and bucketsFind */ - virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); - KeyValuePair* tableRef_no_read_lock(T_sp key, cl_index index); - /*! Return true if the key is within the hash table */ bool contains(T_sp key); diff --git a/include/clasp/core/hashTableEq.h b/include/clasp/core/hashTableEq.h index 467579b7d8..93d3763926 100644 --- a/include/clasp/core/hashTableEq.h +++ b/include/clasp/core/hashTableEq.h @@ -38,7 +38,8 @@ class HashTableEq_O : public HashTable_O { LISP_CLASS(core, CorePkg, HashTableEq_O, "HashTableEq", HashTable_O); DEFAULT_CTOR_DTOR(HashTableEq_O); -private: // instance variables here +public: + virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); public: static HashTableEq_sp create(uint sz, Number_sp rehashSize, double rehashThreshold); static HashTableEq_sp create_default(); @@ -49,7 +50,6 @@ class HashTableEq_O : public HashTable_O { public: // Functions here virtual T_sp hashTableTest() const { return cl::_sym_eq; }; - virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); bool keyTest(T_sp entryKey, T_sp searchKey) const; gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, HashGenerator& hg) const; diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index ee6a8bfaf9..77fe955523 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -782,17 +782,6 @@ KeyValuePair* HashTable_O::searchTable_no_read_lock(T_sp key, cl_index index) { return nullptr; } -KeyValuePair* HashTable_O::tableRef_no_read_lock(T_sp key, cl_index index) { - DEBUG_HASH_TABLE({ - core::clasp_write_string(fmt::format("{}:{}:{} key = {} index = {}\n", __FILE__, __LINE__, __FUNCTION__, _rep_(key), index)); - }); - VERIFY_HASH_TABLE(this); - BOUNDS_ASSERT(index < this->_Table.size()); - KeyValuePair* result = this->searchTable_no_read_lock(key, index); - VERIFY_HASH_TABLE(this); - return result; -} - CL_LAMBDA(ht); CL_DECLARE(); CL_DOCSTRING(R"dx(hashTableForceRehash)dx"); @@ -815,7 +804,7 @@ T_mv HashTable_O::gethash(T_sp key, T_sp default_value) { } // #endif cl_index index = this->sxhashKey(key, sz, hg); - KeyValuePair* keyValuePair = this->tableRef_no_read_lock(key, index); + KeyValuePair* keyValuePair = this->searchTable_no_read_lock(key, index); LOG("Found keyValueCons"); // % keyValueCons->__repr__() ); INFINITE-LOOP if (keyValuePair) { T_sp value = keyValuePair->_Value; @@ -840,7 +829,7 @@ KeyValuePair* HashTable_O::find(T_sp key) { HT_READ_LOCK(this); HashGenerator hg; cl_index index = this->sxhashKey(key, this->_Table.size(), hg); - KeyValuePair* keyValue = this->tableRef_no_read_lock(key, index); + KeyValuePair* keyValue = this->searchTable_no_read_lock(key, index); if (!keyValue) return keyValue; if (keyValue->_Value.no_keyp()) @@ -858,7 +847,7 @@ bool HashTable_O::remhash(T_sp key) { HT_WRITE_LOCK(this); HashGenerator hg; cl_index index = this->sxhashKey(key, this->_Table.size(), hg); - KeyValuePair* keyValuePair = this->tableRef_no_read_lock(key, index); + KeyValuePair* keyValuePair = this->searchTable_no_read_lock(key, index); if (keyValuePair) { keyValuePair->_Key = deleted(); this->_HashTableCount--; @@ -900,7 +889,7 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { core::clasp_write_string(fmt::format("{}:{}:{} index = {} this->_Table.size() = {}\n", __FILE__, __LINE__, __FUNCTION__, index, this->_Table.size())); }); - KeyValuePair* keyValuePair = this->tableRef_no_read_lock(key, index); + KeyValuePair* keyValuePair = this->searchTable_no_read_lock(key, index); if (keyValuePair) { // rewrite value keyValuePair->_Value = value; From 1fa955f8d14da81d21cc7cf294a6e46e95501a0f Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 14:18:52 -0500 Subject: [PATCH 07/39] delete hash table verification code it's way too ad hoc - it takes a string stream and a filename and writes to standard output, and calls itself with the print argument flipped anyway? If we run into hash table problems again we can come up with something cleaner or impermanent. --- src/core/hashTable.cc | 76 ------------------------------------------- 1 file changed, 76 deletions(-) diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 77fe955523..12594ff748 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -55,20 +55,6 @@ THE SOFTWARE. /**/ #define DEBUG_HASH_TABLE1(expr) #endif -#if 0 -#define VERIFY_HASH_TABLE(xxx) \ - if (this->_Debug) { \ - verifyHashTable(true, std::cerr, xxx, __FILE__, __LINE__); \ - } -#define VERIFY_HASH_TABLE_VA(xxx, ...) \ - if (this->_Debug) { \ - verifyHashTable(true, std::cerr, xxx, __FILE__, __LINE__, __VA_ARGS__); \ - } -#else -#define VERIFY_HASH_TABLE(xxx, ...) -#define VERIFY_HASH_TABLE_VA(xxx, ...) -#endif - // #define DEBUG_LEVEL_FULL #include @@ -107,54 +93,6 @@ std::atomic global_next_hash_table_id; size_t next_hash_table_id() { return global_next_hash_table_id++; } -void verifyHashTable(bool print, std::ostream& ss, HashTable_O* ht, const char* filename, size_t line, size_t index = 0, - T_sp key = nil()) { - if (print) { - clasp_write_string(fmt::format("verifyHashTable HashTable {} size {}\n", (void*)ht, ht->_Table.size())); - } - size_t cnt = 0; - Vector_sp keys = core__make_vector(_lisp->_true(), ht->_HashTableCount + 16, true, make_fixnum(0)); - for (size_t it(0), itEnd(ht->_Table.size()); it < itEnd; ++it) { - KeyValuePair& entry = ht->_Table[it]; - if (!entry._Key.no_keyp() && !entry._Key.deletedp()) { - if (print) { - clasp_write_string(fmt::format("Entry[{}] at {} key: {} badge: {} value: {}\n", it, (void*)&entry, _rep_(entry._Key), - gctools::lisp_general_badge(gc::As_unsafe(entry._Key)), (entry._Value))); - } - keys->vectorPushExtend(entry._Key); - } - } - if (print) { - bool bad = false; - for (size_t it(0), itEnd(cl__length(keys)); it < itEnd; ++it) { - T_sp key = keys->rowMajorAref(it); - HashGenerator hg; - cl_index index = ht->sxhashKey(key, ht->_Table.size(), hg); - KeyValuePair* keyValue = ht->searchTable_no_read_lock(key, index); - if (!keyValue) { - clasp_write_string(fmt::format( - "{}:{} Could not find key {} badge = {} expected at or after Entry[{}] for ht->_Table.size() = {}\n", filename, line, - _rep_(key), gctools::lisp_general_badge(gc::As_unsafe(key)), index, ht->_Table.size())); - clasp_write_string(fmt::format(" hg.asList() -> \n{}\n", _rep_(hg.asList()))); - bad = true; - } - } - if (bad) { -#ifdef DEBUG_HASH_TABLE_DEBUG - clasp_write_string(fmt::format(" hash-table _History ->\n{}\n", _rep_(ht->_History.load()))); -#endif - } - } - if (!print) { - if (cl__length(keys) != ht->_HashTableCount) { - std::cerr << filename << ":" << line << " Working on index " << index << " - dumping hash-table\n"; - verifyHashTable(true, std::cerr, ht, filename, line); - std::cerr << " Added key: " << (void*)key.raw_(); - SIMPLE_ERROR("{}:{} There is a mismatch in _HashTableCount {} vs calcd {}\n", filename, line, ht->_HashTableCount, cnt); - } - } -} - #ifdef CLASP_THREADS struct HashTableReadLock { const HashTable_O* _hashTable; @@ -422,7 +360,6 @@ T_sp HashTable_O::clrhash() { T_sp no_key = ::no_key(); this->_Table.resize(0, KeyValuePair(no_key, no_key)); this->setup(16, this->_RehashSize, this->_RehashThreshold); - VERIFY_HASH_TABLE(this); return this->asSmartPtr(); } @@ -640,7 +577,6 @@ List_sp HashTable_O::keysAsCons() { } void HashTable_O::fields(Record_sp node) { - VERIFY_HASH_TABLE(this); // this->Base::fields(node); node->field(INTERN_(core, rehash_size), this->_RehashSize); node->/*pod_*/ field(INTERN_(core, rehash_threshold), this->_RehashThreshold); @@ -669,7 +605,6 @@ void HashTable_O::fields(Record_sp node) { IMPLEMENT_MEF("Add support to patch hash tables"); } break; } - VERIFY_HASH_TABLE(this); } uint HashTable_O::resizeEmptyTable_no_lock(size_t sz) { @@ -793,7 +728,6 @@ CL_DEFUN void core__hash_table_force_rehash(HashTable_sp ht) { T_mv HashTable_O::gethash(T_sp key, T_sp default_value) { LOG("gethash looking for key[{}]", _rep_(key)); HT_READ_LOCK(this); - VERIFY_HASH_TABLE(this); HashGenerator hg; size_t sz = this->_Table.size(); // #ifdef DEBUG_SLOW @@ -851,10 +785,8 @@ bool HashTable_O::remhash(T_sp key) { if (keyValuePair) { keyValuePair->_Key = deleted(); this->_HashTableCount--; - VERIFY_HASH_TABLE(this); return true; } - VERIFY_HASH_TABLE(this); return false; } @@ -904,7 +836,6 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { DEBUG_HASH_TABLE({ core::clasp_write_string(fmt::format("{}:{} After rplacd value: {}\n", __FILE__, __LINE__, _rep_(keyValuePair->_Value))); }); - VERIFY_HASH_TABLE(this); return value; } DEBUG_HASH_TABLE({ @@ -939,11 +870,9 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { entryP->_Value = value; this->_HashTableCount++; DEBUG_HASH_TABLE({ core::clasp_write_string(fmt::format("{}:{} Found empty slot at index = {}\n", __FILE__, __LINE__, write)); }); - VERIFY_HASH_TABLE_VA(this, write, key); if (this->_HashTableCount > this->_RehashThreshold * this->_Table.size()) { LOG("Expanding hash table"); this->rehash_no_lock(true); - VERIFY_HASH_TABLE(this); } return value; NO_ROOM: @@ -956,10 +885,7 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { printf("%s:%d There is absolutely no room in the hash-table _RehashThreshold = %lf - _HashTableCount -> %lu size -> %lu " "increasing size\n", __FILE__, __LINE__, this->_RehashThreshold, this->_HashTableCount, this->_Table.size()); - verifyHashTable(true, std::cerr, this, __FILE__, __LINE__); - printf("%s:%d ---- done verify\n", __FILE__, __LINE__); this->rehash_no_lock(true); - VERIFY_HASH_TABLE_VA(this, cur); return this->setf_gethash_no_write_lock(key, value); // ------------ // Here we add the key @@ -1029,7 +955,6 @@ void HashTable_O::rehash_no_lock(bool expandTable) { "%lu\n") % this->_HashTableId % this->_InitialSize % this->_RehashCount % newSize % oldHashTableCount % this->_HashTableCount); #endif - VERIFY_HASH_TABLE(this); } void HashTable_O::rehash(bool expandTable) { @@ -1076,7 +1001,6 @@ void dump_one_entry(HashTable_sp ht, size_t it, stringstream& ss, KeyValuePair& CL_DEFMETHOD string HashTable_O::hash_table_dump() { stringstream ss; HT_READ_LOCK(this); - verifyHashTable(true, ss, this, __FILE__, __LINE__); return ss.str(); } From f61fbb7041b4b2e32ac3d88fe5cae3094eade227 Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 14:28:27 -0500 Subject: [PATCH 08/39] privatize internal hash table functions --- include/clasp/core/hashTable.h | 8 ++++---- include/clasp/core/hashTableEq.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index daa84fd0c4..1ed799aded 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -125,7 +125,11 @@ class HashTable_O : public HashTableBase_O { uint calculateHashTableCount() const; void rehash_no_lock(bool expandTable); + T_sp setf_gethash_no_write_lock(T_sp key, T_sp value); +protected: + virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); + public: void rehash(bool expandTable); @@ -137,9 +141,6 @@ class HashTable_O : public HashTableBase_O { return nil(); }; -public: - virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); - public: // Functions here virtual bool equalp(T_sp other) const override; @@ -166,7 +167,6 @@ class HashTable_O : public HashTableBase_O { gc::Fixnum hashIndex(T_sp key) const; T_sp hash_table_setf_gethash(T_sp key, T_sp value) override; - T_sp setf_gethash_no_write_lock(T_sp key, T_sp value); void setf_gethash(T_sp key, T_sp val) { this->hash_table_setf_gethash(key, val); }; Number_sp rehash_size() const override; diff --git a/include/clasp/core/hashTableEq.h b/include/clasp/core/hashTableEq.h index 93d3763926..771204cafa 100644 --- a/include/clasp/core/hashTableEq.h +++ b/include/clasp/core/hashTableEq.h @@ -38,7 +38,7 @@ class HashTableEq_O : public HashTable_O { LISP_CLASS(core, CorePkg, HashTableEq_O, "HashTableEq", HashTable_O); DEFAULT_CTOR_DTOR(HashTableEq_O); -public: +protected: virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); public: static HashTableEq_sp create(uint sz, Number_sp rehashSize, double rehashThreshold); From 7b09d81d0e4e34e503f4df2ce60fdd94717feae2 Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 15:08:13 -0500 Subject: [PATCH 09/39] merge sxhash_ into sxhash_equal --- include/clasp/core/array.h | 3 --- include/clasp/core/array_bit.h | 4 ++-- include/clasp/core/bignum.h | 2 +- include/clasp/core/cons.h | 8 +++----- include/clasp/core/fileSystem.h | 2 +- include/clasp/core/numbers.h | 10 +++++----- include/clasp/core/object.h | 5 ++--- include/clasp/core/pathname.h | 1 - include/clasp/core/string.h | 6 +++--- include/clasp/core/symbol.h | 1 - src/core/array.cc | 5 ----- src/core/bignum.cc | 2 +- src/core/fileSystem.cc | 2 +- src/core/hashTable.cc | 34 +++++---------------------------- src/core/numbers.cc | 20 ++++++++----------- src/core/object.cc | 12 ++---------- src/core/pathname.cc | 15 --------------- src/core/symbol.cc | 14 +++----------- 18 files changed, 37 insertions(+), 109 deletions(-) diff --git a/include/clasp/core/array.h b/include/clasp/core/array.h index dc70769c36..42141fe8df 100644 --- a/include/clasp/core/array.h +++ b/include/clasp/core/array.h @@ -240,7 +240,6 @@ class Array_O : public General_O { return this->unsafe_setf_subseq(p.start, p.end, newVec); } void fillInitialContents(T_sp initialContents); - virtual void sxhash_(HashGenerator& hg) const override = 0; virtual void sxhash_equalp(HashGenerator& hg) const override; // -------------------------------------------------- // Ranged operations with explicit limits @@ -324,7 +323,6 @@ class MDArray_O : public Array_O { virtual size_t displacedIndexOffset() const override { return this->_DisplacedIndexOffset; } virtual bool arrayHasFillPointerP() const override { return this->_Flags.fillPointerP(); }; virtual T_sp replaceArray(T_sp other) override; - virtual void sxhash_(HashGenerator& hg) const override; void fillPointerSet(size_t idx) override { // This better not be bigger than the vector size (must be a vector) if (idx > this->_ArrayTotalSize) @@ -420,7 +418,6 @@ class AbstractSimpleVector_O : public Array_O { virtual void ranged_sxhash(HashGenerator& hg, size_t start, size_t end) const { TYPE_ERROR(this->asSmartPtr(), Cons_O::createList(cl::_sym_string, cl::_sym_bit_vector)); }; - virtual void sxhash_(HashGenerator& hg) const override { this->General_O::sxhash_(hg); } virtual bool equal(T_sp other) const override { return this->eq(other); }; virtual bool equalp(T_sp other) const override; void asAbstractSimpleVectorRange(AbstractSimpleVector_sp& sv, size_t& start, size_t& end) const override { diff --git a/include/clasp/core/array_bit.h b/include/clasp/core/array_bit.h index 5cb2140584..5418ea64d0 100644 --- a/include/clasp/core/array_bit.h +++ b/include/clasp/core/array_bit.h @@ -58,7 +58,7 @@ class SimpleBitVector_O : public specialized_SimpleBitVector { // for convenience if not speed virtual void __write__(T_sp strm) const override final; virtual bool equal(T_sp other) const final; - virtual void sxhash_(HashGenerator& hg) const final { this->ranged_sxhash(hg, 0, this->length()); } + virtual void sxhash_equal(HashGenerator& hg) const final { this->ranged_sxhash(hg, 0, this->length()); } virtual void ranged_sxhash(HashGenerator& hg, size_t start, size_t end) const final { if (hg.isFilling()) { Fixnum hash = 5381; @@ -100,7 +100,7 @@ class BitVectorNs_O : public template_Vectorcar()); - if (hg.isFilling()) - hg.hashObject(this->cdr()); + inline void sxhash_equal(HashGenerator& hg) const { + if (hg.isFilling()) hg.hashObject(this->car()); + if (hg.isFilling()) hg.hashObject(this->cdr()); } bool equal(T_sp obj) const; diff --git a/include/clasp/core/fileSystem.h b/include/clasp/core/fileSystem.h index d6436c59a8..b0763a6018 100644 --- a/include/clasp/core/fileSystem.h +++ b/include/clasp/core/fileSystem.h @@ -78,7 +78,7 @@ class Path_O : public General_O { void setPath(const std::filesystem::path& p); void setPathFromString(const string& path); - void sxhash_(HashGenerator& hg) const; + void sxhash_equal(HashGenerator& hg) const; Path_sp parent_path(); /*! Return just the fileName (*--end) as a string*/ diff --git a/include/clasp/core/numbers.h b/include/clasp/core/numbers.h index b32c123ce6..fac7d54fcb 100644 --- a/include/clasp/core/numbers.h +++ b/include/clasp/core/numbers.h @@ -217,7 +217,7 @@ class Number_O : public General_O { virtual Number_sp cosh_() const { SUBIMP(); }; virtual Number_sp tanh_() const { SUBIMP(); }; - virtual void sxhash_(HashGenerator& hg) const override { SUBIMP(); }; + virtual void sxhash_equal(HashGenerator& hg) const override { SUBIMP(); }; inline static bool zerop(Number_sp x) { if (x.fixnump()) @@ -592,7 +592,7 @@ class DoubleFloat_O : public Float_O { static DoubleFloat_sp coerce(Number_sp x); - void sxhash_(HashGenerator& hg) const override; + void sxhash_equal(HashGenerator& hg) const override; // virtual Number_sp copy() const; string __repr__() const override; void set(double val) { this->_Value = val; }; @@ -682,7 +682,7 @@ class LongFloat_O : public Float_O { static LongFloat_sp coerce(Number_sp x); - void sxhash_(HashGenerator& hg) const override; + void sxhash_equal(HashGenerator& hg) const override; string __repr__() const override; void set(long_float_t val) { this->_Value = val; }; long_float_t get() const { return this->_Value; }; @@ -771,7 +771,7 @@ class Complex_O : public Number_O { Real_sp real() const { return this->_real; }; Real_sp imaginary() const { return this->_imaginary; }; - void sxhash_(HashGenerator& hg) const override; + void sxhash_equal(HashGenerator& hg) const override; // virtual Number_sp copy() const; string __repr__() const override; @@ -862,7 +862,7 @@ class Ratio_O : public Rational_O { Integer_sp numerator() const { return this->_numerator; }; Integer_sp denominator() const { return this->_denominator; }; - void sxhash_(HashGenerator& hg) const override; + void sxhash_equal(HashGenerator& hg) const override; // virtual Number_sp copy() const; string __repr__() const override; Number_sp signum_() const override; diff --git a/include/clasp/core/object.h b/include/clasp/core/object.h index b2ee6abe8e..61495a8492 100644 --- a/include/clasp/core/object.h +++ b/include/clasp/core/object.h @@ -376,7 +376,6 @@ class General_O : public T_O { LISP_CLASS(core, CorePkg, General_O, "General", T_O); public: - virtual void sxhash_(HashGenerator& hg) const; virtual void sxhash_equal(HashGenerator& hg) const; virtual void sxhash_equalp(HashGenerator& hg) const { return this->sxhash_equal(hg); }; @@ -564,11 +563,11 @@ inline void clasp_sxhash(T_sp obj, HashGenerator& hg) { return; } else if (obj.consp()) { Cons_O* cons = obj.unsafe_cons(); - cons->sxhash_(hg); + cons->sxhash_equal(hg); return; } else if (obj.generalp()) { General_O* general = obj.unsafe_general(); - general->sxhash_(hg); + general->sxhash_equal(hg); return; } SIMPLE_ERROR("Handle sxhash_ for object"); diff --git a/include/clasp/core/pathname.h b/include/clasp/core/pathname.h index 5b65df0825..36e6dbae70 100644 --- a/include/clasp/core/pathname.h +++ b/include/clasp/core/pathname.h @@ -125,7 +125,6 @@ class Pathname_O : public General_O { virtual bool equal(T_sp obj) const; virtual bool equalp(T_sp obj) const { return this->equal(obj); }; - virtual void sxhash_(HashGenerator& hg) const; virtual void sxhash_equal(HashGenerator& hg) const; virtual void sxhash_equalp(HashGenerator& hg) const; diff --git a/include/clasp/core/string.h b/include/clasp/core/string.h index 82ae1aafac..7b21c3ac9f 100644 --- a/include/clasp/core/string.h +++ b/include/clasp/core/string.h @@ -104,7 +104,7 @@ class SimpleBaseString_O : public specialized_SimpleBaseString { }; virtual std::string get_path_string() const final { return get_std_string(); } virtual std::string __repr__() const override; - virtual void sxhash_(HashGenerator& hg) const final { this->ranged_sxhash(hg, 0, this->length()); } + virtual void sxhash_equal(HashGenerator& hg) const final { this->ranged_sxhash(hg, 0, this->length()); } virtual void ranged_sxhash(HashGenerator& hg, size_t start, size_t end) const final { if (hg.isFilling()) { Fixnum hash = 5381; @@ -190,7 +190,7 @@ class SimpleCharacterString_O : public specialized_SimpleCharacterString { virtual std::string __repr__() const final; public: - virtual void sxhash_(HashGenerator& hg) const override { this->ranged_sxhash(hg, 0, this->length()); } + virtual void sxhash_equal(HashGenerator& hg) const override { this->ranged_sxhash(hg, 0, this->length()); } virtual void ranged_sxhash(HashGenerator& hg, size_t start, size_t end) const override { if (hg.isFilling()) { Fixnum hash = 5381; @@ -213,7 +213,7 @@ class StrNs_O : public ComplexVector_O { : Base(dimension, fillPointer, data, displacedToP, displacedIndexOffset){}; public: - virtual void sxhash_(HashGenerator& hg) const final { + virtual void sxhash_equal(HashGenerator& hg) const final { AbstractSimpleVector_sp svec; size_t start, end; this->asAbstractSimpleVectorRange(svec, start, end); diff --git a/include/clasp/core/symbol.h b/include/clasp/core/symbol.h index 3ffbc475dd..a4f608b98e 100644 --- a/include/clasp/core/symbol.h +++ b/include/clasp/core/symbol.h @@ -281,7 +281,6 @@ class Symbol_O : public General_O { void setf_specialP(bool m) { setFlag(m, IS_SPECIAL); } void makeSpecial(); // TODO: Redundant, remove? public: // Hashing - void sxhash_(HashGenerator& hg) const override; void sxhash_equal(HashGenerator& hg) const override; void sxhash_equalp(HashGenerator& hg) const override { this->sxhash_equal(hg); }; diff --git a/src/core/array.cc b/src/core/array.cc index 546b536868..9305451e5d 100644 --- a/src/core/array.cc +++ b/src/core/array.cc @@ -330,11 +330,6 @@ T_sp MDArray_O::replaceArray(T_sp other) { void MDArray_O::set_data(Array_sp a) { this->_Data = a; } -void MDArray_O::sxhash_(HashGenerator& hg) const { - // Just to get it working. FIXME - this->General_O::sxhash_(hg); -} - Array_sp MDArray_O::unsafe_subseq(size_t start, size_t iend) const { return this->_Data->unsafe_subseq(start + this->_DisplacedIndexOffset, iend + this->_DisplacedIndexOffset); } diff --git a/src/core/bignum.cc b/src/core/bignum.cc index 70419d8d3a..2a22c8671e 100644 --- a/src/core/bignum.cc +++ b/src/core/bignum.cc @@ -54,7 +54,7 @@ Bignum_sp Bignum_O::create(const mpz_class& c) { return create_from_limbs(len, 0, false, count, dest); } -void Bignum_O::sxhash_(HashGenerator& hg) const { +void Bignum_O::sxhash_equal(HashGenerator& hg) const { mp_size_t len = this->length(); if (!(hg.addValue(len))) return; diff --git a/src/core/fileSystem.cc b/src/core/fileSystem.cc index 9be50b8b79..52948154fc 100644 --- a/src/core/fileSystem.cc +++ b/src/core/fileSystem.cc @@ -142,7 +142,7 @@ Path_mv af_makePath(List_sp args) { return (Values(me)); } -void Path_O::sxhash_(HashGenerator& hg) const { +void Path_O::sxhash_equal(HashGenerator& hg) const { string ts = this->_Path._value.string(); for (char const& c : ts) diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 12594ff748..03efced01a 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -469,43 +469,19 @@ void HashTable_O::sxhash_eql(Hash1Generator& hg, T_sp obj) { void HashTable_O::sxhash_equal(HashGenerator& hg, T_sp obj) { if (obj.fixnump()) { - if (hg.isFilling()) - hg.addValue(obj.unsafe_fixnum()); - return; + if (hg.isFilling()) hg.addValue(obj.unsafe_fixnum()); } else if (obj.single_floatp()) { - if (hg.isFilling()) { + if (hg.isFilling()) hg.addValue(float_convert::float_to_bits(obj.unsafe_single_float())); - } - return; } else if (obj.characterp()) { - if (hg.isFilling()) - hg.addValue(obj.unsafe_character()); - return; + if (hg.isFilling()) hg.addValue(obj.unsafe_character()); } else if (obj.consp()) { Cons_sp cobj = gc::As_unsafe(obj); - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, CONS_CAR(cobj)); - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, CONS_CDR(cobj)); - return; + cobj->sxhash_equal(hg); } else if (obj.generalp()) { - if (cl__numberp(obj)) { - hg.hashObject(obj); - return; - } else if (String_sp str_obj = obj.asOrNull()) { - if (hg.isFilling()) - str_obj->sxhash_(hg); - return; - } else if (BitVector_sp bv_obj = obj.asOrNull()) { - if (hg.isFilling()) - bv_obj->sxhash_(hg); - return; - } General_sp gobj = gc::As_unsafe(obj); gobj->sxhash_equal(hg); - return; - } - SIMPLE_ERROR("You cannot EQUAL hash on {}", _rep_(obj)); + } else SIMPLE_ERROR("You cannot EQUAL hash on {}", _rep_(obj)); } void HashTable_O::sxhash_equalp(HashGenerator& hg, T_sp obj) { diff --git a/src/core/numbers.cc b/src/core/numbers.cc index 3c88621c38..9a1000711b 100644 --- a/src/core/numbers.cc +++ b/src/core/numbers.cc @@ -1230,7 +1230,7 @@ CL_DEFMETHOD Integer_sp DoubleFloat_O::castToInteger() const { Number_sp DoubleFloat_O::signum_() const { return create(_signum(_Value)); } -void DoubleFloat_O::sxhash_(HashGenerator& hg) const { +void DoubleFloat_O::sxhash_equal(HashGenerator& hg) const { hg.addValue((std::fpclassify(this->_Value) == FP_ZERO) ? 0u : float_convert::float_to_bits(this->_Value)); } @@ -1277,7 +1277,7 @@ CL_DEFMETHOD Integer_sp LongFloat_O::castToInteger() const { Number_sp LongFloat_O::reciprocal_() const { return LongFloat_O::create(long_float_t{1.0} / this->_Value); } -void LongFloat_O::sxhash_(HashGenerator& hg) const { +void LongFloat_O::sxhash_equal(HashGenerator& hg) const { hg.addValue((std::fpclassify(this->_Value) == FP_ZERO) ? 0u : float_convert::float_to_bits(this->_Value)); } @@ -1389,11 +1389,9 @@ bool Ratio_O::eql_(T_sp obj) const { } return false; } -void Ratio_O::sxhash_(HashGenerator& hg) const { - if (hg.isFilling()) - hg.hashObject(this->_numerator); - if (hg.isFilling()) - hg.hashObject(this->_denominator); +void Ratio_O::sxhash_equal(HashGenerator& hg) const { + if (hg.isFilling()) hg.hashObject(this->_numerator); + if (hg.isFilling()) hg.hashObject(this->_denominator); } Number_sp Ratio_O::signum_() const { @@ -1467,11 +1465,9 @@ string Complex_O::__repr__() const { return ss.str(); } -void Complex_O::sxhash_(HashGenerator& hg) const { - if (hg.isFilling()) - hg.hashObject(this->_real); - if (hg.isFilling()) - hg.hashObject(this->_imaginary); +void Complex_O::sxhash_equal(HashGenerator& hg) const { + if (hg.isFilling()) hg.hashObject(this->_real); + if (hg.isFilling()) hg.hashObject(this->_imaginary); } bool Complex_O::eql_(T_sp o) const { diff --git a/src/core/object.cc b/src/core/object.cc index 9e84c29b4c..9c9672aeed 100644 --- a/src/core/object.cc +++ b/src/core/object.cc @@ -373,17 +373,9 @@ string General_O::className() const { return this->__class()->_classNameAsString(); } -void General_O::sxhash_(HashGenerator& hg) const { - if (hg.isFilling()) { - hg.addGeneralAddress(this->asSmartPtr()); - } -} - void General_O::sxhash_equal(HashGenerator& hg) const { - if (!hg.isFilling()) - return; - hg.addGeneralAddress(this->asSmartPtr()); - return; + if (hg.isFilling()) + hg.addGeneralAddress(this->asSmartPtr()); } bool General_O::eql_(T_sp obj) const { return this->eq(obj); } diff --git a/src/core/pathname.cc b/src/core/pathname.cc index 2f2a1e06b1..346a98597a 100644 --- a/src/core/pathname.cc +++ b/src/core/pathname.cc @@ -415,21 +415,6 @@ bool Pathname_O::equal(T_sp obj) const { return false; } -void Pathname_O::sxhash_(HashGenerator& hg) const { - if (hg.isFilling()) - hg.hashObject(this->_Host); - if (hg.isFilling()) - hg.hashObject(this->_Device); - if (hg.isFilling()) - hg.hashObject(this->_Directory); - if (hg.isFilling()) - hg.hashObject(this->_Name); - if (hg.isFilling()) - hg.hashObject(this->_Type); - if (hg.isFilling()) - hg.hashObject(this->_Version); -} - void Pathname_O::sxhash_equal(HashGenerator& hg) const { if (hg.isFilling()) HashTable_O::sxhash_equal(hg, this->_Host); diff --git a/src/core/symbol.cc b/src/core/symbol.cc index db3e891666..5a0233dd27 100644 --- a/src/core/symbol.cc +++ b/src/core/symbol.cc @@ -411,21 +411,13 @@ void Symbol_O::fmakunbound_setf() { void Symbol_O::setf_symbolFunction(Function_sp fn) { ensureFunctionCell(fn)->real_function_set(fn); } -void Symbol_O::sxhash_(HashGenerator& hg) const { +void Symbol_O::sxhash_equal(HashGenerator& hg) const { // clhs 18.2.14 sxhash // Although similarity is defined for symbols in terms of both the symbol's name and the packages // in which the symbol is accessible, item 3 disallows using package information to compute the hash // code, since changes to the package status of a symbol are not visible to equal. - // if (hg.isFilling()) this->getPackage().unsafe_general()->sxhash_(hg); - if (hg.isFilling()) - this->_Name->sxhash_(hg); -} - -void Symbol_O::sxhash_equal(HashGenerator& hg) const { - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, this->getPackage()); - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, this->_Name); + // if (hg.isFilling()) this->getPackage().unsafe_general()->sxhash_equal(hg); + if (hg.isFilling()) this->_Name->sxhash_equal(hg); } Symbol_sp Symbol_O::copy_symbol(T_sp copy_properties) const { From 81ad3e559b2041f5f168ad54e8984ea8ce6c7145 Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 18:26:27 -0500 Subject: [PATCH 10/39] reorganize sxhash the sxhashKey deferring to static functions in HashTable_O thing has been bugging me for years. begone. Also moves hash stuff out of HashTable_O which is nice for organization. Another bonus: equalp hash on a string no longer conses. I hadn't realized it consed. --- include/clasp/core/character.fwd.h | 2 + include/clasp/core/character.h | 2 - include/clasp/core/cons.h | 4 + include/clasp/core/hashTable.h | 11 +- include/clasp/core/hashTableCustom.h | 2 +- include/clasp/core/hashTableEq.h | 5 +- include/clasp/core/hashTableEql.h | 2 +- include/clasp/core/hashTableEqual.h | 2 +- include/clasp/core/hashTableEqualp.h | 2 +- include/clasp/core/object.h | 10 ++ include/clasp/core/string.h | 29 ++++ src/core/array.cc | 6 +- src/core/hashTable.cc | 224 ++------------------------- src/core/hashTableCustom.cc | 4 +- src/core/hashTableEq.cc | 7 +- src/core/hashTableEql.cc | 14 +- src/core/hashTableEqual.cc | 5 +- src/core/hashTableEqualp.cc | 5 +- src/core/instance.cc | 16 +- src/core/object.cc | 6 + src/core/pathname.cc | 36 ++--- src/lisp/kernel/lsp/predlib.lisp | 5 +- 22 files changed, 120 insertions(+), 279 deletions(-) diff --git a/include/clasp/core/character.fwd.h b/include/clasp/core/character.fwd.h index 9d8cd33370..c56c57bf0a 100644 --- a/include/clasp/core/character.fwd.h +++ b/include/clasp/core/character.fwd.h @@ -42,4 +42,6 @@ inline Character_sp clasp_make_character(claspCharacter c) { return gc::make_tag inline claspCharacter clasp_as_claspCharacter(Character_sp c) { return c.unsafe_character(); } +claspCharacter char_upcase(claspCharacter); + } // namespace core diff --git a/include/clasp/core/character.h b/include/clasp/core/character.h index 265c7542cc..4c93411fab 100644 --- a/include/clasp/core/character.h +++ b/include/clasp/core/character.h @@ -111,8 +111,6 @@ namespace core { inline bool clasp_invalid_base_char_p(claspCharacter c) { return (c <= 32) || (c == 127); } -claspCharacter char_upcase(claspCharacter code); - claspCharacter char_downcase(claspCharacter code); // See character.fwd.h for the following diff --git a/include/clasp/core/cons.h b/include/clasp/core/cons.h index e65f0870ad..13881f65d8 100644 --- a/include/clasp/core/cons.h +++ b/include/clasp/core/cons.h @@ -253,6 +253,10 @@ class Cons_O : public T_O { if (hg.isFilling()) hg.hashObject(this->car()); if (hg.isFilling()) hg.hashObject(this->cdr()); } + inline void sxhash_equalp(HashGenerator& hg) const { + if (hg.isFilling()) hg.hashObjectEqualp(this->car()); + if (hg.isFilling()) hg.hashObjectEqualp(this->cdr()); + } bool equal(T_sp obj) const; bool equalp(T_sp obj) const; diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index 1ed799aded..d490ed1bb5 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -110,12 +110,6 @@ class HashTable_O : public HashTableBase_O { SimpleBaseString_sp writeLockName); // set everything up with defaults public: - static void sxhash_eq(Hash1Generator& running_hash, T_sp obj); - static void sxhash_eql(Hash1Generator& running_hash, T_sp obj); - static void sxhash_eq(HashGenerator& running_hash, T_sp obj); - static void sxhash_eql(HashGenerator& running_hash, T_sp obj); - static void sxhash_equal(HashGenerator& running_hash, T_sp obj); - static void sxhash_equalp(HashGenerator& running_hash, T_sp obj); void setupThreadSafeHashTable(); void setupDebug(); @@ -126,10 +120,12 @@ class HashTable_O : public HashTableBase_O { void rehash_no_lock(bool expandTable); T_sp setf_gethash_no_write_lock(T_sp key, T_sp value); + gc::Fixnum sxhashKey(T_sp key) const; // NOTE: Only call with (read) lock held protected: virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); - + virtual void sxhashEffect(T_sp key, HashGenerator& hg) const { SUBIMP() }; + public: void rehash(bool expandTable); @@ -154,7 +150,6 @@ class HashTable_O : public HashTableBase_O { T_sp operator[](const std::string& key); - virtual gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, HashGenerator& hg) const; virtual bool keyTest(T_sp entryKey, T_sp searchKey) const; /*! Return true if the key is within the hash table */ diff --git a/include/clasp/core/hashTableCustom.h b/include/clasp/core/hashTableCustom.h index 867f58246c..709e33d65e 100644 --- a/include/clasp/core/hashTableCustom.h +++ b/include/clasp/core/hashTableCustom.h @@ -51,7 +51,7 @@ class HashTableCustom_O : public HashTable_O { bool keyTest(T_sp entryKey, T_sp searchKey) const; - gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, HashGenerator& hg) const; + void sxhashEffect(T_sp key, HashGenerator& hg) const; }; }; // namespace core diff --git a/include/clasp/core/hashTableEq.h b/include/clasp/core/hashTableEq.h index 771204cafa..b67c570d85 100644 --- a/include/clasp/core/hashTableEq.h +++ b/include/clasp/core/hashTableEq.h @@ -45,14 +45,11 @@ class HashTableEq_O : public HashTable_O { static HashTableEq_sp create_default(); static HashTableEq_sp createFromPList(List_sp plist, Symbol_sp nilTerminatedValidKeywords[]); -public: - static int sxhash_eq(T_sp obj); - public: // Functions here virtual T_sp hashTableTest() const { return cl::_sym_eq; }; bool keyTest(T_sp entryKey, T_sp searchKey) const; - gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, HashGenerator& hg) const; + void sxhashEffect(T_sp key, HashGenerator& hg) const; }; }; // namespace core diff --git a/include/clasp/core/hashTableEql.h b/include/clasp/core/hashTableEql.h index f9be0bbf67..4ab88833b8 100644 --- a/include/clasp/core/hashTableEql.h +++ b/include/clasp/core/hashTableEql.h @@ -50,7 +50,7 @@ class HashTableEql_O : public HashTable_O { bool keyTest(T_sp entryKey, T_sp searchKey) const; - gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, HashGenerator& hg) const; + void sxhashEffect(T_sp key, HashGenerator& hg) const; }; }; // namespace core diff --git a/include/clasp/core/hashTableEqual.h b/include/clasp/core/hashTableEqual.h index 352c23e000..7a3345177b 100644 --- a/include/clasp/core/hashTableEqual.h +++ b/include/clasp/core/hashTableEqual.h @@ -48,7 +48,7 @@ class HashTableEqual_O : public HashTable_O { bool keyTest(T_sp entryKey, T_sp searchKey) const; - gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, HashGenerator& hg) const; + void sxhashEffect(T_sp key, HashGenerator& hg) const; }; }; // namespace core diff --git a/include/clasp/core/hashTableEqualp.h b/include/clasp/core/hashTableEqualp.h index 292ea49ece..9d25aeb5b4 100644 --- a/include/clasp/core/hashTableEqualp.h +++ b/include/clasp/core/hashTableEqualp.h @@ -49,7 +49,7 @@ class HashTableEqualp_O : public HashTable_O { bool keyTest(T_sp entryKey, T_sp searchKey) const; - gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, HashGenerator& hg) const; + void sxhashEffect(T_sp key, HashGenerator& hg) const; }; }; // namespace core diff --git a/include/clasp/core/object.h b/include/clasp/core/object.h index 61495a8492..a6359407b3 100644 --- a/include/clasp/core/object.h +++ b/include/clasp/core/object.h @@ -267,6 +267,7 @@ class HashGenerator : public HashGeneratorBase { } void hashObject(T_sp obj); + void hashObjectEqualp(T_sp obj); }; }; // namespace core @@ -592,6 +593,15 @@ inline void clasp_sxhash(T_sp obj, Hash1Generator& hg) { } SIMPLE_ERROR("Handle sxhash_ for object"); }; + +claspCharacter char_upcase(claspCharacter); // FIXME: bad location +inline void clasp_sxhash_equalp(T_sp obj, HashGenerator& hg) { + if (obj.consp()) obj.as_unsafe()->sxhash_equalp(hg); + else if (obj.generalp()) obj.as_unsafe()->sxhash_equalp(hg); + else if (obj.characterp()) // fold case + hg.addValue(char_upcase(obj.unsafe_character())); + else clasp_sxhash(obj, hg); +} }; // namespace core namespace core { diff --git a/include/clasp/core/string.h b/include/clasp/core/string.h index 7b21c3ac9f..9821efffac 100644 --- a/include/clasp/core/string.h +++ b/include/clasp/core/string.h @@ -115,6 +115,14 @@ class SimpleBaseString_O : public specialized_SimpleBaseString { hg.addValue(hash); } } + virtual void sxhash_equalp(HashGenerator& hg) const final { + if (hg.isFilling()) { + Fixnum hash = 5381; + for (const auto& c : *this) + hash = ((hash << 5) + hash) + char_upcase(c); + hg.addValue(hash); + } + } }; }; // namespace core @@ -201,6 +209,13 @@ class SimpleCharacterString_O : public specialized_SimpleCharacterString { hg.addValue(hash); } } + virtual void sxhash_equalp(HashGenerator& hg) const final { + if (hg.isFilling()) { + Fixnum hash = 5381; + for (const auto& c : *this) hash = ((hash << 5) + hash) + char_upcase(c); + hg.addValue(hash); + } + } }; }; // namespace core @@ -298,6 +313,13 @@ class Str8Ns_O : public template_Vector { public: // Str8Ns specific functions virtual SimpleString_sp asMinimalSimpleString() const final; + virtual void sxhash_equalp(HashGenerator& hg) const final { + if (hg.isFilling()) { + Fixnum hash = 5381; + for (const auto& c : *this) hash = ((hash << 5) + hash) + char_upcase(c); + hg.addValue(hash); + } + } }; }; // namespace core @@ -364,6 +386,13 @@ class StrWNs_O : public template_Vectorlength(); ++i) { - if (!hg.isFilling()) - break; - T_sp obj = this->rowMajorAref(i); - HashTable_O::sxhash_equalp(hg, obj); + if (!hg.isFilling()) break; + clasp_sxhash_equalp(this->rowMajorAref(i), hg); } } diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 03efced01a..fb905f90e3 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -306,20 +306,6 @@ CL_DEFUN bool core__hash_table_entry_deleted_p(T_sp cons) { return oCdr(gc::As(cons)).no_keyp(); }; -CL_LAMBDA(&rest args); -CL_DECLARE(); -CL_DOCSTRING(R"dx(hash_eql generates an eql hash for a list of objects)dx"); -DOCGROUP(clasp); -CL_DEFUN Fixnum core__hash_eql(List_sp args) { - HashGenerator hg; - for (auto cur : args) { - HashTable_O::sxhash_eql(hg, oCar(cur)); - if (!hg.isFilling()) - break; - } - return hg.rawhash(); -}; - CL_LAMBDA(&rest args); CL_DECLARE(); CL_DOCSTRING(R"dx(hash_equal generates an equal hash for a list of objects)dx"); @@ -327,9 +313,8 @@ DOCGROUP(clasp); CL_DEFUN Fixnum core__hash_equal(List_sp args) { HashGenerator hg; for (auto cur : args) { - HashTable_O::sxhash_equal(hg, oCar(cur)); - if (hg.isFull()) - break; + clasp_sxhash(oCar(cur), hg); + if (hg.isFull()) break; } return hg.rawhash(); }; @@ -341,9 +326,8 @@ DOCGROUP(clasp); CL_DEFUN Fixnum core__hash_equalp(List_sp args) { HashGenerator hg; for (auto cur : args) { - HashTable_O::sxhash_equalp(hg, oCar(cur)); - if (hg.isFull()) - break; + clasp_sxhash_equalp(oCar(cur), hg); + if (hg.isFull()) break; } return hg.rawhash(); }; @@ -376,153 +360,6 @@ void HashTable_O::setup(uint sz, Number_sp rehashSize, double rehashThreshold) { this->_RehashThreshold = maybeFixRehashThreshold(rehashThreshold); } -void HashTable_O::sxhash_eq(HashGenerator& hg, T_sp obj) { - if (obj.generalp()) { - hg.addGeneralAddress(gc::As_unsafe(obj)); - return; - } else if (obj.consp()) { - hg.addConsAddress(gc::As_unsafe(obj)); - return; - } else { - hg.addValue((uintptr_t)obj.raw_()); - } -} - -void HashTable_O::sxhash_eq(Hash1Generator& hg, T_sp obj) { - if (obj.generalp()) { - hg.addGeneralAddress(gc::As_unsafe(obj)); - return; - } else if (obj.consp()) { - hg.addConsAddress(gc::As_unsafe(obj)); - return; - } else { - hg.addValue((uintptr_t)obj.raw_()); - } -} - -void HashTable_O::sxhash_eql(HashGenerator& hg, T_sp obj) { - uintptr_t tag = (uintptr_t)gctools::ptag(obj.raw_()); - switch (tag) { - case gctools::fixnum00_tag: - case gctools::fixnum01_tag: -#if TAG_BITS == 4 - case gctools::fixnum10_tag: - case gctools::fixnum11_tag: -#endif - { - hg.addValue0(obj.unsafe_fixnum()); - return; - } - case gctools::single_float_tag: { - hg.addValue0(float_convert::float_to_bits(obj.unsafe_single_float())); - return; - } - case gctools::character_tag: { - hg.addValue0(obj.unsafe_character()); - return; - } - case gctools::general_tag: { - if (cl__numberp(obj)) { - hg.hashObject(obj); - return; - } - hg.addGeneralAddress(gc::As_unsafe(obj)); - return; - } - case gctools::cons_tag: { - hg.addConsAddress(gc::As_unsafe(obj)); - return; - } - default: - break; - } - SIMPLE_ERROR("Illegal object (object.raw_() = {}) for eql hash {} tag = {}", (void*)obj.raw_(), _rep_(obj), tag); -} - -void HashTable_O::sxhash_eql(Hash1Generator& hg, T_sp obj) { - if (obj.fixnump()) { - if (hg.isFilling()) - hg.addValue(obj.unsafe_fixnum()); - return; - } else if (obj.single_floatp()) { - if (hg.isFilling()) { - hg.addValue(float_convert::float_to_bits(obj.unsafe_single_float())); - } - return; - } else if (obj.characterp()) { - if (hg.isFilling()) - hg.addValue(obj.unsafe_character()); - return; - } else if (obj.generalp()) { - if (gc::IsA(obj)) { - hg.hashObject(obj); - return; - } - hg.addGeneralAddress(gc::As_unsafe(obj)); - return; - } else if (obj.consp()) { - hg.addConsAddress(gc::As_unsafe(obj)); - return; - } - SIMPLE_ERROR("Illegal object for eql hash {}", _rep_(obj)); -} - -void HashTable_O::sxhash_equal(HashGenerator& hg, T_sp obj) { - if (obj.fixnump()) { - if (hg.isFilling()) hg.addValue(obj.unsafe_fixnum()); - } else if (obj.single_floatp()) { - if (hg.isFilling()) - hg.addValue(float_convert::float_to_bits(obj.unsafe_single_float())); - } else if (obj.characterp()) { - if (hg.isFilling()) hg.addValue(obj.unsafe_character()); - } else if (obj.consp()) { - Cons_sp cobj = gc::As_unsafe(obj); - cobj->sxhash_equal(hg); - } else if (obj.generalp()) { - General_sp gobj = gc::As_unsafe(obj); - gobj->sxhash_equal(hg); - } else SIMPLE_ERROR("You cannot EQUAL hash on {}", _rep_(obj)); -} - -void HashTable_O::sxhash_equalp(HashGenerator& hg, T_sp obj) { - if (obj.fixnump()) { - if (hg.isFilling()) - hg.addValue(obj.unsafe_fixnum()); - return; - } else if (obj.single_floatp()) { - if (hg.isFilling()) { - float value = obj.unsafe_single_float(); - hg.addValue((std::fpclassify(value) == FP_ZERO) ? 0u : float_convert::float_to_bits(value)); - } - return; - } else if (obj.characterp()) { - if (hg.isFilling()) - hg.addValue(char_upcase(clasp_as_claspCharacter(gc::As(obj)))); - return; - } else if (obj.consp()) { - Cons_sp cobj = gc::As_unsafe(obj); - if (hg.isFilling()) - HashTable_O::sxhash_equalp(hg, CONS_CAR(cobj)); - if (hg.isFilling()) - HashTable_O::sxhash_equalp(hg, CONS_CDR(cobj)); - return; - } else if (obj.generalp()) { - if (cl__numberp(obj)) { - if (hg.isFilling()) - hg.hashObject(obj); - return; - } else if (cl__stringp(obj)) { - SimpleString_sp upstr = cl__string_upcase(obj); - hg.hashObject(upstr); - return; - } - General_sp gobj = gc::As_unsafe(obj); - gobj->sxhash_equalp(hg); - return; - } - SIMPLE_ERROR("You cannot EQUALP hash on {}", _rep_(obj)); -} - bool HashTable_O::equalp(T_sp other) const { if (this == &(*other)) return true; @@ -637,7 +474,13 @@ size_t HashTable_O::hashTableSize() const { bool HashTable_O::keyTest(T_sp entryKey, T_sp searchKey) const { SUBCLASS_MUST_IMPLEMENT(); } -gc::Fixnum HashTable_O::sxhashKey(T_sp obj, gc::Fixnum bound, HashGenerator& hg) const { SUBCLASS_MUST_IMPLEMENT(); } +gc::Fixnum HashTable_O::sxhashKey(T_sp obj) const { + HashGenerator hg; + this->sxhashEffect(obj, hg); + // We don't use hashTableSize() here because sxhashKey is only called while + // the table is already locked. + return hg.hashBound(this->_Table.size()); +} CL_LAMBDA(key hash-table &optional default-value); CL_DOCSTRING(R"dx(gethash)dx"); @@ -704,16 +547,7 @@ CL_DEFUN void core__hash_table_force_rehash(HashTable_sp ht) { T_mv HashTable_O::gethash(T_sp key, T_sp default_value) { LOG("gethash looking for key[{}]", _rep_(key)); HT_READ_LOCK(this); - HashGenerator hg; - size_t sz = this->_Table.size(); - // #ifdef DEBUG_SLOW - if (sz == 0) { - printf("%s:%d:%s hash-table @%p table @%p size is zero\n", __FILE__, __LINE__, __FUNCTION__, this, - this->_Table._Vector._Contents.raw_()); - gctools::wait_for_user_signal("bad hash-table"); - } - // #endif - cl_index index = this->sxhashKey(key, sz, hg); + cl_index index = this->sxhashKey(key); KeyValuePair* keyValuePair = this->searchTable_no_read_lock(key, index); LOG("Found keyValueCons"); // % keyValueCons->__repr__() ); INFINITE-LOOP if (keyValuePair) { @@ -730,15 +564,12 @@ T_mv HashTable_O::gethash(T_sp key, T_sp default_value) { CL_LISPIFY_NAME("core:hashIndex"); CL_DEFMETHOD gc::Fixnum HashTable_O::hashIndex(T_sp key) const { - HashGenerator hg; - gc::Fixnum idx = this->sxhashKey(key, this->_Table.size(), hg); - return idx; + return this->sxhashKey(key); } KeyValuePair* HashTable_O::find(T_sp key) { HT_READ_LOCK(this); - HashGenerator hg; - cl_index index = this->sxhashKey(key, this->_Table.size(), hg); + cl_index index = this->sxhashKey(key); KeyValuePair* keyValue = this->searchTable_no_read_lock(key, index); if (!keyValue) return keyValue; @@ -755,8 +586,7 @@ bool HashTable_O::contains(T_sp key) { bool HashTable_O::remhash(T_sp key) { HT_WRITE_LOCK(this); - HashGenerator hg; - cl_index index = this->sxhashKey(key, this->_Table.size(), hg); + cl_index index = this->sxhashKey(key); KeyValuePair* keyValuePair = this->searchTable_no_read_lock(key, index); if (keyValuePair) { keyValuePair->_Key = deleted(); @@ -774,25 +604,8 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { if (key.no_keyp()) { SIMPLE_ERROR("Do not use {} as a key!!", _rep_(key)); } -#ifdef DEBUG_HASH_TABLE_DEBUG - HashGenerator hg(this->_Debug); -#else - HashGenerator hg; -#endif - cl_index index = this->sxhashKey(key, this->_Table.size(), hg); -#ifdef DEBUG_HASH_TABLE_DEBUG - if (this->_Debug) { - core::T_sp info = Cons_O::createList(INTERN_(kw, setf_gethash), Cons_O::create(key, value), INTERN_(kw, index), - make_fixnum(index), INTERN_(kw, generator), hg.asList()); - T_sp expected; - Cons_sp cell = core::Cons_O::create(info, nil()); - do { - expected = this->_History.load(); - cell->rplacd(expected); - } while (!this->_History.compare_exchange_weak(expected, cell)); - } -#endif + cl_index index = this->sxhashKey(key); DEBUG_HASH_TABLE({ core::clasp_write_string(fmt::format("{}:{}:{} index = {} this->_Table.size() = {}\n", __FILE__, __LINE__, __FUNCTION__, index, this->_Table.size())); @@ -832,14 +645,11 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { goto NO_ROOM; ADD_KEY_VALUE: DEBUG_HASH_TABLE1({ - HashGenerator hg2(this->_Debug); - cl_index index2 = this->sxhashKey(key, this->_Table.size(), hg2); + cl_index index2 = this->sxhashKey(key); if (index2 != index) { lisp_write(fmt::format("{}:{}:{} INDEX mismatch!!! key = {} badge = {} index = {} write = {} index2 = {} size = {}\n", __FILE__, __LINE__, __FUNCTION__, _rep_(key), lisp_general_badge(gc::As_unsafe(key)), index, write, index2, this->_Table.size())); - lisp_write(fmt::format("{} hg -> {}\n", CPP_SOURCE(), hg.asString())); - lisp_write(fmt::format("{} hg2 -> {}\n", CPP_SOURCE(), hg2.asString())); } }); entryP->_Key = key; diff --git a/src/core/hashTableCustom.cc b/src/core/hashTableCustom.cc index a10aee1ccf..55bfe582cb 100644 --- a/src/core/hashTableCustom.cc +++ b/src/core/hashTableCustom.cc @@ -51,13 +51,13 @@ bool HashTableCustom_O::keyTest(T_sp entryKey, T_sp searchKey) const { return c.notnilp(); } -gc::Fixnum HashTableCustom_O::sxhashKey(T_sp obj, gc::Fixnum bound, HashGenerator& hg) const { +void HashTableCustom_O::sxhashEffect(T_sp obj, HashGenerator& hg) const { T_sp hash = eval::funcall(hasher, obj); if (hash.fixnump()) { gc::Fixnum fxhash = hash.unsafe_fixnum(); if (fxhash >= 0) { hg.addValue(fxhash); - return hg.hashBound(bound); + return; } } TYPE_ERROR(hash, Cons_O::createList(cl::_sym_and, cl::_sym_fixnum, Cons_O::createList(cl::_sym_Integer_O, Integer_O::create(0)))); diff --git a/src/core/hashTableEq.cc b/src/core/hashTableEq.cc index 62e13ec9b0..b621c03500 100644 --- a/src/core/hashTableEq.cc +++ b/src/core/hashTableEq.cc @@ -93,9 +93,10 @@ KeyValuePair* HashTableEq_O::searchTable_no_read_lock(T_sp key, cl_index index) bool HashTableEq_O::keyTest(T_sp entryKey, T_sp searchKey) const { return cl__eq(entryKey, searchKey); } -gc::Fixnum HashTableEq_O::sxhashKey(T_sp obj, gc::Fixnum bound, HashGenerator& hg) const { - HashTable_O::sxhash_eq(hg, obj); - return hg.hashBound(bound); +void HashTableEq_O::sxhashEffect(T_sp obj, HashGenerator& hg) const { + if (obj.generalp()) hg.addGeneralAddress(obj.as_unsafe()); + else if (obj.consp()) hg.addConsAddress(obj.as_unsafe()); + else hg.addValue((uintptr_t)obj.raw_()); } }; // namespace core diff --git a/src/core/hashTableEql.cc b/src/core/hashTableEql.cc index b642fe2bfa..bbc437b534 100644 --- a/src/core/hashTableEql.cc +++ b/src/core/hashTableEql.cc @@ -53,11 +53,15 @@ HashTableEql_sp HashTableEql_O::create_default() { bool HashTableEql_O::keyTest(T_sp entryKey, T_sp searchKey) const { return cl__eql(entryKey, searchKey); } -gc::Fixnum HashTableEql_O::sxhashKey(T_sp obj, gc::Fixnum bound, HashGenerator& hg) const { - HashTable_O::sxhash_eql(hg, obj); - gc::Fixnum hash = hg.hashBound(bound); - LOG("HashTableEql_O::sxhashKey obj[{}] raw_hash[{}] bound[{}] hash[{}]", _rep_(obj), hg.asString(), bound, hash); - return hash; +void HashTableEql_O::sxhashEffect(T_sp obj, HashGenerator& hg) const { + if (obj.fixnump()) hg.addValue0(obj.unsafe_fixnum()); + else if (obj.single_floatp()) hg.addValue0(float_convert::float_to_bits(obj.unsafe_single_float())); + else if (obj.characterp()) hg.addValue0(obj.unsafe_character()); + else if (obj.generalp()) { + if (cl__numberp(obj)) hg.hashObject(obj); + else hg.addGeneralAddress(obj.as_unsafe()); + } else if (obj.consp()) hg.addConsAddress(obj.as_unsafe()); + else SIMPLE_ERROR("Illegal object (object.raw_() = {}) for eql hash {}", (void*)obj.raw_(), _rep_(obj)); } }; // namespace core diff --git a/src/core/hashTableEqual.cc b/src/core/hashTableEqual.cc index d716c31a14..aecab6a2b8 100644 --- a/src/core/hashTableEqual.cc +++ b/src/core/hashTableEqual.cc @@ -59,9 +59,8 @@ HashTableEqual_sp HashTableEqual_O::create_default() { bool HashTableEqual_O::keyTest(T_sp entryKey, T_sp searchKey) const { return cl__equal(entryKey, searchKey); } -gc::Fixnum HashTableEqual_O::sxhashKey(T_sp obj, gc::Fixnum bound, HashGenerator& hg) const { - HashTable_O::sxhash_equal(hg, obj); - return hg.hashBound(bound); +void HashTableEqual_O::sxhashEffect(T_sp obj, HashGenerator& hg) const { + clasp_sxhash(obj, hg); } }; // namespace core diff --git a/src/core/hashTableEqualp.cc b/src/core/hashTableEqualp.cc index 05e936ead6..6b3d9d356c 100644 --- a/src/core/hashTableEqualp.cc +++ b/src/core/hashTableEqualp.cc @@ -63,9 +63,8 @@ bool HashTableEqualp_O::keyTest(T_sp entryKey, T_sp searchKey) const { return equalp; } -gc::Fixnum HashTableEqualp_O::sxhashKey(T_sp obj, gc::Fixnum bound, HashGenerator& hg) const { - HashTable_O::sxhash_equalp(hg, obj); - return hg.hashBound(bound); +void HashTableEqualp_O::sxhashEffect(T_sp obj, HashGenerator& hg) const { + clasp_sxhash_equalp(obj, hg); } }; // namespace core diff --git a/src/core/instance.cc b/src/core/instance.cc index b2e9184324..8a554e3848 100644 --- a/src/core/instance.cc +++ b/src/core/instance.cc @@ -377,14 +377,14 @@ bool Instance_O::equalp(T_sp obj) const { // also only for structure-objects. void Instance_O::sxhash_equalp(HashGenerator& hg) const { if (this->_Class->_Class != _lisp->_Roots._TheStructureClass) { - HashTable_O::sxhash_eq(hg, this->asSmartPtr()); - return; - } - if (hg.isFilling()) - HashTable_O::sxhash_equalp(hg, this->_Class->_className()); - for (size_t i(0), iEnd(this->numberOfSlots()); i < iEnd; ++i) { - if (!this->instanceRef(i).unboundp() && hg.isFilling()) - HashTable_O::sxhash_equalp(hg, this->instanceRef(i)); + // Not a structure, so revert to eql hash + this->General_O::sxhash_equalp(hg); + } else { + if (hg.isFilling()) clasp_sxhash_equalp(this->_Class->_className(), hg); + for (size_t i(0), iEnd(this->numberOfSlots()); i < iEnd; ++i) { + if (!this->instanceRef(i).unboundp() && hg.isFilling()) + clasp_sxhash_equalp(this->instanceRef(i), hg); + } } } diff --git a/src/core/object.cc b/src/core/object.cc index 9c9672aeed..683c35742d 100644 --- a/src/core/object.cc +++ b/src/core/object.cc @@ -452,6 +452,12 @@ void HashGenerator::hashObject(T_sp obj) { LIKELY_if(this->_Depth < MaxDepth) clasp_sxhash(obj, *this); this->_Depth = depth; } +void HashGenerator::hashObjectEqualp(T_sp obj) { + int depth = this->_Depth; + ++this->_Depth; + LIKELY_if(this->_Depth < MaxDepth) clasp_sxhash_equalp(obj, *this); + this->_Depth = depth; +} Fixnum bignum_hash(const mpz_class& bignum) { auto bn = bignum.get_mpz_t(); diff --git a/src/core/pathname.cc b/src/core/pathname.cc index 346a98597a..1dcffe9fcc 100644 --- a/src/core/pathname.cc +++ b/src/core/pathname.cc @@ -416,33 +416,21 @@ bool Pathname_O::equal(T_sp obj) const { } void Pathname_O::sxhash_equal(HashGenerator& hg) const { - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, this->_Host); - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, this->_Device); - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, this->_Directory); - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, this->_Name); - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, this->_Type); - if (hg.isFilling()) - HashTable_O::sxhash_equal(hg, this->_Version); + if (hg.isFilling()) clasp_sxhash(this->_Host, hg); + if (hg.isFilling()) clasp_sxhash(this->_Device, hg); + if (hg.isFilling()) clasp_sxhash(this->_Directory, hg); + if (hg.isFilling()) clasp_sxhash(this->_Name, hg); + if (hg.isFilling()) clasp_sxhash(this->_Type, hg); + if (hg.isFilling()) clasp_sxhash(this->_Version, hg); } void Pathname_O::sxhash_equalp(HashGenerator& hg) const { - if (hg.isFilling()) - HashTable_O::sxhash_equalp(hg, this->_Host); - if (hg.isFilling()) - HashTable_O::sxhash_equalp(hg, this->_Device); - if (hg.isFilling()) - HashTable_O::sxhash_equalp(hg, this->_Directory); - if (hg.isFilling()) - HashTable_O::sxhash_equalp(hg, this->_Name); - if (hg.isFilling()) - HashTable_O::sxhash_equalp(hg, this->_Type); - if (hg.isFilling()) - HashTable_O::sxhash_equalp(hg, this->_Version); + if (hg.isFilling()) clasp_sxhash_equalp(this->_Host, hg); + if (hg.isFilling()) clasp_sxhash_equalp(this->_Device, hg); + if (hg.isFilling()) clasp_sxhash_equalp(this->_Directory, hg); + if (hg.isFilling()) clasp_sxhash_equalp(this->_Name, hg); + if (hg.isFilling()) clasp_sxhash_equalp(this->_Type, hg); + if (hg.isFilling()) clasp_sxhash_equalp(this->_Version, hg); } Pathname_sp Pathname_O::tilde_expand(Pathname_sp pathname) { diff --git a/src/lisp/kernel/lsp/predlib.lisp b/src/lisp/kernel/lsp/predlib.lisp index d64486570e..7086968ce9 100644 --- a/src/lisp/kernel/lsp/predlib.lisp +++ b/src/lisp/kernel/lsp/predlib.lisp @@ -401,7 +401,7 @@ and is not adjustable." (defun upgraded-array-element-type (element-type &optional env) (declare (ignore env)) - (let* ((hash (logand 127 (si:hash-eql element-type))) + (let* ((hash (logand 127 (sxhash element-type))) (record (aref *upgraded-array-element-type-cache* hash))) (declare (type (integer 0 127) hash)) (if (and record (eq (car record) element-type)) @@ -1425,7 +1425,8 @@ if not possible." (return-from subtypep (values (subclassp t1 t2) t))) ;; Finally, cached results. (let* ((cache *subtypep-cache*) - (hash (the (integer 0 255) (logand (hash-eql t1 t2) 255))) + ;; FIXME: mixing could be improved + (hash (the (integer 0 255) (logand (core:hash-equal t1 t2) 255))) (elt (aref cache hash))) (when (and elt (eq (caar elt) t1) (eq (cdar elt) t2)) (setq elt (cdr elt)) From 249a52f999bc6d4cec5a80518e1f63ff2040aedb Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 18:50:32 -0500 Subject: [PATCH 11/39] adjust HashTable_O::find return convention Returning a pointer to the inside of a Lisp object is something to avoid, and moreso if it's a bespoke structure. This change breaks Cando, but I've looked at Cando's code and it should work with this fine once I update it. --- include/clasp/core/hashTable.h | 3 +-- src/core/hashTable.cc | 13 ++++--------- src/core/pathname.cc | 6 +++--- src/core/sysprop.cc | 12 ++++++------ 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index d490ed1bb5..02eebdb536 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -155,8 +155,7 @@ class HashTable_O : public HashTableBase_O { /*! Return true if the key is within the hash table */ bool contains(T_sp key); - /*! Return the key/value pair in a CONS if found or NIL if not */ - KeyValuePair* find(T_sp key); + std::optional find(T_sp key); // gethash but more convenient for C++ T_mv gethash(T_sp key, T_sp defaultValue = nil()) override; gc::Fixnum hashIndex(T_sp key) const; diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index fb905f90e3..01dec5468a 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -567,21 +567,16 @@ CL_DEFMETHOD gc::Fixnum HashTable_O::hashIndex(T_sp key) const { return this->sxhashKey(key); } -KeyValuePair* HashTable_O::find(T_sp key) { +std::optional HashTable_O::find(T_sp key) { HT_READ_LOCK(this); cl_index index = this->sxhashKey(key); KeyValuePair* keyValue = this->searchTable_no_read_lock(key, index); - if (!keyValue) - return keyValue; - if (keyValue->_Value.no_keyp()) - return nullptr; - return keyValue; + if (!keyValue || keyValue->_Value.no_keyp()) return std::optional(); + else return std::optional(keyValue->_Value); } bool HashTable_O::contains(T_sp key) { - HT_READ_LOCK(this); - KeyValuePair* keyValue = this->find(key); - return keyValue != nullptr; + return this->find(key).has_value(); } bool HashTable_O::remhash(T_sp key) { diff --git a/src/core/pathname.cc b/src/core/pathname.cc index 1dcffe9fcc..8391e26ac1 100644 --- a/src/core/pathname.cc +++ b/src/core/pathname.cc @@ -602,10 +602,10 @@ CL_DOCSTRING(R"dx(Returns the host's list of translations. Each translation is a two elements: from-wildcard and to-wildcard. From-wildcard is a logical pathname whose host is host. To-wildcard is a pathname.)dx") CL_DEFUN List_sp cl__logical_pathname_translations(String_sp host) { - KeyValuePair* pair = _lisp->pathnameTranslations_()->find(host); - if (!pair) // This type error should be (satisfies logical-host-p) + auto found = _lisp->pathnameTranslations_()->find(host); + if (found) return *found; + else // This type error should be (satisfies logical-host-p) TYPE_ERROR(host, cl::_sym_string); - return pair->_Value; } CL_LISPIFY_NAME("cl:logical-pathname-translations"); diff --git a/src/core/sysprop.cc b/src/core/sysprop.cc index 1885e935f1..1d9237b1bf 100644 --- a/src/core/sysprop.cc +++ b/src/core/sysprop.cc @@ -42,9 +42,9 @@ DOCGROUP(clasp); CL_DEFUN_SETF T_sp core__put_sysprop(T_sp value, T_sp key, T_sp area) { ASSERT(_lisp->_Roots._Sysprop.notnilp()); HashTableEql_sp sysprops = gc::As_unsafe(_lisp->_Roots._Sysprop); - KeyValuePair* area_pair = sysprops->find(area); + auto area_pair = sysprops->find(area); if (area_pair) - return gc::As(area_pair->_Value)->hash_table_setf_gethash(key, value); + return gc::As(*area_pair)->hash_table_setf_gethash(key, value); HashTableEql_sp new_hash_table = gc::As( HashTable_O::create_thread_safe(cl::_sym_eql, SimpleBaseString_O::make("SYSPRRD"), SimpleBaseString_O::make("SYSPRWR"))); @@ -59,9 +59,9 @@ DOCGROUP(clasp); CL_DEFUN T_mv core__get_sysprop(T_sp key, T_sp area) { ASSERT(_lisp->_Roots._Sysprop.notnilp()); HashTableEql_sp sysprops = gc::As_unsafe(_lisp->_Roots._Sysprop); - KeyValuePair* area_pair = sysprops->find(area); + auto area_pair = sysprops->find(area); if (area_pair) - return gc::As(area_pair->_Value)->gethash(key); + return gc::As(*area_pair)->gethash(key); return Values(nil(), nil()); } @@ -73,8 +73,8 @@ DOCGROUP(clasp); CL_DEFUN bool core__rem_sysprop(T_sp key, T_sp area) { ASSERT(_lisp->_Roots._Sysprop.notnilp()); HashTableEql_sp sysprops = gc::As_unsafe(_lisp->_Roots._Sysprop); - KeyValuePair* area_pair = sysprops->find(area); - return area_pair && gc::As(area_pair->_Value)->remhash(key); + auto area_pair = sysprops->find(area); + return area_pair && gc::As(*area_pair)->remhash(key); } SYMBOL_SC_(CorePkg, put_sysprop); From d873d0a8917c3708d065e2c4a0d5ab665677e29c Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 19:08:03 -0500 Subject: [PATCH 12/39] only one loop in hash table search % is nice --- src/core/hashTable.cc | 27 ++++++--------------------- src/core/hashTableEq.cc | 21 +++++++-------------- 2 files changed, 13 insertions(+), 35 deletions(-) diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 01dec5468a..c57c7e934f 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -497,12 +497,11 @@ CL_DEFUN T_mv core__gethash3(T_sp key, T_sp hashTable, T_sp default_value) { }; KeyValuePair* HashTable_O::searchTable_no_read_lock(T_sp key, cl_index index) { - KeyValuePair* table = &this->_Table[0]; // get the table for debugging size_t tableSize = this->_Table.size(); - for (size_t cur = index, curEnd(tableSize); cur < curEnd; ++cur) { - KeyValuePair& entry = table[cur]; - if (entry._Key.no_keyp()) - goto NOT_FOUND; + size_t cur = index; + do { + KeyValuePair& entry = this->_Table[cur]; + if (entry._Key.no_keyp()) break; if (!entry._Key.deletedp()) { DEBUG_HASH_TABLE( { core::clasp_write_string(fmt::format("{}:{} search-end !deletedp index = {}\n", __FILE__, __LINE__, cur)); }); @@ -516,22 +515,8 @@ KeyValuePair* HashTable_O::searchTable_no_read_lock(T_sp key, cl_index index) { return &entry; } } - } - for (size_t cur = 0, curEnd(index); cur < curEnd; ++cur) { - KeyValuePair& entry = table[cur]; - if (entry._Key.no_keyp()) - goto NOT_FOUND; - if (!entry._Key.deletedp()) { - DEBUG_HASH_TABLE( - { core::clasp_write_string(fmt::format("{}:{} search-begin !deletedp index = {}\n", __FILE__, __LINE__, cur)); }); - if (this->keyTest(entry._Key, key)) { - DEBUG_HASH_TABLE( - { core::clasp_write_string(fmt::format("{}:{} search-begin found key index = {}\n", __FILE__, __LINE__, cur)); }); - return &entry; - } - } - } -NOT_FOUND: + cur = (cur + 1) % tableSize; + } while (cur != index); // loop over the whole table if necessary DEBUG_HASH_TABLE({ core::clasp_write_string(fmt::format("{}:{} key not found\n", __FILE__, __LINE__)); }); return nullptr; } diff --git a/src/core/hashTableEq.cc b/src/core/hashTableEq.cc index b621c03500..a7256a6561 100644 --- a/src/core/hashTableEq.cc +++ b/src/core/hashTableEq.cc @@ -73,21 +73,14 @@ HashTableEq_sp HashTableEq_O::createFromPList(List_sp plist, Symbol_sp nilTermin } KeyValuePair* HashTableEq_O::searchTable_no_read_lock(T_sp key, cl_index index) { - for (size_t cur = index, curEnd(this->_Table.size()); cur < curEnd; ++cur) { + size_t tableSize = this->_Table.size(); + size_t cur = index; + do { KeyValuePair& entry = this->_Table[cur]; - if (entry._Key == key) - return &entry; - if (entry._Key.no_keyp()) - goto NOT_FOUND; - } - for (size_t cur = 0, curEnd(index); cur < curEnd; ++cur) { - KeyValuePair& entry = this->_Table[cur]; - if (entry._Key == key) - return &entry; - if (entry._Key.no_keyp()) - goto NOT_FOUND; - } -NOT_FOUND: + if (entry._Key == key) return &entry; + if (entry._Key.no_keyp()) break; + cur = (cur + 1) % tableSize; + } while (cur != index); return nullptr; } From c379f3e5418c750de9672a7a58735b1b4fe9f0e2 Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 9 Dec 2024 19:41:42 -0500 Subject: [PATCH 13/39] define gethash in terms of find --- src/core/hashTable.cc | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index c57c7e934f..4ef983d7bc 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -530,21 +530,9 @@ CL_DEFUN void core__hash_table_force_rehash(HashTable_sp ht) { } T_mv HashTable_O::gethash(T_sp key, T_sp default_value) { - LOG("gethash looking for key[{}]", _rep_(key)); - HT_READ_LOCK(this); - cl_index index = this->sxhashKey(key); - KeyValuePair* keyValuePair = this->searchTable_no_read_lock(key, index); - LOG("Found keyValueCons"); // % keyValueCons->__repr__() ); INFINITE-LOOP - if (keyValuePair) { - T_sp value = keyValuePair->_Value; - if (value.no_keyp()) { - LOG("valueOrUnbound is unbound - returning default"); - return (Values(default_value, nil())); - } - LOG("Found assoc - returning"); // : %s") % res->__repr__() ); INFINITE-LOOP - return Values(value, _lisp->_true()); - } - return Values(default_value, nil()); + auto res = this->find(key); + if (res) return Values(*res, _lisp->_true()); + else return Values(default_value, nil()); } CL_LISPIFY_NAME("core:hashIndex"); From 22b29fd147c8b75979c2fcd9c34e293940d679d3 Mon Sep 17 00:00:00 2001 From: Bike Date: Mon, 16 Dec 2024 15:04:35 -0500 Subject: [PATCH 14/39] delete old unused function --- src/core/hashTable.cc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 4ef983d7bc..c9ae8a217c 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -296,16 +296,6 @@ CL_DEFUN T_sp cl__clrhash(HashTableBase_sp hash_table) { return hash_table; }; -CL_LAMBDA(cons); -CL_DECLARE(); -CL_DOCSTRING(R"dx(hashTableEntryDeletedP)dx"); -DOCGROUP(clasp); -CL_DEFUN bool core__hash_table_entry_deleted_p(T_sp cons) { - if (!cons.consp()) - SIMPLE_ERROR("Arg must be a cons"); - return oCdr(gc::As(cons)).no_keyp(); -}; - CL_LAMBDA(&rest args); CL_DECLARE(); CL_DOCSTRING(R"dx(hash_equal generates an equal hash for a list of objects)dx"); From aa224314232204287f2a5d829f5aa61a7ee18fd8 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 17 Dec 2024 09:58:15 -0500 Subject: [PATCH 15/39] Remove rehash threshold stuff from the Lisp object seriously unnecessary. I assume the intent was to avoid consing up a double float object for defaulting, but we do have singles. --- include/clasp/core/hashTableEq.h | 1 + include/clasp/core/lisp.h | 4 ---- src/analysis/clasp_gc.sif | 7 ------- src/analysis/clasp_gc_cando.sif | 7 ------- src/core/hashTableEq.cc | 4 ++++ src/core/lisp.cc | 2 -- src/core/write_object.cc | 5 ++--- 7 files changed, 7 insertions(+), 23 deletions(-) diff --git a/include/clasp/core/hashTableEq.h b/include/clasp/core/hashTableEq.h index b67c570d85..e5ed2dbb05 100644 --- a/include/clasp/core/hashTableEq.h +++ b/include/clasp/core/hashTableEq.h @@ -41,6 +41,7 @@ class HashTableEq_O : public HashTable_O { protected: virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); public: + static HashTableEq_sp create(uint sz); static HashTableEq_sp create(uint sz, Number_sp rehashSize, double rehashThreshold); static HashTableEq_sp create_default(); static HashTableEq_sp createFromPList(List_sp plist, Symbol_sp nilTerminatedValidKeywords[]); diff --git a/include/clasp/core/lisp.h b/include/clasp/core/lisp.h index 60ec742f2e..f0e390fe91 100644 --- a/include/clasp/core/lisp.h +++ b/include/clasp/core/lisp.h @@ -318,8 +318,6 @@ class Lisp { //! Package names to packages gctools::Vec0 _Packages; //----- - DoubleFloat_sp _RehashSize; - DoubleFloat_sp _RehashThreshold; T_sp _NullStream; HashTableEqualp_sp _ThePathnameTranslations; Complex_sp _ImaginaryUnit; @@ -511,8 +509,6 @@ class Lisp { void dump_apropos(const char* part) const; public: - DoubleFloat_sp rehashSize() const { return this->_Roots._RehashSize; }; - DoubleFloat_sp rehashThreshold() const { return this->_Roots._RehashThreshold; }; T_sp nullStream() const { return this->_Roots._NullStream; }; public: diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index dcf0035392..61ae2db785 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -5943,13 +5943,6 @@ :offset-ctype "gctools::tagged_pointer>>" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._Packages" "._Vector" "._Contents")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._RehashSize")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" - :layout-offset-field-names ("_Roots" "._RehashThreshold")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._NullStream")} diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index 1f9fa8cb09..5a61bc25a6 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -12512,13 +12512,6 @@ :offset-ctype "gctools::tagged_pointer>>" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._Packages" "._Vector" "._Contents")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._RehashSize")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" - :layout-offset-field-names ("_Roots" "._RehashThreshold")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._NullStream")} diff --git a/src/core/hashTableEq.cc b/src/core/hashTableEq.cc index a7256a6561..c346f6210c 100644 --- a/src/core/hashTableEq.cc +++ b/src/core/hashTableEq.cc @@ -41,6 +41,10 @@ HashTableEq_sp HashTableEq_O::create(uint sz, Number_sp rehashSize, double rehas return hashTable; } +HashTableEq_sp HashTableEq_O::create(uint sz) { + return HashTableEq_O::create(sz, SingleFloat_dummy_O::create(2.0), DEFAULT_REHASH_THRESHOLD); +} + HashTableEq_sp HashTableEq_O::create_default() { DoubleFloat_sp rhs = DoubleFloat_O::create(2.0); return HashTableEq_O::create(8, rhs, DEFAULT_REHASH_THRESHOLD); diff --git a/src/core/lisp.cc b/src/core/lisp.cc index 3647be5e0d..5ed46dfb3e 100644 --- a/src/core/lisp.cc +++ b/src/core/lisp.cc @@ -547,8 +547,6 @@ void Lisp::startupLispEnvironment() { { FILE* null_out = fopen("/dev/null", "w"); this->_Roots._NullStream = CFileStream_O::make(str_create("/dev/null"), null_out, StreamDirection::io); - this->_Roots._RehashSize = DoubleFloat_O::create(2.0); - this->_Roots._RehashThreshold = DoubleFloat_O::create(maybeFixRehashThreshold(0.7)); this->_Roots._ImaginaryUnit = Complex_O::create(0.0, 1.0); this->_Roots._ImaginaryUnitNegative = Complex_O::create(0.0, -1.0); this->_Roots._PlusHalf = Ratio_O::create_primitive(make_fixnum(1), make_fixnum(2)); diff --git a/src/core/write_object.cc b/src/core/write_object.cc index 221f7b489a..5861d1cc5e 100644 --- a/src/core/write_object.cc +++ b/src/core/write_object.cc @@ -36,7 +36,7 @@ THE SOFTWARE. #include #include #include -#include +#include #include #include #include @@ -163,8 +163,7 @@ T_sp write_object(T_sp x, T_sp stream) { T_sp circle_counter = _sym_STARcircle_counterSTAR->symbolValue(); if (circle_counter.nilp()) { - HashTable_sp hash = gc::As_unsafe( - cl__make_hash_table(cl::_sym_eq, make_fixnum(1024), _lisp->rehashSize(), _lisp->rehashThreshold())); + HashTable_sp hash = HashTableEq_O::create(1024); DynamicScopeManager scope(_sym_STARcircle_counterSTAR, _lisp->_true()); DynamicScopeManager scope2(_sym_STARcircle_stackSTAR, hash); do_write_object_circle(x, _lisp->nullStream()); From 8531f081d49c6449dd2fcb12e249d9d67e3f6f21 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 17 Dec 2024 11:22:25 -0500 Subject: [PATCH 16/39] make hash table pairs a class function again trying to present a coherent API. Also delete an unused function that uses KeyValuePair directly. --- include/clasp/core/hashTable.h | 2 ++ src/core/hashTable.cc | 52 +++++++++++----------------------- 2 files changed, 18 insertions(+), 36 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index 02eebdb536..ac6f647103 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -191,6 +191,8 @@ class HashTable_O : public HashTableBase_O { void insert(T_sp obj) { this->setf_gethash(obj, nil()); }; /*! Return a Cons of all keys */ List_sp keysAsCons(); + /* Return a vector of all keys and values. */ + Vector_sp pairs() const; }; T_mv clasp_gethash_safe(T_sp key, T_sp hashTable, T_sp default_); diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index c9ae8a217c..5a910694e3 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -131,21 +131,25 @@ struct HashTableWriteLock { #define HT_WRITE_LOCK(me) #endif +Vector_sp HashTable_O::pairs() const { + // FIXME: use maphash for this, but without the overhead of a std::function + HT_READ_LOCK(this); + SimpleVector_sp keyvalues = SimpleVector_O::make(_HashTableCount * 2); + size_t idx(0); + for (size_t it(0), itEnd(_Table.size()); it < itEnd; ++it) { + const KeyValuePair& entry = _Table[it]; + if (!entry._Key.no_keyp() && !entry._Key.deletedp()) { + keyvalues[idx++] = entry._Key; + keyvalues[idx++] = entry._Value; + } + } + return keyvalues; +} + DOCGROUP(clasp); CL_DEFUN Vector_sp core__hash_table_pairs(HashTableBase_sp hash_table_base) { if (gc::IsA(hash_table_base)) { - HashTable_sp hash_table = gc::As_unsafe(hash_table_base); - HT_READ_LOCK(&*hash_table); - SimpleVector_sp keyvalues = SimpleVector_O::make(hash_table->_HashTableCount * 2); - size_t idx(0); - for (size_t it(0), itEnd(hash_table->_Table.size()); it < itEnd; ++it) { - KeyValuePair& entry = hash_table->_Table[it]; - if (!entry._Key.no_keyp() && !entry._Key.deletedp()) { - keyvalues[idx++] = entry._Key; - keyvalues[idx++] = entry._Value; - } - } - return keyvalues; + return hash_table_base.as_unsafe()->pairs(); } else if (gc::IsA(hash_table_base)) { WeakKeyHashTable_sp hash_table = gc::As_unsafe(hash_table_base); return hash_table->_HashTable.pairs(); @@ -718,30 +722,6 @@ string HashTable_O::__repr__() const { return ss.str(); } -#define DUMP_LOW_LEVEL 1 - -void dump_one_entry(HashTable_sp ht, size_t it, stringstream& ss, KeyValuePair& entry) { - T_sp key = entry._Key; - T_sp value = entry._Value; -#ifdef DUMP_LOW_LEVEL - ss << " ( "; - size_t hi = ht->hashIndex(key); - if (hi != it) - ss << "!!!out-of-place-bucket!!! hi=" << hi; - ss << " hashIndex(key)=" << ht->hashIndex(key) << " "; - if ((key).consp()) { - List_sp ckey = key; - ss << "(cons " << oCar(ckey).raw_() << " . " << oCdr(ckey).raw_() << ")@" << (void*)ckey.raw_(); - } else { - ss << key.raw_(); - } - ss << ", " << value.raw_() << ")" - << " " << std::endl; -#else - ss << " " << _rep_(entry._Key) << " " << _rep_(entry._Value) << std::endl; -#endif -}; - CL_DEFMETHOD string HashTable_O::hash_table_dump() { stringstream ss; HT_READ_LOCK(this); From 67e0e3cc3a8f4907caeb8206833a645100bf0ddb Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 17 Dec 2024 12:27:39 -0500 Subject: [PATCH 17/39] remove redundant test in hash table access i'm reasonably sure this should never be tripped: no_key is not usually available as a value, so nobody's storing it in hash tables from Lisp. In C++ we only put it in the value as the default when we're resizing a table, and in that case we make the key no_key as well. So the only way you'd have a key that's not no_key and a value that is no_key is I think if your hash table is thread unsafe and you store a new key/value in it while another thread looks for that key, and if that's what you're doing you're in crazytown to begin with so the test is not going to help. --- src/core/hashTable.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 5a910694e3..932d928d37 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -538,7 +538,7 @@ std::optional HashTable_O::find(T_sp key) { HT_READ_LOCK(this); cl_index index = this->sxhashKey(key); KeyValuePair* keyValue = this->searchTable_no_read_lock(key, index); - if (!keyValue || keyValue->_Value.no_keyp()) return std::optional(); + if (!keyValue) return std::optional(); else return std::optional(keyValue->_Value); } From 2aa46e80c2e1addfcac26adde0d43538ff8470c8 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 17 Dec 2024 15:34:06 -0500 Subject: [PATCH 18/39] Use HashTable_sp instead of specific test types wherever possible The idea is to let external code (e.g. Cando) use these createEq whatevers instead of requiring a HashTableEq type they don't need. This will eventually let me remove the test types or at least make them an internal implementation detail. --- include/clasp/asttooling/translators.h | 2 +- include/clasp/clbind/class_registry.h | 2 +- include/clasp/core/character.fwd.h | 2 +- include/clasp/core/coretypes.h | 4 ++-- include/clasp/core/funcallableInstance.h | 2 +- include/clasp/core/hashTable.h | 4 ++++ include/clasp/core/instance.h | 2 +- include/clasp/core/lisp.h | 8 ++++---- include/clasp/core/package.h | 6 +++--- include/clasp/core/symbolToEnumConverter.h | 8 ++++---- include/clasp/llvmo/llvmoExpose.h | 4 ++-- src/clbind/class_registry.cc | 2 +- src/core/character.cc | 2 +- src/core/compiler.cc | 4 ++-- src/core/corePackage.cc | 10 +++++----- src/core/documentation.cc | 2 +- src/core/funcallableInstance.cc | 4 ++-- src/core/hashTable.cc | 5 +++++ src/core/instance.cc | 4 ++-- src/core/lisp.cc | 10 +++++----- src/core/package.cc | 6 +++--- src/core/readtable.cc | 14 +++++++------- src/core/symbolToEnumConverter.cc | 8 ++++---- src/core/sysprop.cc | 14 +++++++------- src/core/write_object.cc | 2 +- src/gctools/exposeClasses0.cc | 4 ++-- src/llvmo/llvmoExpose.cc | 6 +++--- 27 files changed, 75 insertions(+), 66 deletions(-) diff --git a/include/clasp/asttooling/translators.h b/include/clasp/asttooling/translators.h index c6681a3aff..44384edc1a 100644 --- a/include/clasp/asttooling/translators.h +++ b/include/clasp/asttooling/translators.h @@ -120,7 +120,7 @@ template <> struct to_object> { template <> struct to_object&, translate::dont_adopt_pointer> { typedef std::map GivenType; static core::T_sp convert(GivenType vals) { - core::HashTableEqual_sp result = core::HashTableEqual_O::create_default(); + core::HashTable_sp result = core::HashTable_O::createEqual(); for (auto pair : vals) { core::SimpleBaseString_sp str = core::SimpleBaseString_O::make(pair.first); core::T_sp obj = to_object::convert(pair.second); diff --git a/include/clasp/clbind/class_registry.h b/include/clasp/clbind/class_registry.h index d613f04345..5aa4e68455 100644 --- a/include/clasp/clbind/class_registry.h +++ b/include/clasp/clbind/class_registry.h @@ -81,7 +81,7 @@ class ClassRegistry_O : public core::General_O { GCPRIVATE : /*! Index on the type_id.id converted to a core::Pointer and use EQL equality */ - core::HashTableEql_sp m_classes; + core::HashTable_sp m_classes; // std::map m_classes; #if 0 diff --git a/include/clasp/core/character.fwd.h b/include/clasp/core/character.fwd.h index c56c57bf0a..fc3ea92384 100644 --- a/include/clasp/core/character.fwd.h +++ b/include/clasp/core/character.fwd.h @@ -30,7 +30,7 @@ namespace core { bool clasp_charEqual2(T_sp x, T_sp y); struct CharacterInfo { - HashTableEqual_sp _NamesToCharacterIndex; + HashTable_sp _NamesToCharacterIndex; gctools::Vec0 gIndexedCharacters; gctools::Vec0 gCharacterNames; const char* repr() const { return "CharacterInfo"; }; diff --git a/include/clasp/core/coretypes.h b/include/clasp/core/coretypes.h index fe62ee4713..45964b8b58 100644 --- a/include/clasp/core/coretypes.h +++ b/include/clasp/core/coretypes.h @@ -27,8 +27,8 @@ typedef gctools::smart_ptr Pointer_sp; class SimpleVector_O; typedef gctools::smart_ptr SimpleVector_sp; -class HashTableEqual_O; -typedef gctools::smart_ptr HashTableEqual_sp; +class HashTable_O; +typedef gctools::smart_ptr HashTable_sp; class Instance_O; typedef gctools::smart_ptr Instance_sp; diff --git a/include/clasp/core/funcallableInstance.h b/include/clasp/core/funcallableInstance.h index 38b6c2a663..a6aa82a5cf 100644 --- a/include/clasp/core/funcallableInstance.h +++ b/include/clasp/core/funcallableInstance.h @@ -80,7 +80,7 @@ class FuncallableInstance_O : public Function_O { public: virtual bool compiledP() const { return true; }; - void accumulateSuperClasses(HashTableEq_sp supers, ComplexVector_T_sp arrayedSupers, Instance_sp mc); + void accumulateSuperClasses(HashTable_sp supers, ComplexVector_T_sp arrayedSupers, Instance_sp mc); void lowLevel_calculateClassPrecedenceList(); // virtual bool isSubClassOf(Instance_sp mc) const; diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index ac6f647103..f559f3466b 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -106,6 +106,10 @@ class HashTable_O : public HashTableBase_O { #endif public: static HashTable_sp create(T_sp test); // set everything up with defaults + static HashTable_sp createEq(size_t sz = 8); + static HashTable_sp createEql(); + static HashTable_sp createEqual(); + static HashTable_sp createEqualp(); static HashTable_sp create_thread_safe(T_sp test, SimpleBaseString_sp readLockName, SimpleBaseString_sp writeLockName); // set everything up with defaults diff --git a/include/clasp/core/instance.h b/include/clasp/core/instance.h index 2bfd645d05..b7ddd2599f 100644 --- a/include/clasp/core/instance.h +++ b/include/clasp/core/instance.h @@ -159,7 +159,7 @@ class Instance_O : public General_O { return this->isSubClassOf(lisp_classFromClassSymbol(oclass::static_classSymbol())); } - void accumulateSuperClasses(HashTableEq_sp supers, ComplexVector_T_sp arrayedSupers, Instance_sp mc); + void accumulateSuperClasses(HashTable_sp supers, ComplexVector_T_sp arrayedSupers, Instance_sp mc); void lowLevel_calculateClassPrecedenceList(); virtual bool isSubClassOf(Instance_sp mc) const; diff --git a/include/clasp/core/lisp.h b/include/clasp/core/lisp.h index f0e390fe91..80cece238f 100644 --- a/include/clasp/core/lisp.h +++ b/include/clasp/core/lisp.h @@ -319,13 +319,13 @@ class Lisp { gctools::Vec0 _Packages; //----- T_sp _NullStream; - HashTableEqualp_sp _ThePathnameTranslations; + HashTable_sp _ThePathnameTranslations; Complex_sp _ImaginaryUnit; Complex_sp _ImaginaryUnitNegative; Ratio_sp _PlusHalf; // DynamicBindingStack _Bindings; - HashTableEqual_sp _SourceFileIndices; // map - HashTableEqual_sp _PackageNameIndexMap; // map + HashTable_sp _SourceFileIndices; // map + HashTable_sp _PackageNameIndexMap; // map bool _PrintSymbolsProperly; bool _TheSystemIsUp; bool _Started; @@ -410,7 +410,7 @@ class Lisp { // void catchUnwindTag(List_sp catchStore); // List_sp catchFindTag(T_sp tag); public: - HashTableEqualp_sp pathnameTranslations_() const { return this->_Roots._ThePathnameTranslations; }; + HashTable_sp pathnameTranslations_() const { return this->_Roots._ThePathnameTranslations; }; // void setPathnameTranslations_(List_sp pnt) { this->_Roots._ThePathnameTranslations = pnt; }; /*! Return the maximum path length for the system */ public: diff --git a/include/clasp/core/package.h b/include/clasp/core/package.h index aa053fcea0..e146b6f3ae 100644 --- a/include/clasp/core/package.h +++ b/include/clasp/core/package.h @@ -53,9 +53,9 @@ class Package_O : public General_O { void __write__(T_sp stream) const override; // in write_ugly.cc public: // instance variables - HashTableEqual_sp _InternalSymbols; - HashTableEqual_sp _ExternalSymbols; - HashTableEq_sp _Shadowing; + HashTable_sp _InternalSymbols; + HashTable_sp _ExternalSymbols; + HashTable_sp _Shadowing; SimpleString_sp _Name; gctools::Vec0 _UsingPackages; gctools::Vec0 _PackagesUsedBy; diff --git a/include/clasp/core/symbolToEnumConverter.h b/include/clasp/core/symbolToEnumConverter.h index 52f7a9e7c8..198cc34947 100644 --- a/include/clasp/core/symbolToEnumConverter.h +++ b/include/clasp/core/symbolToEnumConverter.h @@ -53,10 +53,10 @@ class SymbolToEnumConverter_O : public General_O { * Used when errors are thrown */ SimpleString_sp _WhatTheEnumsRepresent; - HashTableEql_sp _EnumToSymbol; - HashTableEq_sp _ArchiveSymbolToEnum; - HashTableEql_sp _EnumToArchiveSymbol; - HashTableEq_sp _SymbolToEnum; + HashTable_sp _EnumToSymbol; + HashTable_sp _ArchiveSymbolToEnum; + HashTable_sp _EnumToArchiveSymbol; + HashTable_sp _SymbolToEnum; public: List_sp enumSymbolsAsList() const; diff --git a/include/clasp/llvmo/llvmoExpose.h b/include/clasp/llvmo/llvmoExpose.h index cc5d8025c5..ec307039b0 100644 --- a/include/clasp/llvmo/llvmoExpose.h +++ b/include/clasp/llvmo/llvmoExpose.h @@ -1577,7 +1577,7 @@ class ExecutionEngine_O : public core::ExternalObject_O { void initialize(); GCPROTECTED : PointerToExternalType _ptr; - core::HashTableEqual_sp _DependentModules; + core::HashTable_sp _DependentModules; public: virtual void* externalObject() const { return this->_ptr; }; @@ -1630,7 +1630,7 @@ class Module_O : public core::ExternalObject_O { GCPROTECTED : size_t _Id; std::string _UniqueName; PointerToExternalType _ptr; - core::HashTableEqual_sp _UniqueGlobalVariableStrings; + core::HashTable_sp _UniqueGlobalVariableStrings; public: virtual void* externalObject() const { return this->_ptr; }; diff --git a/src/clbind/class_registry.cc b/src/clbind/class_registry.cc index da09b9773c..50ce2b47d7 100644 --- a/src/clbind/class_registry.cc +++ b/src/clbind/class_registry.cc @@ -149,7 +149,7 @@ CLBIND_API void push_instance_metatable(); void ClassRegistry_O::initialize() { this->Base::initialize(); - this->m_classes = core::HashTableEql_O::create_default(); + this->m_classes = core::HashTable_O::createEql(); } ClassRegistry_sp ClassRegistry_O::get_registry() { diff --git a/src/core/character.cc b/src/core/character.cc index ed032cc30d..7ebdbe367c 100644 --- a/src/core/character.cc +++ b/src/core/character.cc @@ -528,7 +528,7 @@ const char* OrderedCharacterNames[] = { void CharacterInfo::initialize() { int num_chars = sizeof(OrderedCharacterNames) / sizeof(OrderedCharacterNames[0]); - this->_NamesToCharacterIndex = HashTableEqual_O::create_default(); + this->_NamesToCharacterIndex = HashTable_O::createEqual(); this->gCharacterNames.resize(num_chars, nil()); this->gIndexedCharacters.resize(num_chars, nil()); for (size_t fci = 0; fci < num_chars; ++fci) { diff --git a/src/core/compiler.cc b/src/core/compiler.cc index c80aed9bf5..8ab5250da6 100644 --- a/src/core/compiler.cc +++ b/src/core/compiler.cc @@ -1223,12 +1223,12 @@ CL_DEFUN T_mv core__progv_function(List_sp symbols, List_sp values, Function_sp DOCGROUP(clasp); CL_DEFUN T_mv core__declared_global_inline_p(T_sp name) { - return gc::As(_sym_STARfunctions_to_inlineSTAR->symbolValue())->gethash(name); + return gc::As(_sym_STARfunctions_to_inlineSTAR->symbolValue())->gethash(name); } DOCGROUP(clasp); CL_DEFUN T_mv core__declared_global_notinline_p(T_sp name) { - return gc::As(_sym_STARfunctions_to_notinlineSTAR->symbolValue())->gethash(name); + return gc::As(_sym_STARfunctions_to_notinlineSTAR->symbolValue())->gethash(name); } DOCGROUP(clasp); diff --git a/src/core/corePackage.cc b/src/core/corePackage.cc index db3b12a36f..0e36cac9ed 100644 --- a/src/core/corePackage.cc +++ b/src/core/corePackage.cc @@ -523,7 +523,7 @@ void CoreExposer_O::define_essential_globals(LispPtr lisp) { _lisp->_Roots._TerminalIO = terminal_syn; cl::_sym_STARterminal_ioSTAR->defparameter(terminal_syn); _sym_STARdocumentation_poolSTAR->defparameter( - Cons_O::createList(HashTableEql_O::create_default(), SimpleBaseString_O::make("help_file.dat"))); + Cons_O::createList(HashTable_O::createEql(), SimpleBaseString_O::make("help_file.dat"))); _sym_STARdocumentation_poolSTAR->exportYourself(); _sym_STARsystem_defsetf_update_functionsSTAR->defparameter(nil()); cl::_sym_STARmacroexpand_hookSTAR->defparameter(cl::_sym_funcall); @@ -610,7 +610,7 @@ void CoreExposer_O::define_essential_globals(LispPtr lisp) { _sym__PLUS_WNOHANG_PLUS_->defconstant(make_fixnum(WNOHANG)); cl::_sym_STARrandom_stateSTAR->defparameter(RandomState_O::create()); // Set up a hash table to save JIT info - HashTableEqual_sp jit_save = HashTableEqual_O::create_default(); + HashTable_sp jit_save = HashTable_O::createEqual(); #ifdef CLASP_THREADS // When threading - make *jit-saved-symbol-info* a thread safe hash table SimpleBaseString_sp sbsr = SimpleBaseString_O::make("JITSAVR"); @@ -650,15 +650,15 @@ void CoreExposer_O::define_essential_globals(LispPtr lisp) { _sym_STARdebugInterpretedClosureSTAR->defparameter(nil()); _sym_STARdebugFlowControlSTAR->defparameter(nil()); _sym_STARbacktraceSTAR->defparameter(nil()); - _sym_STARfunctions_to_inlineSTAR->defparameter(HashTableEqual_O::create_default()); - _sym_STARfunctions_to_notinlineSTAR->defparameter(HashTableEqual_O::create_default()); + _sym_STARfunctions_to_inlineSTAR->defparameter(HashTable_O::createEqual()); + _sym_STARfunctions_to_notinlineSTAR->defparameter(HashTable_O::createEqual()); _sym_STARextension_systemsSTAR->defparameter(EXTENSION_SYSTEMS); _sym_STARinitialize_hooksSTAR->defparameter(nil()); _sym_STARterminate_hooksSTAR->defparameter(nil()); SimpleBaseString_sp sbsr1 = SimpleBaseString_O::make("SYSPMNR"); SimpleBaseString_sp sbsw1 = SimpleBaseString_O::make("SYSPMNW"); _lisp->_Roots._Finalizers = WeakKeyHashTable_O::create(); - _lisp->_Roots._Sysprop = gc::As(HashTable_O::create_thread_safe(cl::_sym_eql, sbsr1, sbsw1)); + _lisp->_Roots._Sysprop = HashTable_O::create_thread_safe(cl::_sym_eql, sbsr1, sbsw1); _sym_STARdebug_accessorsSTAR->defparameter(nil()); std::list nicknames; std::list use_packages; diff --git a/src/core/documentation.cc b/src/core/documentation.cc index fc8896ec65..2537022f79 100644 --- a/src/core/documentation.cc +++ b/src/core/documentation.cc @@ -164,7 +164,7 @@ void initialize_documentation_primitives(LispPtr lisp) { SYMBOL_EXPORT_SC_(ExtPkg, annotate); SYMBOL_SC_(CorePkg, ensure_documentation); // TODO move help_file.dat definition somewhere better - // _sym_STARdocumentation_poolSTAR->defparameter(Cons_O::createList(HashTableEql_O::create_default(), + // _sym_STARdocumentation_poolSTAR->defparameter(Cons_O::createList(HashTable_O::createEql(), // Str_O::create("help_file.dat"))); _sym_STARdocumentation_poolSTAR->exportYourself(); } diff --git a/src/core/funcallableInstance.cc b/src/core/funcallableInstance.cc index 7bbb410ee9..9ae94c2e3d 100644 --- a/src/core/funcallableInstance.cc +++ b/src/core/funcallableInstance.cc @@ -248,9 +248,9 @@ SYMBOL_EXPORT_SC_(CorePkg, STARdtreeSymbolsSTAR); void registerOneDtreeInfo(const std::string& name, int val) { printf("%s:%d:%s name: %s val: %d\n", __FILE__, __LINE__, __FUNCTION__, name.c_str(), val); if (_sym_STARdtreeSymbolsSTAR->symbolValue().nilp()) { - _sym_STARdtreeSymbolsSTAR->defparameter(HashTableEq_O::create_default()); + _sym_STARdtreeSymbolsSTAR->defparameter(HashTable_O::createEq()); } - HashTableEq_sp ht = gc::As(_sym_STARdtreeSymbolsSTAR->symbolValue()); + HashTable_sp ht = gc::As(_sym_STARdtreeSymbolsSTAR->symbolValue()); Symbol_sp key = lisp_upcase_intern(name, "KEYWORD"); ht->setf_gethash(key, make_fixnum(val)); } diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 932d928d37..6f4b07e0b0 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -244,6 +244,11 @@ HashTable_sp HashTable_O::create(T_sp test) { return ht; } +HashTable_sp HashTable_O::createEq(size_t sz) { return HashTableEq_O::create(sz); } +HashTable_sp HashTable_O::createEql() { return HashTableEql_O::create_default(); } +HashTable_sp HashTable_O::createEqual() { return HashTableEqual_O::create_default(); } +HashTable_sp HashTable_O::createEqualp() { return HashTableEqualp_O::create_default(); } + HashTable_sp HashTable_O::create_thread_safe(T_sp test, SimpleBaseString_sp readLockName, SimpleBaseString_sp writeLockName) { Fixnum_sp size = make_fixnum(16); DoubleFloat_sp rehashSize = DoubleFloat_O::create(2.0); diff --git a/src/core/instance.cc b/src/core/instance.cc index 8a554e3848..9ed133f5f1 100644 --- a/src/core/instance.cc +++ b/src/core/instance.cc @@ -432,7 +432,7 @@ void Instance_O::CLASS_set_creator(Creator_sp cb) { this->instanceSet(REF_CLASS_CREATOR, cb); } -void Instance_O::accumulateSuperClasses(HashTableEq_sp supers, ComplexVector_T_sp arrayedSupers, Instance_sp mc) { +void Instance_O::accumulateSuperClasses(HashTable_sp supers, ComplexVector_T_sp arrayedSupers, Instance_sp mc) { if (IS_SYMBOL_UNDEFINED(mc->_className())) return; // printf("%s:%d accumulateSuperClasses of: %s\n", __FILE__, __LINE__, _rep_(mc->className()).c_str() ); @@ -456,7 +456,7 @@ void Instance_O::accumulateSuperClasses(HashTableEq_sp supers, ComplexVector_T_s void Instance_O::lowLevel_calculateClassPrecedenceList() { using namespace boost; - HashTableEq_sp supers = HashTableEq_O::create_default(); + HashTable_sp supers = HashTable_O::createEq(); ComplexVector_T_sp arrayedSupers(ComplexVector_T_O::make(16, nil(), clasp_make_fixnum(0))); if (!gc::IsA(arrayedSupers)) { printf("%s:%d:%s The object must be a ComplexVector_T_sp but failed gc::IsA()\n", __FILE__, __LINE__, diff --git a/src/core/lisp.cc b/src/core/lisp.cc index 5ed46dfb3e..9407db370f 100644 --- a/src/core/lisp.cc +++ b/src/core/lisp.cc @@ -171,7 +171,7 @@ struct FindApropos : public KeyValueMapper //, public gctools::StackRoot SimpleString_sp _substr; FindApropos(SimpleString_sp str) { this->_substr = str; - this->_symbols = HashTableEq_O::create_default(); + this->_symbols = HashTable_O::createEq(); }; virtual bool mapKeyValue(T_sp key, T_sp value) { // Bignum_sp skey = gc::As(key); @@ -226,9 +226,9 @@ void Lisp::initialize() { // printf("%s:%d Initializing _lisp\n", __FILE__, __LINE__ ); this->_Roots.charInfo.initialize(); - this->_Roots._SourceFileIndices = HashTableEqual_O::create_default(); - this->_Roots._PackageNameIndexMap = HashTableEqual_O::create_default(); - this->_Roots._ThePathnameTranslations = HashTableEqualp_O::create_default(); + this->_Roots._SourceFileIndices = HashTable_O::createEqual(); + this->_Roots._PackageNameIndexMap = HashTable_O::createEqual(); + this->_Roots._ThePathnameTranslations = HashTable_O::createEqualp(); } template void setup_static_classSymbol(BootStrapCoreSymbolMap const& sidMap) { @@ -501,7 +501,7 @@ void Lisp::startupLispEnvironment() { #endif { initialize_Lisp(); - core::HashTableEql_sp ht = core::HashTableEql_O::create_default(); + core::HashTable_sp ht = core::HashTable_O::createEql(); core::_sym_STARcxxDocumentationSTAR->defparameter(ht); Readtable_sp readtable = Readtable_O::create_standard_readtable(); cl::_sym_STARreadtableSTAR->defparameter(readtable); diff --git a/src/core/package.cc b/src/core/package.cc index 0d3a8ebabc..31b7ea3941 100644 --- a/src/core/package.cc +++ b/src/core/package.cc @@ -515,9 +515,9 @@ Package_sp Package_O::create(SimpleString_sp name) { void Package_O::initialize() { WITH_PACKAGE_READ_WRITE_LOCK(this); this->Base::initialize(); - this->_InternalSymbols = HashTableEqual_O::create_default(); - this->_ExternalSymbols = HashTableEqual_O::create_default(); - this->_Shadowing = HashTableEq_O::create_default(); + this->_InternalSymbols = HashTable_O::createEqual(); + this->_ExternalSymbols = HashTable_O::createEqual(); + this->_Shadowing = HashTable_O::createEq(); #if 0 this->_InternalSymbols->setupThreadSafeHashTable(); this->_ExternalSymbols->setupThreadSafeHashTable(); diff --git a/src/core/readtable.cc b/src/core/readtable.cc index 2d10475d8e..3de1bf48bd 100644 --- a/src/core/readtable.cc +++ b/src/core/readtable.cc @@ -80,7 +80,7 @@ CL_DEFUN T_sp cl__set_syntax_from_char(Character_sp toChar, Character_sp fromCha } gc::Nilable fromTable = fromReadTable->DispatchMacroCharacters_->gethash(fromChar); if (fromTable.notnilp()) { - HashTableEql_sp toTable = HashTableEql_O::create_default(); + HashTable_sp toTable = HashTable_O::createEql(); fromTable->maphash([&toTable](T_sp key, T_sp val) { toTable->setf_gethash(key, val); }); toReadTable->DispatchMacroCharacters_->setf_gethash(toChar, toTable); } else { @@ -832,7 +832,7 @@ CL_DEFUN T_mv core__sharp_vertical_bar(T_sp sin, Character_sp ch, T_sp num) { SYMBOL_EXPORT_SC_(KeywordPkg, syntax); HashTable_sp Readtable_O::create_standard_syntax_table() { - HashTableEql_sp syntax = HashTableEql_O::create_default(); + HashTable_sp syntax = HashTable_O::createEql(); syntax->setf_gethash(clasp_character_create_from_name("TAB"), kw::_sym_whitespace); syntax->setf_gethash(clasp_character_create_from_name("NEWLINE"), kw::_sym_whitespace); syntax->setf_gethash(clasp_character_create_from_name("LINEFEED"), kw::_sym_whitespace); @@ -895,9 +895,9 @@ void Readtable_O::initialize() { this->Base::initialize(); // printf("%s:%d Initializing readtable\n", __FILE__, __LINE__ ); this->Case_ = kw::_sym_upcase; - this->SyntaxTypes_ = HashTableEql_O::create_default(); - this->MacroCharacters_ = HashTableEql_O::create_default(); - this->DispatchMacroCharacters_ = HashTableEql_O::create_default(); + this->SyntaxTypes_ = HashTable_O::createEql(); + this->MacroCharacters_ = HashTable_O::createEql(); + this->DispatchMacroCharacters_ = HashTable_O::createEql(); } clasp_readtable_case Readtable_O::getReadtableCaseAsEnum_() { @@ -977,7 +977,7 @@ T_mv Readtable_O::get_macro_character_(Character_sp ch) { T_sp Readtable_O::make_dispatch_macro_character_(Character_sp ch, T_sp non_terminating_p) { this->set_macro_character_(ch, _sym_dispatch_macro_character, non_terminating_p); - this->DispatchMacroCharacters_->setf_gethash(ch, HashTableEql_O::create_default()); + this->DispatchMacroCharacters_->setf_gethash(ch, HashTable_O::createEql()); return _lisp->_true(); } @@ -1041,7 +1041,7 @@ Readtable_sp Readtable_O::copyReadtable_(gc::Nilable tdest) { this->MacroCharacters_->maphash([&dest](T_sp key, T_sp val) { dest->MacroCharacters_->setf_gethash(key, val); }); this->DispatchMacroCharacters_->maphash([&dest](T_sp key, T_sp val) { HashTable_sp entry = gc::As(val); - HashTable_sp table = HashTableEql_O::create_default(); + HashTable_sp table = HashTable_O::createEql(); entry->maphash([&table](T_sp subkey, T_sp func) { table->setf_gethash(subkey, func); }); dest->DispatchMacroCharacters_->setf_gethash(key, table); }); diff --git a/src/core/symbolToEnumConverter.cc b/src/core/symbolToEnumConverter.cc index 22e8734e0f..9ac7df2445 100644 --- a/src/core/symbolToEnumConverter.cc +++ b/src/core/symbolToEnumConverter.cc @@ -147,10 +147,10 @@ CL_DEFUN Fixnum core__enum_logical_or(SymbolToEnumConverter_sp converter, List_s void SymbolToEnumConverter_O::initialize() { this->Base::initialize(); - this->_EnumToSymbol = HashTableEql_O::create_default(); - this->_ArchiveSymbolToEnum = HashTableEq_O::create_default(); - this->_EnumToArchiveSymbol = HashTableEql_O::create_default(); - this->_SymbolToEnum = HashTableEq_O::create_default(); + this->_EnumToSymbol = HashTable_O::createEql(); + this->_ArchiveSymbolToEnum = HashTable_O::createEq(); + this->_EnumToArchiveSymbol = HashTable_O::createEql(); + this->_SymbolToEnum = HashTable_O::createEq(); } #if 0 void SymbolToEnumConverter_O::archiveBase(ArchiveP node) diff --git a/src/core/sysprop.cc b/src/core/sysprop.cc index 1d9237b1bf..51537b63fe 100644 --- a/src/core/sysprop.cc +++ b/src/core/sysprop.cc @@ -41,12 +41,12 @@ CL_DECLARE(); DOCGROUP(clasp); CL_DEFUN_SETF T_sp core__put_sysprop(T_sp value, T_sp key, T_sp area) { ASSERT(_lisp->_Roots._Sysprop.notnilp()); - HashTableEql_sp sysprops = gc::As_unsafe(_lisp->_Roots._Sysprop); + HashTable_sp sysprops = gc::As_unsafe(_lisp->_Roots._Sysprop); auto area_pair = sysprops->find(area); if (area_pair) - return gc::As(*area_pair)->hash_table_setf_gethash(key, value); + return gc::As(*area_pair)->hash_table_setf_gethash(key, value); - HashTableEql_sp new_hash_table = gc::As( + HashTable_sp new_hash_table = gc::As( HashTable_O::create_thread_safe(cl::_sym_eql, SimpleBaseString_O::make("SYSPRRD"), SimpleBaseString_O::make("SYSPRWR"))); sysprops->hash_table_setf_gethash(area, new_hash_table); return new_hash_table->hash_table_setf_gethash(key, value); @@ -58,10 +58,10 @@ CL_DOCSTRING(R"dx(get_sysprop - returns (values val foundp))dx"); DOCGROUP(clasp); CL_DEFUN T_mv core__get_sysprop(T_sp key, T_sp area) { ASSERT(_lisp->_Roots._Sysprop.notnilp()); - HashTableEql_sp sysprops = gc::As_unsafe(_lisp->_Roots._Sysprop); + HashTable_sp sysprops = gc::As_unsafe(_lisp->_Roots._Sysprop); auto area_pair = sysprops->find(area); if (area_pair) - return gc::As(*area_pair)->gethash(key); + return gc::As(*area_pair)->gethash(key); return Values(nil(), nil()); } @@ -72,9 +72,9 @@ CL_DOCSTRING(R"dx(rem_sysprop)dx"); DOCGROUP(clasp); CL_DEFUN bool core__rem_sysprop(T_sp key, T_sp area) { ASSERT(_lisp->_Roots._Sysprop.notnilp()); - HashTableEql_sp sysprops = gc::As_unsafe(_lisp->_Roots._Sysprop); + HashTable_sp sysprops = gc::As_unsafe(_lisp->_Roots._Sysprop); auto area_pair = sysprops->find(area); - return area_pair && gc::As(*area_pair)->remhash(key); + return area_pair && gc::As(*area_pair)->remhash(key); } SYMBOL_SC_(CorePkg, put_sysprop); diff --git a/src/core/write_object.cc b/src/core/write_object.cc index 5861d1cc5e..1a9bb2fcee 100644 --- a/src/core/write_object.cc +++ b/src/core/write_object.cc @@ -163,7 +163,7 @@ T_sp write_object(T_sp x, T_sp stream) { T_sp circle_counter = _sym_STARcircle_counterSTAR->symbolValue(); if (circle_counter.nilp()) { - HashTable_sp hash = HashTableEq_O::create(1024); + HashTable_sp hash = HashTable_O::createEq(1024); DynamicScopeManager scope(_sym_STARcircle_counterSTAR, _lisp->_true()); DynamicScopeManager scope2(_sym_STARcircle_stackSTAR, hash); do_write_object_circle(x, _lisp->nullStream()); diff --git a/src/gctools/exposeClasses0.cc b/src/gctools/exposeClasses0.cc index 8782ca1fc0..676eaa9d0f 100644 --- a/src/gctools/exposeClasses0.cc +++ b/src/gctools/exposeClasses0.cc @@ -177,8 +177,8 @@ template void add_range_typeq_test_i } void initialize_typeq_map() { - core::HashTableEqual_sp classNameToLispName = core::HashTableEqual_O::create_default(); - core::HashTableEq_sp theTypeqMap = core::HashTableEq_O::create_default(); + core::HashTable_sp classNameToLispName = core::HashTable_O::createEqual(); + core::HashTable_sp theTypeqMap = core::HashTable_O::createEq(); #define ADD_SINGLE_TYPEQ_TEST(type, stamp) \ { \ classNameToLispName->setf_gethash(core::SimpleBaseString_O::make(#type), type::static_classSymbol()); \ diff --git a/src/llvmo/llvmoExpose.cc b/src/llvmo/llvmoExpose.cc index 601e917673..c55890a329 100644 --- a/src/llvmo/llvmoExpose.cc +++ b/src/llvmo/llvmoExpose.cc @@ -1486,7 +1486,7 @@ CL_DEFMETHOD void Module_O::dump_namedMDList() const { void Module_O::initialize() { this->Base::initialize(); - this->_UniqueGlobalVariableStrings = core::HashTableEqual_O::create_default(); + this->_UniqueGlobalVariableStrings = core::HashTable_O::createEqual(); } CL_DEFMETHOD void Module_O::emit_version_ident_metadata() { @@ -1543,7 +1543,7 @@ CL_DEFMETHOD core::List_sp Module_O::getGlobalList() const { namespace llvmo { -void ExecutionEngine_O::initialize() { this->_DependentModules = core::HashTableEqual_O::create_default(); } +void ExecutionEngine_O::initialize() { this->_DependentModules = core::HashTable_O::createEqual(); } string ExecutionEngine_O::__repr__() const { stringstream ss; @@ -4153,7 +4153,7 @@ namespace llvmo { DOCGROUP(clasp); CL_DEFUN core::T_sp llvm_sys__lookup_jit_symbol_info(void* ptr) { printf("%s:%d:%s ptr = %p\n", __FILE__, __LINE__, __FUNCTION__, ptr); - core::HashTableEqual_sp ht = gc::As(comp::_sym_STARjit_saved_symbol_infoSTAR->symbolValue()); + core::HashTable_sp ht = gc::As(comp::_sym_STARjit_saved_symbol_infoSTAR->symbolValue()); core::T_sp result = nil(); ht->map_while_true([ptr, &result](core::T_sp key, core::T_sp value) -> bool { if (value.consp()) { From b7116f9150f17a0634052685dbd062c465f68557 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 17 Dec 2024 16:55:32 -0500 Subject: [PATCH 19/39] Eliminate special casing in eq hash table search this was an optimization of uncertain utility that locks in the type hierardhy, so away it goes --- include/clasp/core/hashTable.h | 3 ++- include/clasp/core/hashTableEq.h | 2 -- src/core/hashTableEq.cc | 12 ------------ 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index f559f3466b..f0fdd0ea08 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -126,8 +126,9 @@ class HashTable_O : public HashTableBase_O { T_sp setf_gethash_no_write_lock(T_sp key, T_sp value); gc::Fixnum sxhashKey(T_sp key) const; // NOTE: Only call with (read) lock held + KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); + protected: - virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); virtual void sxhashEffect(T_sp key, HashGenerator& hg) const { SUBIMP() }; public: diff --git a/include/clasp/core/hashTableEq.h b/include/clasp/core/hashTableEq.h index e5ed2dbb05..55335d7288 100644 --- a/include/clasp/core/hashTableEq.h +++ b/include/clasp/core/hashTableEq.h @@ -38,8 +38,6 @@ class HashTableEq_O : public HashTable_O { LISP_CLASS(core, CorePkg, HashTableEq_O, "HashTableEq", HashTable_O); DEFAULT_CTOR_DTOR(HashTableEq_O); -protected: - virtual KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); public: static HashTableEq_sp create(uint sz); static HashTableEq_sp create(uint sz, Number_sp rehashSize, double rehashThreshold); diff --git a/src/core/hashTableEq.cc b/src/core/hashTableEq.cc index c346f6210c..ff82ae86d3 100644 --- a/src/core/hashTableEq.cc +++ b/src/core/hashTableEq.cc @@ -76,18 +76,6 @@ HashTableEq_sp HashTableEq_O::createFromPList(List_sp plist, Symbol_sp nilTermin return ht; } -KeyValuePair* HashTableEq_O::searchTable_no_read_lock(T_sp key, cl_index index) { - size_t tableSize = this->_Table.size(); - size_t cur = index; - do { - KeyValuePair& entry = this->_Table[cur]; - if (entry._Key == key) return &entry; - if (entry._Key.no_keyp()) break; - cur = (cur + 1) % tableSize; - } while (cur != index); - return nullptr; -} - bool HashTableEq_O::keyTest(T_sp entryKey, T_sp searchKey) const { return cl__eq(entryKey, searchKey); } void HashTableEq_O::sxhashEffect(T_sp obj, HashGenerator& hg) const { From 5460da76a516cf982b33b0632a5c599c385e9335 Mon Sep 17 00:00:00 2001 From: Bike Date: Thu, 19 Dec 2024 14:34:28 -0500 Subject: [PATCH 20/39] ran static analyzer --- src/analysis/clasp_gc.sif | 32 ++++++------ src/analysis/clasp_gc_cando.sif | 88 ++++++++++++++++----------------- 2 files changed, 56 insertions(+), 64 deletions(-) diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index 61ae2db785..c4638ed829 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -189,19 +189,19 @@ :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_WhatTheEnumsRepresent")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_EnumToSymbol")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_ArchiveSymbolToEnum")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_EnumToArchiveSymbol")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_SymbolToEnum")} {class-kind :stamp-name "STAMPWTAG_llvmo__Attribute_O" :stamp-key "llvmo::Attribute_O" @@ -3876,7 +3876,7 @@ {fixed-field :offset-type-cxx-identifier "RAW_POINTER_OFFSET" :offset-ctype "UnknownType" :offset-base-ctype "llvmo::ExecutionEngine_O" :layout-offset-field-names ("_ptr")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "llvmo::ExecutionEngine_O" :layout-offset-field-names ("_DependentModules")} {class-kind :stamp-name "STAMPWTAG_llvmo__MCSubtargetInfo_O" :stamp-key "llvmo::MCSubtargetInfo_O" @@ -4647,7 +4647,7 @@ {fixed-field :offset-type-cxx-identifier "RAW_POINTER_OFFSET" :offset-ctype "UnknownType" :offset-base-ctype "llvmo::Module_O" :layout-offset-field-names ("_ptr")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "llvmo::Module_O" :layout-offset-field-names ("_UniqueGlobalVariableStrings")} {class-kind :stamp-name "STAMPWTAG_llvmo__Target_O" :stamp-key "llvmo::Target_O" @@ -5674,13 +5674,13 @@ :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Package_O" :layout-offset-field-names ("_InternalSymbols")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Package_O" :layout-offset-field-names ("_ExternalSymbols")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Package_O" :layout-offset-field-names ("_Shadowing")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" @@ -5798,7 +5798,7 @@ :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "clbind::ClassRegistry_O" :layout-offset-field-names ("m_classes")} {class-kind :stamp-name "STAMPWTAG_core__Cons_O" :stamp-key "core::Cons_O" :parent-class "core::T_O" :lisp-class-base "core::T_O" :root-class "core::T_O" @@ -5857,8 +5857,7 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._ClassTable")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" ".charInfo" "._NamesToCharacterIndex")} {fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" :offset-ctype "gctools::tagged_pointer>>" @@ -5947,8 +5946,7 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._NullStream")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._ThePathnameTranslations")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" @@ -5960,12 +5958,10 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._PlusHalf")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._SourceFileIndices")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._PackageNameIndexMap")} {fixed-field :offset-type-cxx-identifier "ctype__Bool" :offset-ctype "_Bool" :offset-base-ctype "core::Lisp" diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index 5a61bc25a6..8362b3ffbc 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -1642,7 +1642,7 @@ :offset-base-ctype "chem::AtomTable_O" :layout-offset-field-names ("_Atoms" "._Vector" "._Contents")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::AtomTable_O" :layout-offset-field-names ("_AtomTableIndexes")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" @@ -1744,7 +1744,7 @@ :offset-base-ctype "chem::RingFinder_O" :layout-offset-field-names ("_edges" "._Vector" "._Contents")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::RingFinder_O" :layout-offset-field-names ("_rings")} {fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" :offset-ctype "gctools::tagged_pointer>>" @@ -2441,11 +2441,11 @@ :offset-base-ctype "chem::AddIonOctree_O" :layout-offset-field-names ("vaAtoms" "._Vector" "._Contents")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::AddIonOctree_O" :layout-offset-field-names ("atomsToResidues")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::AddIonOctree_O" :layout-offset-field-names ("residuesToMolecules")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" @@ -2513,7 +2513,7 @@ :offset-ctype "std::basic_string,std::allocator>" :offset-base-ctype "chem::CandoDatabase_O" :layout-offset-field-names ("_DateUpdated")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::CandoDatabase_O" :layout-offset-field-names ("_Topologys")} {class-kind :stamp-name "STAMPWTAG_chem__AbstractLargeSquareMatrix_O" :stamp-key "chem::AbstractLargeSquareMatrix_O" :parent-class "core::CxxObject_O" @@ -2610,7 +2610,7 @@ :lisp-class-base "chem::FFBaseDb_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::FFParameterBaseDb_O" :layout-offset-field-names ("_Parameters")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" @@ -2621,7 +2621,7 @@ :parent-class "chem::FFParameterBaseDb_O" :lisp-class-base "chem::FFParameterBaseDb_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::FFItorDb_O" :layout-offset-field-names ("_Parameters")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" @@ -2630,7 +2630,7 @@ :parent-class "chem::FFParameterBaseDb_O" :lisp-class-base "chem::FFParameterBaseDb_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::FFStretchDb_O" :layout-offset-field-names ("_Parameters")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" @@ -2644,7 +2644,7 @@ :parent-class "chem::FFParameterBaseDb_O" :lisp-class-base "chem::FFParameterBaseDb_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::FFAngleDb_O" :layout-offset-field-names ("_Parameters")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" @@ -2664,7 +2664,7 @@ :parent-class "chem::FFParameterBaseDb_O" :lisp-class-base "chem::FFParameterBaseDb_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::FFNonbondDb_O" :layout-offset-field-names ("_Parameters")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" @@ -2726,7 +2726,7 @@ :parent-class "chem::FFParameterBaseDb_O" :lisp-class-base "chem::FFParameterBaseDb_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::FFPtorDb_O" :layout-offset-field-names ("_Parameters")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" @@ -3032,7 +3032,7 @@ :parent-class "core::CxxObject_O" :lisp-class-base "core::CxxObject_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::WildElementDict_O" :layout-offset-field-names ("_AtomWildCards")} {class-kind :stamp-name "STAMPWTAG_llvmo__CodeBlock_O" :stamp-key "llvmo::CodeBlock_O" @@ -3082,7 +3082,7 @@ :offset-base-ctype "chem::Structure_Old_ListEntry_O" :layout-offset-field-names ("_SuperposeCoordinates")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::Structure_Old_ListEntry_O" :layout-offset-field-names ("_Data")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_int" :offset-ctype "unsigned int" @@ -3239,7 +3239,7 @@ :offset-base-ctype "chem::Structure_Old_List_O" :layout-offset-field-names ("_RmsCutOff")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::Structure_Old_List_O" :layout-offset-field-names ("_Data")} {class-kind :stamp-name "STAMPWTAG_chem__ReportBase_O" :stamp-key "chem::ReportBase_O" :parent-class "core::CxxObject_O" :lisp-class-base "core::CxxObject_O" @@ -3590,7 +3590,7 @@ :offset-base-ctype "chem::ConformationCollection_O" :layout-offset-field-names ("_AllAtoms" "._Contents")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ConformationCollection_O" :layout-offset-field-names ("_Data")} {class-kind :stamp-name "STAMPWTAG_chem__SuperposableConformationCollection_O" @@ -3611,7 +3611,7 @@ :offset-base-ctype "chem::SuperposableConformationCollection_O" :layout-offset-field-names ("_AllAtoms" "._Contents")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::SuperposableConformationCollection_O" :layout-offset-field-names ("_Data")} {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" @@ -3629,7 +3629,7 @@ :parent-class "core::CxxObject_O" :lisp-class-base "core::CxxObject_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "adapt::ObjectSet_O" :layout-offset-field-names ("_Set")} {class-kind :stamp-name "STAMPWTAG_chem__PdbMonomerConnectivity_O" :stamp-key "chem::PdbMonomerConnectivity_O" :parent-class "core::CxxObject_O" @@ -3670,7 +3670,7 @@ :offset-base-ctype "chem::ConformationExplorerEntry_O" :layout-offset-field-names ("_UniqueEntryIndex")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ConformationExplorerEntry_O" :layout-offset-field-names ("_Binder")} {class-kind :stamp-name "STAMPWTAG_mp__ConditionVariable_O" :stamp-key "mp::ConditionVariable_O" @@ -3740,7 +3740,7 @@ {fixed-field :offset-type-cxx-identifier "ctype_int" :offset-ctype "int" :offset-base-ctype "chem::SpanningLoop_O" :layout-offset-field-names ("iTempInt")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::SpanningLoop_O" :layout-offset-field-names ("_BackSpan")} {class-kind :stamp-name "STAMPWTAG_chem__ProperTorsion_O" :stamp-key "chem::ProperTorsion_O" :parent-class "core::CxxObject_O" :lisp-class-base "core::CxxObject_O" @@ -3981,7 +3981,7 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ChemInfoMatch_O" :layout-offset-field-names ("_Root")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ChemInfoMatch_O" :layout-offset-field-names ("_RingLookup")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" @@ -4055,7 +4055,7 @@ :offset-base-ctype "chem::ConformationExplorer_O" :layout-offset-field-names ("_SuperposeAtomIndexes")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ConformationExplorer_O" :layout-offset-field-names ("_Binder")} {class-kind :stamp-name "STAMPWTAG_chem__ChemInfoGraph_O" :stamp-key "chem::ChemInfoGraph_O" @@ -4065,7 +4065,7 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ChemInfoGraph_O" :layout-offset-field-names ("_Root")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ChemInfoGraph_O" :layout-offset-field-names ("_nodes_to_index")} {fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" @@ -4194,7 +4194,7 @@ :offset-base-ctype "chem::ConformationExplorerEntryStage_O" :layout-offset-field-names ("_FinalCoordinates")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ConformationExplorerEntryStage_O" :layout-offset-field-names ("_Binder")} {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" @@ -4223,7 +4223,7 @@ :offset-base-ctype "chem::Trajectory_O" :layout-offset-field-names ("_Frames" "._Vector" "._Contents")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::Trajectory_O" :layout-offset-field-names ("_Namespace")} {class-kind :stamp-name "STAMPWTAG_chem__CalculatePosition_O" :stamp-key "chem::CalculatePosition_O" :parent-class "core::CxxObject_O" @@ -4300,7 +4300,7 @@ :offset-base-ctype "chem::ConformationCollectionEntry_O" :layout-offset-field-names ("_AllCoordinates")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ConformationCollectionEntry_O" :layout-offset-field-names ("_Data")} {class-kind :stamp-name "STAMPWTAG_chem__ComplexRestraint_O" :stamp-key "chem::ComplexRestraint_O" @@ -4373,7 +4373,7 @@ :parent-class "core::CxxObject_O" :lisp-class-base "core::CxxObject_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::MoleculeGraph_O" :layout-offset-field-names ("_nodes_to_index")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" @@ -4735,7 +4735,7 @@ :offset-base-ctype "chem::ElementsInfo_O" :layout-offset-field-names ("_atomicInfo" "._Vector" "._Contents")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "chem::ElementsInfo_O" :layout-offset-field-names ("_elementFromAtomicSymbol")} {fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" @@ -4857,7 +4857,7 @@ :parent-class "core::CxxObject_O" :lisp-class-base "core::CxxObject_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "adapt::SymbolSet_O" :layout-offset-field-names ("_Symbols")} {class-kind :stamp-name "STAMPWTAG_chem__MapOfMonomerNamesToAtomIndexers_O" :stamp-key "chem::MapOfMonomerNamesToAtomIndexers_O" :parent-class "core::CxxObject_O" @@ -6204,7 +6204,7 @@ :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "clbind::ClassRegistry_O" :layout-offset-field-names ("m_classes")} {class-kind :stamp-name "STAMPWTAG_core__ClassHolder_O" :stamp-key "core::ClassHolder_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" @@ -6230,19 +6230,19 @@ :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_WhatTheEnumsRepresent")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_EnumToSymbol")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_ArchiveSymbolToEnum")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_EnumToArchiveSymbol")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::SymbolToEnumConverter_O" :layout-offset-field-names ("_SymbolToEnum")} {class-kind :stamp-name "STAMPWTAG_llvmo__Attribute_O" :stamp-key "llvmo::Attribute_O" @@ -9515,7 +9515,7 @@ {fixed-field :offset-type-cxx-identifier "RAW_POINTER_OFFSET" :offset-ctype "UnknownType" :offset-base-ctype "llvmo::ExecutionEngine_O" :layout-offset-field-names ("_ptr")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "llvmo::ExecutionEngine_O" :layout-offset-field-names ("_DependentModules")} {class-kind :stamp-name "STAMPWTAG_llvmo__Type_O" :stamp-key "llvmo::Type_O" @@ -9807,7 +9807,7 @@ {fixed-field :offset-type-cxx-identifier "RAW_POINTER_OFFSET" :offset-ctype "UnknownType" :offset-base-ctype "llvmo::Module_O" :layout-offset-field-names ("_ptr")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "llvmo::Module_O" :layout-offset-field-names ("_UniqueGlobalVariableStrings")} {class-kind :stamp-name "STAMPWTAG_llvmo__Target_O" :stamp-key "llvmo::Target_O" @@ -10542,13 +10542,13 @@ :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Package_O" :layout-offset-field-names ("_InternalSymbols")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Package_O" :layout-offset-field-names ("_ExternalSymbols")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Package_O" :layout-offset-field-names ("_Shadowing")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" @@ -12426,8 +12426,7 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._ClassTable")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" ".charInfo" "._NamesToCharacterIndex")} {fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" :offset-ctype "gctools::tagged_pointer>>" @@ -12516,8 +12515,7 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._NullStream")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._ThePathnameTranslations")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" @@ -12529,12 +12527,10 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._PlusHalf")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._SourceFileIndices")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._PackageNameIndexMap")} {fixed-field :offset-type-cxx-identifier "ctype__Bool" :offset-ctype "_Bool" :offset-base-ctype "core::Lisp" From ed8834364c018c1d9fea75fcf9f78e80241eb96d Mon Sep 17 00:00:00 2001 From: Bike Date: Thu, 19 Dec 2024 14:53:00 -0500 Subject: [PATCH 21/39] actually delete blocked constructors don't need this skulduggery. --- include/clasp/gctools/gcvector.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/clasp/gctools/gcvector.h b/include/clasp/gctools/gcvector.h index 1ad588fce0..855c3009c5 100644 --- a/include/clasp/gctools/gcvector.h +++ b/include/clasp/gctools/gcvector.h @@ -48,9 +48,9 @@ template class GCVector_moveable : public GCContainer { typedef T* iterator; typedef T const* const_iterator; -private: - GCVector_moveable(const GCVector_moveable& that); // disable copy ctor - GCVector_moveable& operator=(const GCVector_moveable&); // disable assignment +public: + GCVector_moveable(const GCVector_moveable&) = delete; + GCVector_moveable& operator=(const GCVector_moveable&) = delete; public: value_type* data() { return &this->_Data[0]; }; From 534600452fc753ee8b7d4c64623ffc151af57076 Mon Sep 17 00:00:00 2001 From: Bike Date: Sat, 21 Dec 2024 12:32:28 -0500 Subject: [PATCH 22/39] Delete rotten hash table debugging code --- include/clasp/core/hashTable.h | 23 +---------------------- src/core/hashTable.cc | 28 ---------------------------- src/gctools/gcFunctions.cc | 13 ------------- src/koga/config-header.lisp | 1 - src/koga/configure.lisp | 5 ----- 5 files changed, 1 insertion(+), 69 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index f0fdd0ea08..89269be9f7 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -33,8 +33,6 @@ THE SOFTWARE. #include #include -// #define DEBUG_HASH_TABLE_DEBUG - namespace core { double maybeFixRehashThreshold(double rt); #define DEFAULT_REHASH_THRESHOLD 0.7 @@ -68,17 +66,8 @@ class HashTable_O : public HashTableBase_O { friend T_sp cl__maphash(T_sp function_desig, T_sp hash_table); HashTable_O() - : -#ifdef DEBUG_REHASH_COUNT - _HashTableId(next_hash_table_id()), _RehashCount(0), _InitialSize(0), -#endif - _RehashSize(nil()), _RehashThreshold(maybeFixRehashThreshold(0.7)), _HashTableCount(0) -#ifdef DEBUG_HASH_TABLE_DEBUG - , - _Debug(false), _History(nil()) -#endif + : _RehashSize(nil()), _RehashThreshold(maybeFixRehashThreshold(0.7)), _HashTableCount(0) {}; - // DEFAULT_CTOR_DTOR(HashTable_O); friend class HashTableEq_O; friend class HashTableEql_O; friend class HashTableEqual_O; @@ -88,19 +77,10 @@ class HashTable_O : public HashTableBase_O { friend T_sp cl__clrhash(HashTable_sp hash_table); public: // instance variables here -#ifdef DEBUG_REHASH_COUNT - size_t _HashTableId; - size_t _RehashCount; - size_t _InitialSize; -#endif Number_sp _RehashSize; double _RehashThreshold; gctools::Vec0 _Table; size_t _HashTableCount; -#ifdef DEBUG_HASH_TABLE_DEBUG - bool _Debug; - std::atomic _History; -#endif #ifdef CLASP_THREADS mutable mp::SharedMutex_sp _Mutex; #endif @@ -115,7 +95,6 @@ class HashTable_O : public HashTableBase_O { public: void setupThreadSafeHashTable(); - void setupDebug(); private: void setup(uint sz, Number_sp rehashSize, double rehashThreshold); diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 6f4b07e0b0..c188ebf775 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -186,9 +186,6 @@ CL_DEFUN T_sp cl__make_hash_table(T_sp test, Fixnum_sp size, Number_sp rehash_si size_t isize = clasp_to_int(size); if (isize == 0) isize = 16; -#ifdef DEBUG_REHASH_COUNT - this->_InitialSize = isize; -#endif // clasp_write_string(fmt::format("{}:{} - make_hash_table - fix me so that I grow by powers of 2\n" , __FILE__ , __LINE__ )); if (test == cl::_sym_eq || (cl::_sym_eq->fboundp() && test == cl::_sym_eq->symbolFunction())) { table = HashTableEq_O::create(isize, rehash_size, rehash_threshold); @@ -217,14 +214,6 @@ void HashTable_O::setupThreadSafeHashTable() { #endif } -void HashTable_O::setupDebug() { -#ifdef DEBUG_HASH_TABLE_DEBUG - this->_Debug = true; -#else - // do nothing -#endif -} - CL_LAMBDA(ht); CL_DECLARE(); CL_DOCSTRING(R"dx(hash_table_weakness)dx"); @@ -662,17 +651,6 @@ CL_DEFUN_SETF T_sp setf_gethash(T_sp value, T_sp key, HashTableBase_sp hash_tabl void HashTable_O::rehash_no_lock(bool expandTable) { DEBUG_HASH_TABLE1({ core::clasp_write_string(fmt::format("{}:{} rehash_no_lock\n", __FILE__, __LINE__)); }); ASSERTF(!Number_O::zerop(this->_RehashSize), "RehashSize is zero - it shouldn't be"); -#ifdef DEBUG_HASH_TABLE_DEBUG - if (this->_Debug) { - core::T_sp info = INTERN_(kw, rehash); - T_sp expected; - Cons_sp cell = core::Cons_O::create(info, nil()); - do { - expected = this->_History.load(); - cell->rplacd(expected); - } while (!this->_History.compare_exchange_weak(expected, cell)); - } -#endif gc::Fixnum curSize = this->_Table.size(); ASSERTF(this->_Table.size() != 0, "HashTable is empty in expandHashTable curSize={} this->_Table.size()= {} this shouldn't be", @@ -702,12 +680,6 @@ void HashTable_O::rehash_no_lock(bool expandTable) { this->setf_gethash_no_write_lock(key, value); } } -#ifdef DEBUG_REHASH_COUNT - this->_RehashCount++; - MONITOR(BF("Hash-table rehash id %lu initial-size %lu rehash-number %lu rehash-size %lu oldHashTableCount %lu _HashTableCount " - "%lu\n") % - this->_HashTableId % this->_InitialSize % this->_RehashCount % newSize % oldHashTableCount % this->_HashTableCount); -#endif } void HashTable_O::rehash(bool expandTable) { diff --git a/src/gctools/gcFunctions.cc b/src/gctools/gcFunctions.cc index 2f9749b8dd..7f64750ac9 100644 --- a/src/gctools/gcFunctions.cc +++ b/src/gctools/gcFunctions.cc @@ -767,19 +767,6 @@ bool debugging_configuration(bool setFeatures, bool buildReport, stringstream& s if (buildReport) ss << (fmt::format("DEBUG_FASTGF = {}\n", (debug_fastgf ? "**DEFINED**" : "undefined"))); - bool debug_rehash_count = false; -#ifdef DEBUG_REHASH_COUNT -#ifndef DEBUG_MONITOR -#error "DEBUG_MONITOR must also be enabled if DEBUG_REHASH_COUNT is turned on" -#endif - debug_rehash_count = true; - debugging = true; - if (setFeatures) - features = core::Cons_O::create(_lisp->internKeyword("DEBUG-REHASH_COUNT"), features); -#endif - if (buildReport) - ss << (fmt::format("DEBUG_REHASH_COUNT = {}\n", (debug_rehash_count ? "**DEFINED**" : "undefined"))); - bool debug_jit_log_symbols = false; #ifdef DEBUG_JIT_LOG_SYMBOLS if (!core::global_options->_SilentStartup) { diff --git a/src/koga/config-header.lisp b/src/koga/config-header.lisp index ff695aa842..19180b4e4b 100644 --- a/src/koga/config-header.lisp +++ b/src/koga/config-header.lisp @@ -78,7 +78,6 @@ "DEBUG_TRACK_UNWINDS" (debug-track-unwinds configuration) "DEBUG_NO_UNWIND" (debug-no-unwind configuration) "DEBUG_STARTUP" (debug-startup configuration) - "DEBUG_REHASH_COUNT" (debug-rehash-count configuration) "DEBUG_MONITOR" (debug-monitor configuration) "DEBUG_MONITOR_SUPPORT" (debug-monitor-support configuration) "DEBUG_MEMORY_PROFILE" (debug-memory-profile configuration) diff --git a/src/koga/configure.lisp b/src/koga/configure.lisp index 78ae4694be..e6998c5d8f 100644 --- a/src/koga/configure.lisp +++ b/src/koga/configure.lisp @@ -347,11 +347,6 @@ :initform nil :type boolean :documentation "Generate per-thread logs in /tmp/dispatch-history/** of the slow path of fastgf") - (debug-rehash-count :accessor debug-rehash-count - :initarg :debug-rehash-count - :initform nil - :type boolean - :documentation "Keep track of the number of times each hash table has been rehashed") (debug-monitor :accessor debug-monitor :initarg :debug-monitor :initform nil From 858d7138448b887ce859b7f77fd041448850c64f Mon Sep 17 00:00:00 2001 From: Bike Date: Sat, 21 Dec 2024 23:00:19 -0500 Subject: [PATCH 23/39] Merge weak hash tables into normal hash tables The old implementation is still around for now because there's a lot to delete and I'm not sure these new tables will be scanned correctly for snapshots. --- include/clasp/core/hashTable.h | 67 ++++++-- include/clasp/core/hashTableCustom.h | 4 + include/clasp/core/hashTableEq.h | 3 + include/clasp/core/hashTableEql.h | 4 +- include/clasp/core/hashTableEqual.h | 3 + include/clasp/core/hashTableEqualp.h | 3 + include/clasp/gctools/gcweak.h | 79 +++++++++- src/analysis/clasp_gc.sif | 176 +++++++++++++-------- src/analysis/clasp_gc_cando.sif | 200 ++++++++++++++--------- src/core/hashTable.cc | 227 +++++++++++---------------- src/core/hashTableCustom.cc | 10 +- src/core/hashTableEq.cc | 8 +- src/core/hashTableEql.cc | 12 +- src/core/hashTableEqual.cc | 10 +- src/core/hashTableEqualp.cc | 10 +- src/gctools/gcweak.cc | 59 +++++-- 16 files changed, 534 insertions(+), 341 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index 89269be9f7..bf9b9b0505 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -47,11 +47,56 @@ size_t next_hash_table_id(); namespace core { -class KeyValuePair { +FORWARD(Mapping); +class Mapping_O : public General_O { + LISP_ABSTRACT_CLASS(core, CorePkg, Mapping_O, "Mapping", General_O); public: - core::T_sp _Key; - core::T_sp _Value; - KeyValuePair(T_sp k, T_sp v) : _Key(k), _Value(v){}; + virtual size_t size() const = 0; + virtual Mapping_sp realloc(size_t) const = 0; + virtual gctools::KVPair get(size_t) const = 0; + virtual void setValue(size_t, T_sp) = 0; + virtual void newEntry(size_t, T_sp, T_sp) = 0; + virtual void remove(size_t) = 0; +}; + +FORWARD(StrongMapping); +class StrongMapping_O final : public Mapping_O { + LISP_CLASS(core, CorePkg, StrongMapping_O, "StrongMapping", Mapping_O); +public: + // need typedefs for e.g. sizeof_container + typedef gctools::StrongMapping::value_type value_type; +public: + StrongMapping_O(size_t size) : _Mapping(size) {} + static StrongMapping_sp make(size_t); +public: + gctools::StrongMapping _Mapping; +public: + virtual size_t size() const { return _Mapping.size(); } + virtual Mapping_sp realloc(size_t sz) const { return make(sz); } + virtual gctools::KVPair get(size_t i) const { return _Mapping.get(i); } + virtual void setValue(size_t i, T_sp v) { _Mapping.setValue(i, v); } + virtual void newEntry(size_t i, T_sp k, T_sp v) { _Mapping.newEntry(i, k, v); } + virtual void remove(size_t i) { _Mapping.remove(i); } +}; + +FORWARD(WeakKeyMapping); +class WeakKeyMapping_O final : public Mapping_O { + LISP_CLASS(core, CorePkg, WeakKeyMapping_O, "WeakKeyMapping", Mapping_O); +public: + // need typedefs for e.g. sizeof_container + typedef gctools::EphemeronMapping::value_type value_type; +public: + WeakKeyMapping_O(size_t size) : _Mapping(size) {} + static WeakKeyMapping_sp make(size_t); +public: + gctools::EphemeronMapping _Mapping; +public: + virtual size_t size() const { return _Mapping.size(); } + virtual Mapping_sp realloc(size_t sz) const { return make(sz); } + virtual gctools::KVPair get(size_t i) const { return _Mapping.get(i); } + virtual void setValue(size_t i, T_sp v) { _Mapping.setValue(i, v); } + virtual void newEntry(size_t i, T_sp k, T_sp v) { _Mapping.newEntry(i, k, v); } + virtual void remove(size_t i) { _Mapping.remove(i); } }; FORWARD(HashTable); @@ -68,18 +113,17 @@ class HashTable_O : public HashTableBase_O { HashTable_O() : _RehashSize(nil()), _RehashThreshold(maybeFixRehashThreshold(0.7)), _HashTableCount(0) {}; - friend class HashTableEq_O; - friend class HashTableEql_O; - friend class HashTableEqual_O; - friend class HashTableEqualp_O; - friend class HashTableCustom_O; + HashTable_O(Mapping_sp mapping, + Number_sp rehashSize, double rehashThreshold) + : _RehashSize(rehashSize), _RehashThreshold(maybeFixRehashThreshold(rehashThreshold)), + _Table(mapping), _HashTableCount(0) {} friend T_sp cl__maphash(T_sp function_desig, HashTable_sp hash_table); friend T_sp cl__clrhash(HashTable_sp hash_table); public: // instance variables here Number_sp _RehashSize; double _RehashThreshold; - gctools::Vec0 _Table; + Mapping_sp _Table; size_t _HashTableCount; #ifdef CLASP_THREADS mutable mp::SharedMutex_sp _Mutex; @@ -97,7 +141,6 @@ class HashTable_O : public HashTableBase_O { void setupThreadSafeHashTable(); private: - void setup(uint sz, Number_sp rehashSize, double rehashThreshold); uint resizeEmptyTable_no_lock(size_t sz); uint calculateHashTableCount() const; @@ -105,7 +148,7 @@ class HashTable_O : public HashTableBase_O { T_sp setf_gethash_no_write_lock(T_sp key, T_sp value); gc::Fixnum sxhashKey(T_sp key) const; // NOTE: Only call with (read) lock held - KeyValuePair* searchTable_no_read_lock(T_sp key, cl_index index); + std::optional searchTable_no_read_lock(T_sp key, cl_index index); protected: virtual void sxhashEffect(T_sp key, HashGenerator& hg) const { SUBIMP() }; diff --git a/include/clasp/core/hashTableCustom.h b/include/clasp/core/hashTableCustom.h index 709e33d65e..7bc6292d69 100644 --- a/include/clasp/core/hashTableCustom.h +++ b/include/clasp/core/hashTableCustom.h @@ -37,8 +37,12 @@ FORWARD(HashTableCustom); class HashTableCustom_O : public HashTable_O { LISP_CLASS(core, CorePkg, HashTableCustom_O, "HashTableCustom", HashTable_O); DEFAULT_CTOR_DTOR(HashTableCustom_O); + HashTableCustom_O(Mapping_sp map, Number_sp rhsize, double rhthresh, Function_sp ncomparator, Function_sp nhasher) + : HashTable_O(map, rhsize, rhthresh), + comparator(ncomparator), hasher(nhasher) {} public: + static HashTableCustom_sp create(Mapping_sp, Number_sp, double, Function_sp, Function_sp); static HashTableCustom_sp create(uint sz, Number_sp rehashSize, double rehashThreshold, Function_sp comparator, Function_sp hasher); diff --git a/include/clasp/core/hashTableEq.h b/include/clasp/core/hashTableEq.h index 55335d7288..ddaa92b448 100644 --- a/include/clasp/core/hashTableEq.h +++ b/include/clasp/core/hashTableEq.h @@ -37,8 +37,11 @@ FORWARD(HashTableEq); class HashTableEq_O : public HashTable_O { LISP_CLASS(core, CorePkg, HashTableEq_O, "HashTableEq", HashTable_O); DEFAULT_CTOR_DTOR(HashTableEq_O); + HashTableEq_O(Mapping_sp map, Number_sp rhsize, double rhthresh) + : HashTable_O(map, rhsize, rhthresh) {} public: + static HashTableEq_sp create(Mapping_sp mapping, Number_sp rehashSize, double rehashThreshold); static HashTableEq_sp create(uint sz); static HashTableEq_sp create(uint sz, Number_sp rehashSize, double rehashThreshold); static HashTableEq_sp create_default(); diff --git a/include/clasp/core/hashTableEql.h b/include/clasp/core/hashTableEql.h index 4ab88833b8..0eba598e54 100644 --- a/include/clasp/core/hashTableEql.h +++ b/include/clasp/core/hashTableEql.h @@ -37,9 +37,11 @@ FORWARD(HashTableEql); class HashTableEql_O : public HashTable_O { LISP_CLASS(core, CorePkg, HashTableEql_O, "HashTableEql", HashTable_O); DEFAULT_CTOR_DTOR(HashTableEql_O); + HashTableEql_O(Mapping_sp map, Number_sp rhsize, double rhthresh) + : HashTable_O(map, rhsize, rhthresh) {} -private: // instance variables here public: + static HashTableEql_sp create(Mapping_sp mapping, Number_sp rehashSize, double rehashThreshold); static HashTableEql_sp create(uint sz, Number_sp rehashSize, double rehashThreshold); static HashTableEql_sp create_default(); diff --git a/include/clasp/core/hashTableEqual.h b/include/clasp/core/hashTableEqual.h index 7a3345177b..77d7f6ae21 100644 --- a/include/clasp/core/hashTableEqual.h +++ b/include/clasp/core/hashTableEqual.h @@ -36,8 +36,11 @@ namespace core { FORWARD(HashTableEqual); class HashTableEqual_O : public HashTable_O { LISP_CLASS(core, CorePkg, HashTableEqual_O, "HashTableEqual", HashTable_O); + HashTableEqual_O(Mapping_sp map, Number_sp rhsize, double rhthresh) + : HashTable_O(map, rhsize, rhthresh) {} public: + static HashTableEqual_sp create(Mapping_sp, Number_sp, double); static HashTableEqual_sp create(uint sz, Number_sp rehashSize, double rehashThreshold); static HashTableEqual_sp create_default(); diff --git a/include/clasp/core/hashTableEqualp.h b/include/clasp/core/hashTableEqualp.h index 9d25aeb5b4..7ad248120c 100644 --- a/include/clasp/core/hashTableEqualp.h +++ b/include/clasp/core/hashTableEqualp.h @@ -37,8 +37,11 @@ FORWARD(HashTableEqualp); class HashTableEqualp_O : public HashTable_O { LISP_CLASS(core, CorePkg, HashTableEqualp_O, "HashTableEqualp", HashTable_O); DEFAULT_CTOR_DTOR(HashTableEqualp_O); + HashTableEqualp_O(Mapping_sp map, Number_sp rhsize, double rhthresh) + : HashTable_O(map, rhsize, rhthresh) {} public: + static HashTableEqualp_sp create(Mapping_sp, Number_sp, double); static HashTableEqualp_sp create(uint sz, Number_sp rehashSize, double rehashThreshold); static HashTableEqualp_sp create_default(); diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index 463b0a45d6..6a9738a257 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -407,6 +407,12 @@ struct WeakPointer { #endif // lacking real support, we have not-actually-weak pointers. }; +// Used below in hash maps and ephemerons. +struct KVPair { + core::T_sp key; + core::T_sp value; +}; + // On Boehm this is not a real ephemeron - it's a weak pointer to the key, // and a strong pointer to the value that happens to get wiped with the key. // To see the difference, imagine having two inverse ephemerons {V1, V2} and @@ -425,8 +431,23 @@ struct WeakPointer { struct Ephemeron { public: Ephemeron(core::T_sp key, core::T_sp value); - std::optional key() const; - std::optional value() const; + // If the ephemeron is valid, return its key and value. + // Otherwise return (deleted, deleted). + KVPair get() const; + std::optional key() const { + auto p = get(); + if (p.key.deletedp()) return std::nullopt; + else return p.key; + } + std::optional value() const { + auto p = get(); + if (p.key.deletedp()) return std::nullopt; + else return p.value; + } + // Caller must ensure that the key is otherwise live, + // or else the value could remain while the key dies (memory leak) + void setValue(core::T_sp v) { _value = v; } + void reinit(core::T_sp k, core::T_sp v); public: #ifdef USE_BOEHM GC_hidden_pointer _key; @@ -437,13 +458,59 @@ struct Ephemeron { #ifdef USE_BOEHM private: struct result_helper_s { - result_helper_s(const Ephemeron* e) : eph(e), result() {} + result_helper_s(const Ephemeron* e) : eph(e) {} const Ephemeron* eph; - std::optional result; + KVPair result; }; - static void* key_helper(void*); - static void* value_helper(void*); + static void* get_helper(void*); #endif }; +// These Mapping objects are used in hash tables. + +// A strong mapping isn't weak at all, obviously, but +// this is the degenerate case. +struct StrongMapping { +public: + typedef GCArray_moveable vector_type; + // for e.g. sizeof_container + typedef typename vector_type::value_type value_type; +private: + static const KVPair initKV; +public: + StrongMapping(size_t size) : _Data(size, initKV) {} +public: + vector_type _Data; +public: + size_t size() const { return _Data.length(); } + KVPair get(size_t i) const { return _Data[i]; } + void setValue(size_t i, core::T_sp v) { _Data[i].value = v; } + void newEntry(size_t i, core::T_sp k, core::T_sp v) { + _Data[i].key = k; + _Data[i].value = v; + } + void remove(size_t i) { + _Data[i].key = core::T_sp(tag_deleted()); + _Data[i].value = core::T_sp(tag_deleted()); + } +}; + +struct EphemeronMapping { +public: + typedef GCArray_moveable vector_type; + typedef typename vector_type::value_type value_type; +private: + static const Ephemeron initEph; +public: + EphemeronMapping(size_t size) : _Data(size, initEph) {} +public: + vector_type _Data; +public: + size_t size() const { return _Data.length(); } + KVPair get(size_t i) const { return _Data[i].get(); } + void setValue(size_t i, core::T_sp v) { _Data[i].setValue(v); } + void newEntry(size_t i, core::T_sp k, core::T_sp v) { _Data[i].reinit(k, v); } + void remove(size_t i) { _Data[i].reinit(deleted(), deleted()); } +}; + }; // namespace gctools diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index c4638ed829..2b782965e1 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -49,11 +49,11 @@ "core::SimpleVector_byte32_t_O" "core::AnsiStream_O" "core::KeywordArgument" "llvmo::Module_O" "core::SingleFloat_dummy_O" "llvmo::DIExpression_O" "llvmo::InvokeInst_O" "core::StrNs_O" - "comp::GlobalFunInfo_O" "clasp_ffi::ForeignData_O" "llvmo::CallInst_O" - "core::BytecodeAstDecls_O" "core::DoubleFloat_O" - "core::ComplexVector_short_float_O" "core::DebuggerFrame_O" - "comp::LocalMacroInfo_O" "comp::LexFixup_O" "core::StringStream_O" - "llvmo::LibraryBase_O" "core::MDArray_int32_t_O" + "comp::GlobalFunInfo_O" "core::Mapping_O" "llvmo::CallInst_O" + "clasp_ffi::ForeignData_O" "core::BytecodeAstDecls_O" + "core::DoubleFloat_O" "core::ComplexVector_short_float_O" + "core::DebuggerFrame_O" "comp::LocalMacroInfo_O" "comp::LexFixup_O" + "core::StringStream_O" "llvmo::LibraryBase_O" "core::MDArray_int32_t_O" "asttooling::AsttoolingExposer_O" "llvmo::IntegerType_O" "comp::GlobalMacroInfo_O" "core::MDArray_int64_t_O" "core::SimpleMDArray_size_t_O" "comp::VariableCellInfo_O" @@ -73,7 +73,7 @@ "core::Unused_dummy_O" "llvmo::DWARFContext_O" "core::HashTableEqual_O" "llvmo::Triple_O" "core::SimpleMDArray_byte64_t_O" "core::BitVectorNs_O" "core::CoreExposer_O" "core::BytecodeDebugVars_O" - "comp::JumpIfSuppliedFixup_O" "core::KeyValuePair" "llvmo::NamedMDNode_O" + "comp::JumpIfSuppliedFixup_O" "llvmo::NamedMDNode_O" "core::SimpleVector_byte16_t_O" "llvmo::ThreadSafeContext_O" "llvmo::TargetMachine_O" "core::SimpleVector_byte64_t_O" "core::SimpleCoreFunGenerator_O" "llvmo::Value_O" @@ -82,8 +82,9 @@ "core::BytecodeDebugMacroexpansion_O" "llvmo::ConstantInt_O" "comp::SpecialVarInfo_O" "core::SimpleMDArray_int16_t_O" "comp::ControlLabelFixup_O" "llvmo::StructLayout_O" - "core::SimpleMDArrayT_O" "llvmo::LoadInst_O" "llvmo::ConstantStruct_O" - "core::Exposer_O" "core::DirectoryIterator_O" "core::MDArray_byte2_t_O" + "core::SimpleMDArrayT_O" "core::StrongMapping_O" "llvmo::LoadInst_O" + "llvmo::ConstantStruct_O" "core::Exposer_O" "gctools::Ephemeron" + "core::DirectoryIterator_O" "core::MDArray_byte2_t_O" "llvmo::DISubroutineType_O" "comp::LabelFixup_O" "comp::Cfunction_O" "llvmo::MetadataAsValue_O" "core::SimpleBitVector_O" "core::SimpleVector_int8_t_O" "llvmo::ResumeInst_O" "llvmo::Function_O" @@ -128,29 +129,30 @@ "llvmo::LandingPadInst_O" "core::ImmobileObject_O" "core::Function_O" "core::SimpleMDArray_int2_t_O" "core::HashTableEql_O" "comp::ConstantInfo_O" "mp::ConditionVariable_O" "core::Real_O" - "core::Lisp" "core::MDArray_byte8_t_O" "core::BytecodeAstThe_O" - "core::FuncallableInstanceCreator_O" "core::StringOutputStream_O" - "llvmo::AttributeSet_O" "llvmo::AtomicRMWInst_O" "comp::Module_O" - "llvmo::MDBuilder_O" "core::SimpleVector_O" "llvmo::DISubprogram_O" - "core::SymbolStorage" "llvmo::ArrayType_O" - "core::SimpleMDArray_int64_t_O" "core::SimpleString_O" - "llvmo::DIVariable_O" "core::SimpleMDArray_byte2_t_O" - "llvmo::BlockAddress_O" "llvmo::DICompositeType_O" - "llvmo::MCSubtargetInfo_O" "core::DerivableCxxClassCreator_O" - "core::HashTableEq_O" "core::HashTableEqualp_O" - "asttooling::PresumedLoc_O" "core::ConcatenatedStream_O" "comp::Fixup_O" - "core::LexDynEnv_O" "core::FuncallableInstance_O" "clbind::detail::edge" + "core::Lisp" "core::MDArray_byte8_t_O" "gctools::KVPair" + "core::BytecodeAstThe_O" "core::FuncallableInstanceCreator_O" + "core::StringOutputStream_O" "llvmo::AttributeSet_O" + "llvmo::AtomicRMWInst_O" "comp::Module_O" "llvmo::MDBuilder_O" + "core::SimpleVector_O" "llvmo::DISubprogram_O" "core::SymbolStorage" + "llvmo::ArrayType_O" "core::SimpleMDArray_int64_t_O" + "core::SimpleString_O" "llvmo::DIVariable_O" + "core::SimpleMDArray_byte2_t_O" "llvmo::BlockAddress_O" + "llvmo::DICompositeType_O" "llvmo::MCSubtargetInfo_O" + "core::DerivableCxxClassCreator_O" "core::HashTableEq_O" + "core::HashTableEqualp_O" "asttooling::PresumedLoc_O" + "core::ConcatenatedStream_O" "comp::Fixup_O" "core::LexDynEnv_O" + "core::FuncallableInstance_O" "clbind::detail::edge" "core::SynonymStream_O" "core::BytecodeModule_O" "core::Ratio_O" "core::MDArray_int2_t_O" "core::ComplexVector_byte2_t_O" "llvmo::ExecutionEngine_O" "core::ClassRepCreator_O" "core::MDArray_long_float_O" "core::SimpleVector_int16_t_O" - "llvmo::Attribute_O" "core::DerivableCxxObject_O" - "core::SymbolToEnumConverter_O" "llvmo::SwitchInst_O" - "core::SingleDispatchGenericFunction_O" "core::ComplexVector_int32_t_O" - "core::ComplexVector_byte4_t_O" "asttooling::SourceLocation_O" - "core::LogicalPathname_O" "llvmo::TargetSubtargetInfo_O" - "core::SimpleVector_double_O" "core::CFileStream_O" - "core::SimpleMDArray_byte32_t_O" "core::Bignum_O" + "llvmo::Attribute_O" "core::WeakKeyMapping_O" + "core::DerivableCxxObject_O" "core::SymbolToEnumConverter_O" + "llvmo::SwitchInst_O" "core::SingleDispatchGenericFunction_O" + "core::ComplexVector_int32_t_O" "core::ComplexVector_byte4_t_O" + "asttooling::SourceLocation_O" "core::LogicalPathname_O" + "llvmo::TargetSubtargetInfo_O" "core::SimpleVector_double_O" + "core::CFileStream_O" "core::SimpleMDArray_byte32_t_O" "core::Bignum_O" "llvmo::LLVMTargetMachine_O" "core::ClassHolder_O" "core::ComplexVector_byte32_t_O" "llvmo::UnaryInstruction_O" "llvmo::GlobalValue_O" "llvmo::PointerType_O" "core::TwoWayStream_O")} @@ -4764,6 +4766,37 @@ :offset-base-ctype "core::DebuggerFrame_O" :layout-offset-field-names ("down")} {fixed-field :offset-type-cxx-identifier "ctype__Bool" :offset-ctype "_Bool" :offset-base-ctype "core::DebuggerFrame_O" :layout-offset-field-names ("is_xep")} +{class-kind :stamp-name "STAMPWTAG_core__Mapping_O" :stamp-key "core::Mapping_O" + :parent-class "core::General_O" :lisp-class-base "core::General_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__WeakKeyMapping_O" :stamp-key "core::WeakKeyMapping_O" + :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{variable-array0 :offset-base-ctype "core::WeakKeyMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::Ephemeron" :offset-base-ctype "core::WeakKeyMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "ctype_unsigned_long" + :fixup-ctype-offset-type-key "unsigned long" :fixup-ctype-key "gctools::Ephemeron" + :layout-offset-field-names ("_key")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::Ephemeron" :layout-offset-field-names ("_value")} +{class-kind :stamp-name "STAMPWTAG_core__StrongMapping_O" :stamp-key "core::StrongMapping_O" + :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{variable-array0 :offset-base-ctype "core::StrongMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::KVPair" :offset-base-ctype "core::StrongMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::KVPair" :layout-offset-field-names ("key")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::KVPair" :layout-offset-field-names ("value")} {class-kind :stamp-name "STAMPWTAG_core__RandomState_O" :stamp-key "core::RandomState_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} @@ -4874,10 +4907,9 @@ :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_RehashSize")} {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTable_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" @@ -4893,10 +4925,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableEqualp_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_HashTableCount")} @@ -4912,10 +4943,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableEq_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_HashTableCount")} @@ -4931,10 +4961,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableEql_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_HashTableCount")} @@ -4950,10 +4979,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableEqual_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_HashTableCount")} @@ -4970,10 +4998,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableCustom_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_HashTableCount")} @@ -6095,6 +6122,22 @@ :length-field-names ("_MaybeSignedLength") :end-field-names ("_MaybeSignedLength")} {variable-field-only :offset-type-cxx-identifier "ctype_signed_char" :fixup-type "signed char"} +{container-kind :stamp-name "STAMPWTAG_gctools__GCArray_moveable_gctools__Ephemeron_" + :stamp-key "gctools::GCArray_moveable" + :parent-class "gctools::GCContainer" :lisp-class-base nil + :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} +{variable-array0 :offset-base-ctype "gctools::GCArray_moveable" + :field-names ("_Data")} +{variable-capacity :ctype "gctools::Ephemeron" + :offset-base-ctype "gctools::GCArray_moveable" + :length-field-names ("_MaybeSignedLength") + :end-field-names ("_MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "ctype_unsigned_long" + :fixup-ctype-offset-type-key "unsigned long" :fixup-ctype-key "gctools::Ephemeron" + :layout-offset-field-names ("_key")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::Ephemeron" :layout-offset-field-names ("_value")} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_std__pair_gctools__smart_ptr_core__T_O__gctools__smart_ptr_core__T_O___" :stamp-key "gctools::GCVector_moveable,gctools::smart_ptr>>" :parent-class "gctools::GCContainer" :lisp-class-base nil @@ -6123,21 +6166,6 @@ :length-field-names ("_MaybeSignedLength") :end-field-names ("_MaybeSignedLength")} {variable-field-only :offset-type-cxx-identifier "ctype_unsigned_char" :fixup-type "unsigned char"} -{container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_core__KeyValuePair_" - :stamp-key "gctools::GCVector_moveable" - :parent-class "gctools::GCContainer" :lisp-class-base nil - :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} -{variable-array0 :offset-base-ctype "gctools::GCVector_moveable" - :field-names ("_Data")} -{variable-capacity :ctype "core::KeyValuePair" - :offset-base-ctype "gctools::GCVector_moveable" - :length-field-names ("_Capacity") :end-field-names ("_End")} -{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :fixup-ctype-offset-type-key "gctools::smart_ptr" - :fixup-ctype-key "core::KeyValuePair" :layout-offset-field-names ("_Key")} -{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :fixup-ctype-offset-type-key "gctools::smart_ptr" - :fixup-ctype-key "core::KeyValuePair" :layout-offset-field-names ("_Value")} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_gctools__smart_ptr_core__Symbol_O__" :stamp-key "gctools::GCVector_moveable>" :parent-class "gctools::GCContainer" :lisp-class-base nil @@ -6349,6 +6377,22 @@ :length-field-names ("_MaybeSignedLength") :end-field-names ("_MaybeSignedLength")} {variable-field-only :offset-type-cxx-identifier "ctype_unsigned_long" :fixup-type "unsigned long"} +{container-kind :stamp-name "STAMPWTAG_gctools__GCArray_moveable_gctools__KVPair_" + :stamp-key "gctools::GCArray_moveable" + :parent-class "gctools::GCContainer" :lisp-class-base nil + :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} +{variable-array0 :offset-base-ctype "gctools::GCArray_moveable" + :field-names ("_Data")} +{variable-capacity :ctype "gctools::KVPair" + :offset-base-ctype "gctools::GCArray_moveable" + :length-field-names ("_MaybeSignedLength") + :end-field-names ("_MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::KVPair" :layout-offset-field-names ("key")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::KVPair" :layout-offset-field-names ("value")} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_std__pair_gctools__smart_ptr_core__Symbol_O__gctools__smart_ptr_core__T_O___" :stamp-key "gctools::GCVector_moveable,gctools::smart_ptr>>" :parent-class "gctools::GCContainer" :lisp-class-base nil diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index 8362b3ffbc..a2564bb610 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -87,15 +87,16 @@ "core::KeywordArgument" "llvmo::Module_O" "llvmo::DIExpression_O" "core::SingleFloat_dummy_O" "chem::FFNonbond_O" "chem::Trajectory_O" "llvmo::InvokeInst_O" "chem::RestraintFixedNonbond_O" "chem::AGVertex_O" - "core::StrNs_O" "comp::GlobalFunInfo_O" "clasp_ffi::ForeignData_O" - "llvmo::CallInst_O" "chem::VirtualAtom_O" "core::BytecodeAstDecls_O" - "chem::AfterMatchBondToAtomTest_O" "core::DoubleFloat_O" - "core::ComplexVector_short_float_O" "core::DebuggerFrame_O" - "chem::ConformationExplorerEntryStage_O" "adapt::AdaptExposer_O" - "comp::LocalMacroInfo_O" "chem::FrameRecognizer_O" - "chem::CalculatePositionAlongBond_O" "comp::LexFixup_O" - "core::StringStream_O" "llvmo::LibraryBase_O" "core::MDArray_int32_t_O" - "adapt::SymbolList_O" "chem::CalculatePositionUsingInternals_O" + "core::StrNs_O" "comp::GlobalFunInfo_O" "core::Mapping_O" + "clasp_ffi::ForeignData_O" "llvmo::CallInst_O" "chem::VirtualAtom_O" + "core::BytecodeAstDecls_O" "chem::AfterMatchBondToAtomTest_O" + "core::DoubleFloat_O" "core::ComplexVector_short_float_O" + "core::DebuggerFrame_O" "chem::ConformationExplorerEntryStage_O" + "adapt::AdaptExposer_O" "comp::LocalMacroInfo_O" + "chem::FrameRecognizer_O" "chem::CalculatePositionAlongBond_O" + "comp::LexFixup_O" "core::StringStream_O" "llvmo::LibraryBase_O" + "core::MDArray_int32_t_O" "adapt::SymbolList_O" + "chem::CalculatePositionUsingInternals_O" "chem::EnergyPeriodicBoundaryConditionsNonbond_O" "asttooling::AsttoolingExposer_O" "chem::HybridizationInfo" "llvmo::IntegerType_O" "chem::AtomInfo" "chem::EnergyDihedral_O" @@ -128,31 +129,31 @@ "core::CoreExposer_O" "core::BytecodeDebugVars_O" "chem::EnergyRigidBodyComponent_O" "core::BitVectorNs_O" "chem::AtomIdMap_O" "comp::JumpIfSuppliedFixup_O" - "geom::SimpleVectorCoordinate_O" "core::KeyValuePair" "chem::FFItor_O" - "llvmo::NamedMDNode_O" "core::SimpleVector_byte16_t_O" - "chem::ChemInfoGraph_O" "chem::EnergyOutOfZPlane" - "core::SimpleVector_byte64_t_O" "core::SimpleCoreFunGenerator_O" - "chem::EnergyPointToLineRestraint_O" "llvmo::ThreadSafeContext_O" - "core::SimpleBaseString_O" "core::Test_O" "llvmo::TargetMachine_O" - "llvmo::Value_O" "llvmo::Metadata_O" "chem::Bond_O" - "core::BytecodeDebugInfo_O" "chem::SuperposableConformationCollection_O" - "core::MDArray_O" "units::UnitsExposer_O" "chem::CoordinateSystem_O" + "geom::SimpleVectorCoordinate_O" "chem::FFItor_O" "llvmo::NamedMDNode_O" + "core::SimpleVector_byte16_t_O" "chem::ChemInfoGraph_O" + "chem::EnergyOutOfZPlane" "core::SimpleVector_byte64_t_O" + "core::SimpleCoreFunGenerator_O" "chem::EnergyPointToLineRestraint_O" + "llvmo::ThreadSafeContext_O" "core::SimpleBaseString_O" "core::Test_O" + "llvmo::TargetMachine_O" "llvmo::Value_O" "llvmo::Metadata_O" + "chem::Bond_O" "core::BytecodeDebugInfo_O" + "chem::SuperposableConformationCollection_O" "core::MDArray_O" + "units::UnitsExposer_O" "chem::CoordinateSystem_O" "chem::AtomReference_O" "clbind::ClassRep_O" "core::BytecodeDebugMacroexpansion_O" "chem::EnergyAngle" "chem::RigidBodyEnergyFunction_O" "llvmo::ConstantInt_O" "comp::SpecialVarInfo_O" "core::SimpleMDArray_int16_t_O" "chem::Logical_O" "comp::ControlLabelFixup_O" "llvmo::StructLayout_O" "core::SimpleMDArrayT_O" "chem::ConformationExplorer_O" - "chem::BondList_O" "llvmo::LoadInst_O" "core::Exposer_O" - "llvmo::ConstantStruct_O" "chem::MacroModelFile_O" - "core::MDArray_byte2_t_O" "core::DirectoryIterator_O" "chem::Angle_O" - "llvmo::DISubroutineType_O" "chem::EnergyComponents_O" - "comp::LabelFixup_O" "comp::Cfunction_O" "llvmo::MetadataAsValue_O" - "kinematics::JumpJoint_O" "core::SimpleBitVector_O" - "core::SimpleVector_int8_t_O" "chem::CDNode_O" "llvmo::ResumeInst_O" - "llvmo::Function_O" "llvmo::DIType_O" "chem::AddIonOctree_O" - "kinematics::StubJoint_O" "chem::ZMatrixEntry_O" "comp::TagInfo_O" - "geom::BoundingCuboid_O" "core::Readtable_O" + "core::StrongMapping_O" "chem::BondList_O" "llvmo::LoadInst_O" + "core::Exposer_O" "llvmo::ConstantStruct_O" "gctools::Ephemeron" + "chem::MacroModelFile_O" "core::MDArray_byte2_t_O" + "core::DirectoryIterator_O" "chem::Angle_O" "llvmo::DISubroutineType_O" + "chem::EnergyComponents_O" "comp::LabelFixup_O" "comp::Cfunction_O" + "llvmo::MetadataAsValue_O" "kinematics::JumpJoint_O" + "core::SimpleBitVector_O" "core::SimpleVector_int8_t_O" "chem::CDNode_O" + "llvmo::ResumeInst_O" "llvmo::Function_O" "llvmo::DIType_O" + "chem::AddIonOctree_O" "kinematics::StubJoint_O" "chem::ZMatrixEntry_O" + "comp::TagInfo_O" "geom::BoundingCuboid_O" "core::Readtable_O" "chem::CalculatePositionRelativeToOrigin_O" "chem::AtomIndexer_O" "chem::ChemInfoMatch_O" "chem::Restraint_O" "units::Quantity_O" "llvmo::IRBuilder_O" "chem::AtomPdbRec" "llvmo::ClaspJIT_O" @@ -215,8 +216,8 @@ "core::HashTableEql_O" "chem::AtomTable_O" "comp::ConstantInfo_O" "chem::SpanningLoop_O" "chem::PdbReader_O" "mp::ConditionVariable_O" "chem::ConformationExplorerEntry_O" "core::Real_O" "core::Lisp" - "core::MDArray_byte8_t_O" "core::FuncallableInstanceCreator_O" - "chem::BondListMatchNode_O" "core::BytecodeAstThe_O" + "core::MDArray_byte8_t_O" "gctools::KVPair" "chem::BondListMatchNode_O" + "core::FuncallableInstanceCreator_O" "core::BytecodeAstThe_O" "core::StringOutputStream_O" "units::Dimension_O" "chem::BondMatcher_O" "llvmo::AttributeSet_O" "llvmo::AtomicRMWInst_O" "chem::PdbMonomerConnectivity_O" "chem::RigidBodyNonbondCrossTerm" @@ -238,15 +239,16 @@ "chem::FixedNonbondRestraint" "llvmo::ExecutionEngine_O" "core::ClassRepCreator_O" "core::MDArray_long_float_O" "core::SimpleVector_int16_t_O" "llvmo::Attribute_O" - "core::DerivableCxxObject_O" "llvmo::SwitchInst_O" - "core::SymbolToEnumConverter_O" "chem::RestrainedPiBond_O" - "chem::ConformationCollection_O" "core::SingleDispatchGenericFunction_O" - "core::ComplexVector_int32_t_O" "chem::StepReport_O" "geom::Color_O" - "chem::FFVdw_O" "core::ComplexVector_byte4_t_O" - "asttooling::SourceLocation_O" "core::LogicalPathname_O" - "llvmo::TargetSubtargetInfo_O" "core::SimpleVector_double_O" - "chem::Root_O" "core::CFileStream_O" "core::SimpleMDArray_byte32_t_O" - "core::Bignum_O" "llvmo::LLVMTargetMachine_O" "core::ClassHolder_O" + "core::DerivableCxxObject_O" "core::WeakKeyMapping_O" + "llvmo::SwitchInst_O" "core::SymbolToEnumConverter_O" + "chem::RestrainedPiBond_O" "chem::ConformationCollection_O" + "core::SingleDispatchGenericFunction_O" "core::ComplexVector_int32_t_O" + "chem::StepReport_O" "geom::Color_O" "chem::FFVdw_O" + "core::ComplexVector_byte4_t_O" "asttooling::SourceLocation_O" + "core::LogicalPathname_O" "llvmo::TargetSubtargetInfo_O" + "core::SimpleVector_double_O" "chem::Root_O" "core::CFileStream_O" + "core::SimpleMDArray_byte32_t_O" "core::Bignum_O" + "llvmo::LLVMTargetMachine_O" "core::ClassHolder_O" "chem::SketchFunction_O" "core::ComplexVector_byte32_t_O" "llvmo::UnaryInstruction_O" "llvmo::GlobalValue_O" "llvmo::PointerType_O" "core::TwoWayStream_O")} @@ -5905,10 +5907,9 @@ :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_RehashSize")} {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTable_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" @@ -5924,10 +5925,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableEqualp_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_HashTableCount")} @@ -5943,10 +5943,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableEq_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_HashTableCount")} @@ -5962,10 +5961,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableEqual_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_HashTableCount")} @@ -5982,10 +5980,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableCustom_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_HashTableCount")} @@ -6007,10 +6004,9 @@ {fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer>" - :offset-base-ctype "core::HashTableEql_O" - :layout-offset-field-names ("_Table" "._Vector" "._Contents")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Table")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_HashTableCount")} @@ -9901,6 +9897,37 @@ :offset-base-ctype "core::DebuggerFrame_O" :layout-offset-field-names ("down")} {fixed-field :offset-type-cxx-identifier "ctype__Bool" :offset-ctype "_Bool" :offset-base-ctype "core::DebuggerFrame_O" :layout-offset-field-names ("is_xep")} +{class-kind :stamp-name "STAMPWTAG_core__Mapping_O" :stamp-key "core::Mapping_O" + :parent-class "core::General_O" :lisp-class-base "core::General_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__WeakKeyMapping_O" :stamp-key "core::WeakKeyMapping_O" + :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{variable-array0 :offset-base-ctype "core::WeakKeyMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::Ephemeron" :offset-base-ctype "core::WeakKeyMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "ctype_unsigned_long" + :fixup-ctype-offset-type-key "unsigned long" :fixup-ctype-key "gctools::Ephemeron" + :layout-offset-field-names ("_key")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::Ephemeron" :layout-offset-field-names ("_value")} +{class-kind :stamp-name "STAMPWTAG_core__StrongMapping_O" :stamp-key "core::StrongMapping_O" + :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{variable-array0 :offset-base-ctype "core::StrongMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::KVPair" :offset-base-ctype "core::StrongMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::KVPair" :layout-offset-field-names ("key")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::KVPair" :layout-offset-field-names ("value")} {class-kind :stamp-name "STAMPWTAG_core__VariableCell_O" :stamp-key "core::VariableCell_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} @@ -11664,6 +11691,22 @@ :length-field-names ("_MaybeSignedLength") :end-field-names ("_MaybeSignedLength")} {variable-field-only :offset-type-cxx-identifier "ctype_signed_char" :fixup-type "signed char"} +{container-kind :stamp-name "STAMPWTAG_gctools__GCArray_moveable_gctools__Ephemeron_" + :stamp-key "gctools::GCArray_moveable" + :parent-class "gctools::GCContainer" :lisp-class-base nil + :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} +{variable-array0 :offset-base-ctype "gctools::GCArray_moveable" + :field-names ("_Data")} +{variable-capacity :ctype "gctools::Ephemeron" + :offset-base-ctype "gctools::GCArray_moveable" + :length-field-names ("_MaybeSignedLength") + :end-field-names ("_MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "ctype_unsigned_long" + :fixup-ctype-offset-type-key "unsigned long" :fixup-ctype-key "gctools::Ephemeron" + :layout-offset-field-names ("_key")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::Ephemeron" :layout-offset-field-names ("_value")} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_chem__EnergyOutOfZPlane_" :stamp-key "gctools::GCVector_moveable" :parent-class "gctools::GCContainer" :lisp-class-base nil @@ -11724,21 +11767,6 @@ :fixup-ctype-key "chem::EnergySketchNonbond" :layout-offset-field-names ("I1")} {variable-field :offset-type-cxx-identifier "ctype_int" :fixup-ctype-offset-type-key "int" :fixup-ctype-key "chem::EnergySketchNonbond" :layout-offset-field-names ("I2")} -{container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_core__KeyValuePair_" - :stamp-key "gctools::GCVector_moveable" - :parent-class "gctools::GCContainer" :lisp-class-base nil - :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} -{variable-array0 :offset-base-ctype "gctools::GCVector_moveable" - :field-names ("_Data")} -{variable-capacity :ctype "core::KeyValuePair" - :offset-base-ctype "gctools::GCVector_moveable" - :length-field-names ("_Capacity") :end-field-names ("_End")} -{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :fixup-ctype-offset-type-key "gctools::smart_ptr" - :fixup-ctype-key "core::KeyValuePair" :layout-offset-field-names ("_Key")} -{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :fixup-ctype-offset-type-key "gctools::smart_ptr" - :fixup-ctype-key "core::KeyValuePair" :layout-offset-field-names ("_Value")} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_gctools__smart_ptr_core__Symbol_O__" :stamp-key "gctools::GCVector_moveable>" :parent-class "gctools::GCContainer" :lisp-class-base nil @@ -12107,6 +12135,22 @@ :fixup-ctype-key "chem::EnergyNonbond" :layout-offset-field-names ("term" ".I2")} {variable-field :offset-type-cxx-identifier "ctype__Bool" :fixup-ctype-offset-type-key "_Bool" :fixup-ctype-key "chem::EnergyNonbond" :layout-offset-field-names ("_Is14")} +{container-kind :stamp-name "STAMPWTAG_gctools__GCArray_moveable_gctools__KVPair_" + :stamp-key "gctools::GCArray_moveable" + :parent-class "gctools::GCContainer" :lisp-class-base nil + :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} +{variable-array0 :offset-base-ctype "gctools::GCArray_moveable" + :field-names ("_Data")} +{variable-capacity :ctype "gctools::KVPair" + :offset-base-ctype "gctools::GCArray_moveable" + :length-field-names ("_MaybeSignedLength") + :end-field-names ("_MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::KVPair" :layout-offset-field-names ("key")} +{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::smart_ptr" + :fixup-ctype-key "gctools::KVPair" :layout-offset-field-names ("value")} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_std__pair_gctools__smart_ptr_core__Symbol_O__gctools__smart_ptr_core__T_O___" :stamp-key "gctools::GCVector_moveable,gctools::smart_ptr>>" :parent-class "gctools::GCContainer" :lisp-class-base nil diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index c188ebf775..7506b3c1b5 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -89,6 +89,14 @@ THE SOFTWARE. #endif namespace core { +StrongMapping_sp StrongMapping_O::make(size_t size) { + return gctools::GC::allocate_container(false, size); +} + +WeakKeyMapping_sp WeakKeyMapping_O::make(size_t size) { + return gctools::GC::allocate_container(false, size); +} + std::atomic global_next_hash_table_id; size_t next_hash_table_id() { return global_next_hash_table_id++; } @@ -136,11 +144,11 @@ Vector_sp HashTable_O::pairs() const { HT_READ_LOCK(this); SimpleVector_sp keyvalues = SimpleVector_O::make(_HashTableCount * 2); size_t idx(0); - for (size_t it(0), itEnd(_Table.size()); it < itEnd; ++it) { - const KeyValuePair& entry = _Table[it]; - if (!entry._Key.no_keyp() && !entry._Key.deletedp()) { - keyvalues[idx++] = entry._Key; - keyvalues[idx++] = entry._Value; + for (size_t it(0), itEnd(_Table->size()); it < itEnd; ++it) { + auto pair = _Table->get(it); + if (!pair.key.no_keyp() && !pair.key.deletedp()) { + keyvalues[idx++] = pair.key; + keyvalues[idx++] = pair.value; } } return keyvalues; @@ -159,6 +167,7 @@ CL_DEFUN Vector_sp core__hash_table_pairs(HashTableBase_sp hash_table_base) { // ---------------------------------------------------------------------- // +SYMBOL_EXPORT_SC_(KeywordPkg, key); CL_LAMBDA(&key (test (function eql)) (size 0) (rehash-size 2.0) (rehash-threshold 0.7) weakness debug (thread-safe t) hash-function); CL_DECLARE(); @@ -167,38 +176,34 @@ CL_DOCSTRING( DOCGROUP(clasp); CL_DEFUN T_sp cl__make_hash_table(T_sp test, Fixnum_sp size, Number_sp rehash_size, Real_sp orehash_threshold, Symbol_sp weakness, T_sp debug, T_sp thread_safe, T_sp hashf) { - SYMBOL_EXPORT_SC_(KeywordPkg, key); - if (weakness.notnilp()) { - if (weakness == INTERN_(kw, key)) { - // We use fboundp because we actually make hash - // tables before eq etc. are bound, so symbolFunction would - // signal an error. - if (test == cl::_sym_eq || (cl::_sym_eq->fboundp() && test == cl::_sym_eq->symbolFunction())) { - return core__make_weak_key_hash_table(size); - } else { - SIMPLE_ERROR("Weak hash tables non-EQ tests are not yet supported"); - } - } - SIMPLE_ERROR("Only :weakness :key (weak-key hash tables) are currently supported"); - } - double rehash_threshold = maybeFixRehashThreshold(clasp_to_double(orehash_threshold)); - HashTable_sp table = nil(); size_t isize = clasp_to_int(size); - if (isize == 0) + if (isize < 16) isize = 16; - // clasp_write_string(fmt::format("{}:{} - make_hash_table - fix me so that I grow by powers of 2\n" , __FILE__ , __LINE__ )); + Mapping_sp mapping; + + if (weakness.nilp()) + mapping = StrongMapping_O::make(isize); + else if (weakness == kw::_sym_key) + mapping = WeakKeyMapping_O::make(isize); + else + SIMPLE_ERROR("Only :weakness :key (weak-key hash tables) are currently supported"); + + // clamped by the constructor. + double rehash_threshold = clasp_to_double(orehash_threshold); + HashTable_sp table = nil(); + if (test == cl::_sym_eq || (cl::_sym_eq->fboundp() && test == cl::_sym_eq->symbolFunction())) { - table = HashTableEq_O::create(isize, rehash_size, rehash_threshold); + table = HashTableEq_O::create(mapping, rehash_size, rehash_threshold); } else if (test == cl::_sym_eql || (cl::_sym_eql->fboundp() && test == cl::_sym_eql->symbolFunction())) { - table = HashTableEql_O::create(isize, rehash_size, rehash_threshold); + table = HashTableEql_O::create(mapping, rehash_size, rehash_threshold); } else if (test == cl::_sym_equal || (cl::_sym_equal->fboundp() && test == cl::_sym_equal->symbolFunction())) { - table = HashTableEqual_O::create(isize, rehash_size, rehash_threshold); + table = HashTableEqual_O::create(mapping, rehash_size, rehash_threshold); } else if (test == cl::_sym_equalp || (cl::_sym_equalp->fboundp() && test == cl::_sym_equalp->symbolFunction())) { - table = HashTableEqualp_O::create(isize, rehash_size, rehash_threshold); + table = HashTableEqualp_O::create(mapping, rehash_size, rehash_threshold); } else { Function_sp comparator = coerce::functionDesignator(test); Function_sp hasher = coerce::functionDesignator(hashf); - table = HashTableCustom_O::create(isize, rehash_size, rehash_threshold, comparator, hasher); + table = HashTableCustom_O::create(mapping, rehash_size, rehash_threshold, comparator, hasher); } if (thread_safe.notnilp()) { table->setupThreadSafeHashTable(); @@ -248,22 +253,22 @@ HashTable_sp HashTable_O::create_thread_safe(T_sp test, SimpleBaseString_sp read } // FIXME: contents read could just be atomic maybe? -#define HASH_TABLE_ITER(tablep, key, value) \ - gctools::tagged_pointer> iter_datap; \ - T_sp key; \ - T_sp value; \ +#define HASH_TABLE_ITER(tablep, keyVar, valueVar) \ + Mapping_sp iter_datap; \ + T_sp keyVar, valueVar; \ { \ HT_READ_LOCK(tablep); \ - iter_datap = tablep->_Table._Vector._Contents; \ + iter_datap = _Table; \ } \ - for (size_t it(0), itEnd(iter_datap->_End); it < itEnd; ++it) { \ - KeyValuePair& entry = (*iter_datap)[it]; \ + for (size_t it = 0, itEnd = iter_datap->size(); it < itEnd; ++it) { \ { \ HT_READ_LOCK(tablep); \ - key = entry._Key; \ - value = entry._Value; \ - } \ - if (!key.no_keyp() && !key.deletedp()) + auto pair = iter_datap->get(it); \ + if (pair.key.no_keyp() || pair.key.deletedp()) \ + continue; \ + keyVar = pair.key; \ + valueVar = pair.value; \ + } #define HASH_TABLE_ITER_END } @@ -327,11 +332,9 @@ DOCGROUP(clasp); CL_DEFUN bool cl__remhash(T_sp key, HashTableBase_sp ht) { return ht->remhash(key); }; T_sp HashTable_O::clrhash() { - ASSERT(!Number_O::zerop(this->_RehashSize)); + HT_WRITE_LOCK(this); this->_HashTableCount = 0; - T_sp no_key = ::no_key(); - this->_Table.resize(0, KeyValuePair(no_key, no_key)); - this->setup(16, this->_RehashSize, this->_RehashThreshold); + this->_Table = this->_Table->realloc(16); return this->asSmartPtr(); } @@ -340,13 +343,6 @@ double maybeFixRehashThreshold(double rt) { return DEFAULT_REHASH_THRESHOLD; return rt; } -void HashTable_O::setup(uint sz, Number_sp rehashSize, double rehashThreshold) { - HT_WRITE_LOCK(this); - sz = this->resizeEmptyTable_no_lock(sz); - this->_RehashSize = rehashSize; - ASSERT(!Number_O::zerop(this->_RehashSize)); - this->_RehashThreshold = maybeFixRehashThreshold(rehashThreshold); -} bool HashTable_O::equalp(T_sp other) const { if (this == &(*other)) @@ -411,9 +407,8 @@ void HashTable_O::fields(Record_sp node) { uint HashTable_O::resizeEmptyTable_no_lock(size_t sz) { if (sz < 16) sz = 16; - T_sp no_key = ::no_key(); this->_HashTableCount = 0; - this->_Table.resize(sz, KeyValuePair(no_key, no_key)); + this->_Table = this->_Table->realloc(sz); return sz; } @@ -429,13 +424,8 @@ size_t HashTable_O::hashTableCount() const { } uint HashTable_O::calculateHashTableCount() const { - HT_READ_LOCK(this); uint cnt = 0; - for (size_t it(0), itEnd(this->_Table.size()); it < itEnd; ++it) { - const KeyValuePair& entry = this->_Table[it]; - if (!entry._Key.no_keyp() && !entry._Key.deletedp()) - ++cnt; - } + HASH_TABLE_ITER(this, _k, _v) { ++cnt; } HASH_TABLE_ITER_END; return cnt; } @@ -457,7 +447,7 @@ T_sp HashTable_O::operator[](const std::string& key) { size_t HashTable_O::hashTableSize() const { HT_READ_LOCK(this); - return this->_Table.size(); + return this->_Table->size(); } bool HashTable_O::keyTest(T_sp entryKey, T_sp searchKey) const { SUBCLASS_MUST_IMPLEMENT(); } @@ -467,7 +457,7 @@ gc::Fixnum HashTable_O::sxhashKey(T_sp obj) const { this->sxhashEffect(obj, hg); // We don't use hashTableSize() here because sxhashKey is only called while // the table is already locked. - return hg.hashBound(this->_Table.size()); + return hg.hashBound(this->_Table->size()); } CL_LAMBDA(key hash-table &optional default-value); @@ -484,29 +474,19 @@ CL_DEFUN T_mv core__gethash3(T_sp key, T_sp hashTable, T_sp default_value) { return ht->gethash(key, default_value); }; -KeyValuePair* HashTable_O::searchTable_no_read_lock(T_sp key, cl_index index) { - size_t tableSize = this->_Table.size(); +__attribute__((optnone)) std::optional HashTable_O::searchTable_no_read_lock(T_sp key, cl_index index) { + size_t tableSize = this->_Table->size(); size_t cur = index; do { - KeyValuePair& entry = this->_Table[cur]; - if (entry._Key.no_keyp()) break; - if (!entry._Key.deletedp()) { - DEBUG_HASH_TABLE( - { core::clasp_write_string(fmt::format("{}:{} search-end !deletedp index = {}\n", __FILE__, __LINE__, cur)); }); - if (this->keyTest(entry._Key, key)) { - DEBUG_HASH_TABLE({ - core::clasp_write_string( - fmt::format("{}:{} search-end found key index = {} entry._Key->{}\n .... {}\n key->{}\n .... {}\n", __FILE__, - __LINE__, cur, (void*)entry._Key.raw_(), dbg_safe_repr((uintptr_t)(void*)entry._Key.raw_()).c_str(), - (void*)key.raw_(), dbg_safe_repr((uintptr_t)(void*)key.raw_()).c_str())); - }); - return &entry; - } + auto pair = _Table->get(cur); + if (pair.key.no_keyp()) break; + if (!pair.key.deletedp()) { + if (keyTest(pair.key, key)) + return cur; } cur = (cur + 1) % tableSize; } while (cur != index); // loop over the whole table if necessary - DEBUG_HASH_TABLE({ core::clasp_write_string(fmt::format("{}:{} key not found\n", __FILE__, __LINE__)); }); - return nullptr; + return std::nullopt; } CL_LAMBDA(ht); @@ -531,9 +511,9 @@ CL_DEFMETHOD gc::Fixnum HashTable_O::hashIndex(T_sp key) const { std::optional HashTable_O::find(T_sp key) { HT_READ_LOCK(this); cl_index index = this->sxhashKey(key); - KeyValuePair* keyValue = this->searchTable_no_read_lock(key, index); - if (!keyValue) return std::optional(); - else return std::optional(keyValue->_Value); + auto found = this->searchTable_no_read_lock(key, index); + if (!found) return std::nullopt; + else return this->_Table->get(*found).value; } bool HashTable_O::contains(T_sp key) { @@ -543,9 +523,9 @@ bool HashTable_O::contains(T_sp key) { bool HashTable_O::remhash(T_sp key) { HT_WRITE_LOCK(this); cl_index index = this->sxhashKey(key); - KeyValuePair* keyValuePair = this->searchTable_no_read_lock(key, index); - if (keyValuePair) { - keyValuePair->_Key = deleted(); + auto found = this->searchTable_no_read_lock(key, index); + if (found) { + _Table->remove(*found); this->_HashTableCount--; return true; } @@ -562,57 +542,31 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { } cl_index index = this->sxhashKey(key); - DEBUG_HASH_TABLE({ - core::clasp_write_string(fmt::format("{}:{}:{} index = {} this->_Table.size() = {}\n", __FILE__, __LINE__, __FUNCTION__, - index, this->_Table.size())); - }); - KeyValuePair* keyValuePair = this->searchTable_no_read_lock(key, index); - if (keyValuePair) { + auto found = this->searchTable_no_read_lock(key, index); + if (found) { // rewrite value - keyValuePair->_Value = value; - DEBUG_HASH_TABLE({ - core::clasp_write_string(fmt::format("{}:{} Found key/value pair: {},{}\n", __FILE__, __LINE__, _rep_(keyValuePair->_Key), - _rep_(keyValuePair->_Value))); - }); - DEBUG_HASH_TABLE({ - core::clasp_write_string( - fmt::format("{}:{} Did rplacd value: {} to cons at {}\n", __FILE__, __LINE__, _rep_(value), (void*)keyValuePair)); - }); - DEBUG_HASH_TABLE({ - core::clasp_write_string(fmt::format("{}:{} After rplacd value: {}\n", __FILE__, __LINE__, _rep_(keyValuePair->_Value))); - }); + _Table->setValue(*found, value); return value; } - DEBUG_HASH_TABLE({ - core::clasp_write_string(fmt::format("{}:{}:{} Looking for empty slot index = {}\n", __FILE__, __LINE__, __FUNCTION__, index)); - }); - KeyValuePair* entryP = &this->_Table[index]; size_t write; - size_t curEnd = this->_Table.size(); - for (write = index; write < curEnd; ++write, ++entryP) { - if (entryP->_Key.no_keyp() || entryP->_Key.deletedp()) + size_t curEnd = this->_Table->size(); + for (write = index; write < curEnd; ++write) { + auto pair = _Table->get(write); + if (pair.key.no_keyp() || pair.key.deletedp()) goto ADD_KEY_VALUE; } - entryP = &this->_Table[0]; // wrap around - for (write = 0; write < index; ++write, ++entryP) { - if (entryP->_Key.no_keyp() || entryP->_Key.deletedp()) + // wrap around + for (write = 0; write < index; ++write) { + auto pair = _Table->get(write); + if (pair.key.no_keyp() || pair.key.deletedp()) goto ADD_KEY_VALUE; } goto NO_ROOM; ADD_KEY_VALUE: - DEBUG_HASH_TABLE1({ - cl_index index2 = this->sxhashKey(key); - if (index2 != index) { - lisp_write(fmt::format("{}:{}:{} INDEX mismatch!!! key = {} badge = {} index = {} write = {} index2 = {} size = {}\n", - __FILE__, __LINE__, __FUNCTION__, _rep_(key), lisp_general_badge(gc::As_unsafe(key)), - index, write, index2, this->_Table.size())); - } - }); - entryP->_Key = key; - entryP->_Value = value; + _Table->newEntry(write, key, value); this->_HashTableCount++; DEBUG_HASH_TABLE({ core::clasp_write_string(fmt::format("{}:{} Found empty slot at index = {}\n", __FILE__, __LINE__, write)); }); - if (this->_HashTableCount > this->_RehashThreshold * this->_Table.size()) { + if (this->_HashTableCount > this->_RehashThreshold * this->_Table->size()) { LOG("Expanding hash table"); this->rehash_no_lock(true); } @@ -626,7 +580,7 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { // printf("%s:%d There is absolutely no room in the hash-table _RehashThreshold = %lf - _HashTableCount -> %lu size -> %lu " "increasing size\n", - __FILE__, __LINE__, this->_RehashThreshold, this->_HashTableCount, this->_Table.size()); + __FILE__, __LINE__, this->_RehashThreshold, this->_HashTableCount, this->_Table->size()); this->rehash_no_lock(true); return this->setf_gethash_no_write_lock(key, value); // ------------ @@ -652,10 +606,10 @@ void HashTable_O::rehash_no_lock(bool expandTable) { DEBUG_HASH_TABLE1({ core::clasp_write_string(fmt::format("{}:{} rehash_no_lock\n", __FILE__, __LINE__)); }); ASSERTF(!Number_O::zerop(this->_RehashSize), "RehashSize is zero - it shouldn't be"); - gc::Fixnum curSize = this->_Table.size(); - ASSERTF(this->_Table.size() != 0, "HashTable is empty in expandHashTable curSize={} this->_Table.size()= {} this shouldn't be", - curSize, this->_Table.size()); - LOG("At start of expandHashTable current hash table size: {}", this->_Table.size()); + gc::Fixnum curSize = this->_Table->size(); + ASSERTF(this->_Table->size() != 0, "HashTable is empty in expandHashTable curSize={} this->_Table->size()= {} this shouldn't be", + curSize, this->_Table->size()); + LOG("At start of expandHashTable current hash table size: {}", this->_Table->size()); gc::Fixnum newSize = 0; if (expandTable) { if (cl__integerp(this->_RehashSize)) { @@ -666,19 +620,14 @@ void HashTable_O::rehash_no_lock(bool expandTable) { } else { newSize = curSize; } - gc::Vec0 oldTable; - oldTable.swap(this->_Table); + Mapping_sp oldTable = _Table; newSize = this->resizeEmptyTable_no_lock(newSize); LOG("Resizing table to size: {}", newSize); - size_t oldSize = oldTable.size(); + size_t oldSize = oldTable->size(); for (size_t it(0), itEnd(oldSize); it < itEnd; ++it) { - KeyValuePair& entry = oldTable[it]; - T_sp key = entry._Key; - T_sp value = entry._Value; - if (!key.no_keyp() && !key.deletedp()) { - // key/value represent a valid entry in the hash table - this->setf_gethash_no_write_lock(key, value); - } + auto pair = oldTable->get(it); + if (pair.key.no_keyp() || pair.key.deletedp()) continue; + this->setf_gethash_no_write_lock(pair.key, pair.value); } } @@ -694,7 +643,7 @@ string HashTable_O::__repr__() const { // the calculator is only useful to check that the count is consistent; // uncomment this if you need to debug, but otherwise it's redundant. // ss << " :calculated-entries " << this->calculateHashTableCount(); - ss << " :SIZE " << this->_Table.size(); + ss << " :SIZE " << this->_Table->size(); ss << " @" << (void*)(this) << ">"; return ss.str(); } diff --git a/src/core/hashTableCustom.cc b/src/core/hashTableCustom.cc index 55bfe582cb..8f4ddfddb8 100644 --- a/src/core/hashTableCustom.cc +++ b/src/core/hashTableCustom.cc @@ -36,13 +36,13 @@ namespace core { // ---------------------------------------------------------------------- // +HashTableCustom_sp HashTableCustom_O::create(Mapping_sp mapping, Number_sp rehashSize, double rehashThreshold, Function_sp comparator, Function_sp hasher) { + return gctools::GC::allocate(mapping, rehashSize, rehashThreshold, comparator, hasher); +} + HashTableCustom_sp HashTableCustom_O::create(uint sz, Number_sp rehashSize, double rehashThreshold, Function_sp comparator, Function_sp hasher) { - auto hashTable = gctools::GC::allocate_with_default_constructor(); - hashTable->setup(sz, rehashSize, rehashThreshold); - hashTable->comparator = comparator; - hashTable->hasher = hasher; - return hashTable; + return create(StrongMapping_O::make(sz), rehashSize, rehashThreshold, comparator, hasher); } bool HashTableCustom_O::keyTest(T_sp entryKey, T_sp searchKey) const { diff --git a/src/core/hashTableEq.cc b/src/core/hashTableEq.cc index ff82ae86d3..c34f9ea5d4 100644 --- a/src/core/hashTableEq.cc +++ b/src/core/hashTableEq.cc @@ -35,10 +35,12 @@ namespace core { // ---------------------------------------------------------------------- // +HashTableEq_sp HashTableEq_O::create(Mapping_sp mapping, Number_sp rehashSize, double rehashThreshold) { + return gctools::GC::allocate(mapping, rehashSize, rehashThreshold); +} + HashTableEq_sp HashTableEq_O::create(uint sz, Number_sp rehashSize, double rehashThreshold) { - auto hashTable = gctools::GC::allocate_with_default_constructor(); - hashTable->setup(sz, rehashSize, rehashThreshold); - return hashTable; + return create(StrongMapping_O::make(sz), rehashSize, rehashThreshold); } HashTableEq_sp HashTableEq_O::create(uint sz) { diff --git a/src/core/hashTableEql.cc b/src/core/hashTableEql.cc index bbc437b534..01e59e4c37 100644 --- a/src/core/hashTableEql.cc +++ b/src/core/hashTableEql.cc @@ -36,18 +36,18 @@ namespace core { // ---------------------------------------------------------------------- // +HashTableEql_sp HashTableEql_O::create(Mapping_sp mapping, Number_sp rehashSize, double rehashThreshold) { + return gctools::GC::allocate(mapping, rehashSize, rehashThreshold); +} + HashTableEql_sp HashTableEql_O::create(uint sz, Number_sp rehashSize, double rehashThreshold) { - if (sz == 0) - sz = 16; - auto hashTable = gctools::GC::allocate_with_default_constructor(); - hashTable->setup(sz, rehashSize, rehashThreshold); - return hashTable; + return create(StrongMapping_O::make(sz), rehashSize, rehashThreshold); } SYMBOL_EXPORT_SC_(ClPkg, eql); HashTableEql_sp HashTableEql_O::create_default() { DoubleFloat_sp rhs = DoubleFloat_O::create(2.0); - HashTableEql_sp ht = HashTableEql_O::create(16, rhs, DEFAULT_REHASH_THRESHOLD); + HashTableEql_sp ht = create(16, rhs, DEFAULT_REHASH_THRESHOLD); return ht; } diff --git a/src/core/hashTableEqual.cc b/src/core/hashTableEqual.cc index aecab6a2b8..48164da26c 100644 --- a/src/core/hashTableEqual.cc +++ b/src/core/hashTableEqual.cc @@ -36,16 +36,18 @@ namespace core { // ---------------------------------------------------------------------- // +HashTableEqual_sp HashTableEqual_O::create(Mapping_sp mapping, Number_sp rehashSize, double rehashThreshold) { + return gctools::GC::allocate(mapping, rehashSize, rehashThreshold); +} + HashTableEqual_sp HashTableEqual_O::create(uint sz, Number_sp rehashSize, double rehashThreshold) { - auto hashTable = gctools::GC::allocate_with_default_constructor(); - hashTable->setup(sz, rehashSize, rehashThreshold); - return hashTable; + return create(StrongMapping_O::make(sz), rehashSize, rehashThreshold); } SYMBOL_EXPORT_SC_(ClPkg, equal); HashTableEqual_sp HashTableEqual_O::create_default() { DoubleFloat_sp rhs = DoubleFloat_O::create(2.0); - HashTableEqual_sp ht = HashTableEqual_O::create(16, rhs, DEFAULT_REHASH_THRESHOLD); + HashTableEqual_sp ht = create(16, rhs, DEFAULT_REHASH_THRESHOLD); return ht; } diff --git a/src/core/hashTableEqualp.cc b/src/core/hashTableEqualp.cc index 6b3d9d356c..d953b350b9 100644 --- a/src/core/hashTableEqualp.cc +++ b/src/core/hashTableEqualp.cc @@ -35,15 +35,17 @@ namespace core { // ---------------------------------------------------------------------- // +HashTableEqualp_sp HashTableEqualp_O::create(Mapping_sp mapping, Number_sp rehashSize, double rehashThreshold) { + return gctools::GC::allocate(mapping, rehashSize, rehashThreshold); +} + HashTableEqualp_sp HashTableEqualp_O::create(uint sz, Number_sp rehashSize, double rehashThreshold) { - auto hashTable = gctools::GC::allocate_with_default_constructor(); - hashTable->setup(sz, rehashSize, rehashThreshold); - return hashTable; + return create(StrongMapping_O::make(sz), rehashSize, rehashThreshold); } HashTableEqualp_sp HashTableEqualp_O::create_default() { DoubleFloat_sp rhs = DoubleFloat_O::create(2.0); - HashTableEqualp_sp ht = HashTableEqualp_O::create(16, rhs, DEFAULT_REHASH_THRESHOLD); + HashTableEqualp_sp ht = create(16, rhs, DEFAULT_REHASH_THRESHOLD); return ht; } diff --git a/src/gctools/gcweak.cc b/src/gctools/gcweak.cc index b0b195fb64..835402df76 100644 --- a/src/gctools/gcweak.cc +++ b/src/gctools/gcweak.cc @@ -403,34 +403,59 @@ Ephemeron::Ephemeron(core::T_sp k, core::T_sp v) } } -void* Ephemeron::key_helper(void* data) { - result_helper_s* rhsp = (result_helper_s*)data; - if (rhsp->eph->_key) // not splatted - rhsp->result.emplace((Tagged)GC_REVEAL_POINTER(rhsp->eph->_key)); - return nullptr; +void Ephemeron::reinit(core::T_sp k, core::T_sp v) { + if (k.objectp()) { + // These will implicitly undo any previously registered + // disappearing link, according to Boehm docs. + // We undo the old registrations first so that it is not possible + // for the new _key to get wiped by the old key being collected, + // in the brief window before the _value is also put in. + // But FIXME: Do we need to put in a fence or something to ensure + // the key stays alive within reinit? + GC_general_register_disappearing_link((void**)&_key, &*k); + GC_general_register_disappearing_link((void**)&_value, &*k); + } else { + GC_unregister_disappearing_link((void**)&_key); + GC_unregister_disappearing_link((void**)&_value); + } + _value = v; + _key = GC_HIDE_POINTER(k.tagged_()); } -void* Ephemeron::value_helper(void* data) { + +void* Ephemeron::get_helper(void* data) { result_helper_s* rhsp = (result_helper_s*)data; - if (rhsp->eph->_value) - rhsp->result.emplace(rhsp->eph->_value); + if (rhsp->eph->_key) { // not splatted + rhsp->result.key = core::T_sp((Tagged)GC_REVEAL_POINTER(rhsp->eph->_key)); + rhsp->result.value = rhsp->eph->_value; + } else { + rhsp->result.key = rhsp->result.value = deleted(); + } return nullptr; } -std::optional Ephemeron::key() const { +KVPair Ephemeron::get() const { result_helper_s rhs(this); // same TODO with GC_call_with_reader_lock. - GC_call_with_alloc_lock(key_helper, &rhs); - return rhs.result; -} -std::optional Ephemeron::value() const { - result_helper_s rhs(this); - GC_call_with_alloc_lock(value_helper, &rhs); + GC_call_with_alloc_lock(get_helper, &rhs); return rhs.result; } #else // not-actually-weak ephemeron default - FIXME for your GC! Ephemeron::Ephemeron(core::T_sp key, core::T_sp value) : _key(key), _value(value) {} -std::optional Ephemeron::key() const { return _key; } -std::optional Ephemeron::value() const { return _value; } +void Ephemeron::reinit(core::T_sp k, core::T_sp v) { + _key = k; _value = v; +} + +KVPair Ephemeron::get() const { return KVPair(_key, _value); } #endif + +// Clang says this definition has to be out-of-line. Sure whatever. +const KVPair StrongMapping::initKV = {.key = core::T_sp(tag_no_key()), + .value = core::T_sp(tag_no_key())}; + +// note that Ephemeron's constructor doesn't have to do anything +// interesting for non-objects, so we shouldn't need to worry about +// static constructor ordering. +const Ephemeron EphemeronMapping::initEph{no_key(), no_key()}; + } // namespace gctools From 3758c40ab88be161fe43dbee866c19756adb754b Mon Sep 17 00:00:00 2001 From: Bike Date: Sun, 22 Dec 2024 09:50:07 -0500 Subject: [PATCH 24/39] Fix HASH-TABLE-COUNT for weak tables the table has to be searched, since afaik there's no way to make boehm decrement a counter when it disappears a pointer. I kept the _Count field so that we don't have to do that iteration when checking for rehash (i.e. every time we setf gethash). --- include/clasp/core/hashTable.h | 45 ++++++++++++++++++++++++++++----- src/analysis/clasp_gc.sif | 23 +++++------------ src/analysis/clasp_gc_cando.sif | 23 +++++------------ src/core/hashTable.cc | 19 +++++--------- 4 files changed, 57 insertions(+), 53 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index bf9b9b0505..f0e04f38b7 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -50,13 +50,34 @@ namespace core { FORWARD(Mapping); class Mapping_O : public General_O { LISP_ABSTRACT_CLASS(core, CorePkg, Mapping_O, "Mapping", General_O); +public: + // This count is increased by newEntry and decreased by remove. + // It is therefore an exact count for strong mappings but potentially + // an undercount for weak mappings, for which the GC may delete an + // entry without decrementing this count. It is maintained anyway so + // that the hash table can decide to rehash based on an easily + // accessible count rather than having to iterate over the whole mapping. + // This means weak tables may be rehashed "early", but there's no harm + // done, and the count is reset to the exact count on rehash so error + // can't accumulate indefinitely. + size_t _Count = 0; public: virtual size_t size() const = 0; + virtual size_t count() const = 0; // exact + size_t countInexact() const { return _Count; } virtual Mapping_sp realloc(size_t) const = 0; virtual gctools::KVPair get(size_t) const = 0; virtual void setValue(size_t, T_sp) = 0; virtual void newEntry(size_t, T_sp, T_sp) = 0; virtual void remove(size_t) = 0; + size_t computeCount() const { + size_t count = 0, sz = size(); + for (size_t i = 0; i < sz; ++i) { + auto p = get(i); + if (!p.key.no_keyp() && !p.key.deletedp()) ++count; + } + return count; + } }; FORWARD(StrongMapping); @@ -72,11 +93,18 @@ class StrongMapping_O final : public Mapping_O { gctools::StrongMapping _Mapping; public: virtual size_t size() const { return _Mapping.size(); } + virtual size_t count() const { return _Count; } virtual Mapping_sp realloc(size_t sz) const { return make(sz); } virtual gctools::KVPair get(size_t i) const { return _Mapping.get(i); } virtual void setValue(size_t i, T_sp v) { _Mapping.setValue(i, v); } - virtual void newEntry(size_t i, T_sp k, T_sp v) { _Mapping.newEntry(i, k, v); } - virtual void remove(size_t i) { _Mapping.remove(i); } + virtual void newEntry(size_t i, T_sp k, T_sp v) { + _Mapping.newEntry(i, k, v); + _Count++; + } + virtual void remove(size_t i) { + _Mapping.remove(i); + _Count--; + } }; FORWARD(WeakKeyMapping); @@ -92,11 +120,12 @@ class WeakKeyMapping_O final : public Mapping_O { gctools::EphemeronMapping _Mapping; public: virtual size_t size() const { return _Mapping.size(); } + virtual size_t count() const { return computeCount(); } virtual Mapping_sp realloc(size_t sz) const { return make(sz); } virtual gctools::KVPair get(size_t i) const { return _Mapping.get(i); } virtual void setValue(size_t i, T_sp v) { _Mapping.setValue(i, v); } - virtual void newEntry(size_t i, T_sp k, T_sp v) { _Mapping.newEntry(i, k, v); } - virtual void remove(size_t i) { _Mapping.remove(i); } + virtual void newEntry(size_t i, T_sp k, T_sp v) { ++_Count; _Mapping.newEntry(i, k, v); } + virtual void remove(size_t i) { --_Count; _Mapping.remove(i); } }; FORWARD(HashTable); @@ -111,12 +140,12 @@ class HashTable_O : public HashTableBase_O { friend T_sp cl__maphash(T_sp function_desig, T_sp hash_table); HashTable_O() - : _RehashSize(nil()), _RehashThreshold(maybeFixRehashThreshold(0.7)), _HashTableCount(0) + : _RehashSize(nil()), _RehashThreshold(maybeFixRehashThreshold(0.7)) {}; HashTable_O(Mapping_sp mapping, Number_sp rehashSize, double rehashThreshold) : _RehashSize(rehashSize), _RehashThreshold(maybeFixRehashThreshold(rehashThreshold)), - _Table(mapping), _HashTableCount(0) {} + _Table(mapping) {} friend T_sp cl__maphash(T_sp function_desig, HashTable_sp hash_table); friend T_sp cl__clrhash(HashTable_sp hash_table); @@ -124,7 +153,6 @@ class HashTable_O : public HashTableBase_O { Number_sp _RehashSize; double _RehashThreshold; Mapping_sp _Table; - size_t _HashTableCount; #ifdef CLASP_THREADS mutable mp::SharedMutex_sp _Mutex; #endif @@ -149,6 +177,9 @@ class HashTable_O : public HashTableBase_O { gc::Fixnum sxhashKey(T_sp key) const; // NOTE: Only call with (read) lock held std::optional searchTable_no_read_lock(T_sp key, cl_index index); + inline size_t count_no_lock() const { + return _Table->count(); + } protected: virtual void sxhashEffect(T_sp key, HashGenerator& hg) const { SUBIMP() }; diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index 2b782965e1..fead8d78a3 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -4769,9 +4769,13 @@ {class-kind :stamp-name "STAMPWTAG_core__Mapping_O" :stamp-key "core::Mapping_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::Mapping_O" :layout-offset-field-names ("_Count")} {class-kind :stamp-name "STAMPWTAG_core__WeakKeyMapping_O" :stamp-key "core::WeakKeyMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakKeyMapping_O" :layout-offset-field-names ("_Count")} {variable-array0 :offset-base-ctype "core::WeakKeyMapping_O" :field-names ("_Mapping" "._Data" "._Data")} {variable-capacity :ctype "gctools::Ephemeron" :offset-base-ctype "core::WeakKeyMapping_O" @@ -4786,6 +4790,8 @@ {class-kind :stamp-name "STAMPWTAG_core__StrongMapping_O" :stamp-key "core::StrongMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::StrongMapping_O" :layout-offset-field-names ("_Count")} {variable-array0 :offset-base-ctype "core::StrongMapping_O" :field-names ("_Mapping" "._Data" "._Data")} {variable-capacity :ctype "gctools::KVPair" :offset-base-ctype "core::StrongMapping_O" @@ -4910,8 +4916,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Mutex")} @@ -4928,9 +4932,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableEqualp_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Mutex")} @@ -4946,9 +4947,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableEq_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Mutex")} @@ -4964,9 +4962,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableEql_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Mutex")} @@ -4982,9 +4977,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableEqual_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Mutex")} @@ -5001,9 +4993,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableCustom_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Mutex")} diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index a2564bb610..9e56c5c76a 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -5910,8 +5910,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Mutex")} @@ -5928,9 +5926,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableEqualp_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Mutex")} @@ -5946,9 +5941,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableEq_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Mutex")} @@ -5964,9 +5956,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableEqual_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Mutex")} @@ -5983,9 +5972,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableCustom_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Mutex")} @@ -6007,9 +5993,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::HashTableEql_O" - :layout-offset-field-names ("_HashTableCount")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Mutex")} @@ -9900,9 +9883,13 @@ {class-kind :stamp-name "STAMPWTAG_core__Mapping_O" :stamp-key "core::Mapping_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::Mapping_O" :layout-offset-field-names ("_Count")} {class-kind :stamp-name "STAMPWTAG_core__WeakKeyMapping_O" :stamp-key "core::WeakKeyMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakKeyMapping_O" :layout-offset-field-names ("_Count")} {variable-array0 :offset-base-ctype "core::WeakKeyMapping_O" :field-names ("_Mapping" "._Data" "._Data")} {variable-capacity :ctype "gctools::Ephemeron" :offset-base-ctype "core::WeakKeyMapping_O" @@ -9917,6 +9904,8 @@ {class-kind :stamp-name "STAMPWTAG_core__StrongMapping_O" :stamp-key "core::StrongMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::StrongMapping_O" :layout-offset-field-names ("_Count")} {variable-array0 :offset-base-ctype "core::StrongMapping_O" :field-names ("_Mapping" "._Data" "._Data")} {variable-capacity :ctype "gctools::KVPair" :offset-base-ctype "core::StrongMapping_O" diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 7506b3c1b5..321e59517a 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -142,7 +142,7 @@ struct HashTableWriteLock { Vector_sp HashTable_O::pairs() const { // FIXME: use maphash for this, but without the overhead of a std::function HT_READ_LOCK(this); - SimpleVector_sp keyvalues = SimpleVector_O::make(_HashTableCount * 2); + SimpleVector_sp keyvalues = SimpleVector_O::make(_Table->count() * 2); size_t idx(0); for (size_t it(0), itEnd(_Table->size()); it < itEnd; ++it) { auto pair = _Table->get(it); @@ -333,7 +333,6 @@ CL_DEFUN bool cl__remhash(T_sp key, HashTableBase_sp ht) { return ht->remhash(ke T_sp HashTable_O::clrhash() { HT_WRITE_LOCK(this); - this->_HashTableCount = 0; this->_Table = this->_Table->realloc(16); return this->asSmartPtr(); } @@ -407,7 +406,6 @@ void HashTable_O::fields(Record_sp node) { uint HashTable_O::resizeEmptyTable_no_lock(size_t sz) { if (sz < 16) sz = 16; - this->_HashTableCount = 0; this->_Table = this->_Table->realloc(sz); return sz; } @@ -420,13 +418,12 @@ CL_DEFUN uint cl__hash_table_count(HashTableBase_sp ht) { return ht->hashTableCo size_t HashTable_O::hashTableCount() const { HT_READ_LOCK(this); - return this->_HashTableCount; + return _Table->count(); } uint HashTable_O::calculateHashTableCount() const { - uint cnt = 0; - HASH_TABLE_ITER(this, _k, _v) { ++cnt; } HASH_TABLE_ITER_END; - return cnt; + HT_READ_LOCK(this); + return _Table->computeCount(); } CL_LAMBDA(arg); @@ -526,7 +523,6 @@ bool HashTable_O::remhash(T_sp key) { auto found = this->searchTable_no_read_lock(key, index); if (found) { _Table->remove(*found); - this->_HashTableCount--; return true; } return false; @@ -564,9 +560,8 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { goto NO_ROOM; ADD_KEY_VALUE: _Table->newEntry(write, key, value); - this->_HashTableCount++; DEBUG_HASH_TABLE({ core::clasp_write_string(fmt::format("{}:{} Found empty slot at index = {}\n", __FILE__, __LINE__, write)); }); - if (this->_HashTableCount > this->_RehashThreshold * this->_Table->size()) { + if (_Table->countInexact() > this->_RehashThreshold * this->_Table->size()) { LOG("Expanding hash table"); this->rehash_no_lock(true); } @@ -580,7 +575,7 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { // printf("%s:%d There is absolutely no room in the hash-table _RehashThreshold = %lf - _HashTableCount -> %lu size -> %lu " "increasing size\n", - __FILE__, __LINE__, this->_RehashThreshold, this->_HashTableCount, this->_Table->size()); + __FILE__, __LINE__, this->_RehashThreshold, this->hashTableCount(), this->_Table->size()); this->rehash_no_lock(true); return this->setf_gethash_no_write_lock(key, value); // ------------ @@ -639,7 +634,7 @@ void HashTable_O::rehash(bool expandTable) { string HashTable_O::__repr__() const { stringstream ss; ss << "#<" << this->_instanceClass()->_classNameAsString(); - ss << " :COUNT " << this->_HashTableCount; + ss << " :COUNT " << this->hashTableCount(); // the calculator is only useful to check that the count is consistent; // uncomment this if you need to debug, but otherwise it's redundant. // ss << " :calculated-entries " << this->calculateHashTableCount(); From 412eb45b9bbd304e95cd84561ce4befa17423ac7 Mon Sep 17 00:00:00 2001 From: Bike Date: Sun, 22 Dec 2024 23:03:12 -0500 Subject: [PATCH 25/39] Remove unneeded type precision from _Finalizers table decl It's still weak, just not a WeakKeyHashTable, which is of course the old code that will be removed. --- include/clasp/core/hashTable.h | 1 + include/clasp/core/hashTableEq.h | 1 + include/clasp/core/lisp.h | 2 +- src/analysis/clasp_gc.sif | 4 ++-- src/analysis/clasp_gc_cando.sif | 4 ++-- src/core/corePackage.cc | 2 +- src/core/hashTable.cc | 1 + src/core/hashTableEq.cc | 4 ++++ src/gctools/gcFunctions.cc | 6 +++--- 9 files changed, 16 insertions(+), 9 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index f0e04f38b7..4c33fa2b0c 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -159,6 +159,7 @@ class HashTable_O : public HashTableBase_O { public: static HashTable_sp create(T_sp test); // set everything up with defaults static HashTable_sp createEq(size_t sz = 8); + static HashTable_sp createEqWeakKey(size_t sz = 8); static HashTable_sp createEql(); static HashTable_sp createEqual(); static HashTable_sp createEqualp(); diff --git a/include/clasp/core/hashTableEq.h b/include/clasp/core/hashTableEq.h index ddaa92b448..2a20f7969d 100644 --- a/include/clasp/core/hashTableEq.h +++ b/include/clasp/core/hashTableEq.h @@ -41,6 +41,7 @@ class HashTableEq_O : public HashTable_O { : HashTable_O(map, rhsize, rhthresh) {} public: + static HashTableEq_sp create(Mapping_sp mapping); static HashTableEq_sp create(Mapping_sp mapping, Number_sp rehashSize, double rehashThreshold); static HashTableEq_sp create(uint sz); static HashTableEq_sp create(uint sz, Number_sp rehashSize, double rehashThreshold); diff --git a/include/clasp/core/lisp.h b/include/clasp/core/lisp.h index 80cece238f..9e8e35cc89 100644 --- a/include/clasp/core/lisp.h +++ b/include/clasp/core/lisp.h @@ -286,7 +286,7 @@ class Lisp { T_sp _TerminalIO; List_sp _ActiveThreads; List_sp _DefaultSpecialBindings; - WeakKeyHashTable_sp _Finalizers; + HashTable_sp _Finalizers; HashTable_sp _Sysprop; HashTable_sp _ClassTable; CharacterInfo charInfo; // Contains GC managed pointers diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index fead8d78a3..007f68c366 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -5864,8 +5864,8 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._DefaultSpecialBindings")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._Finalizers")} + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" + :layout-offset-field-names ("_Roots" "._Finalizers")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._Sysprop")} diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index 9e56c5c76a..64dc73832e 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -12450,8 +12450,8 @@ :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._DefaultSpecialBindings")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._Finalizers")} + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" + :layout-offset-field-names ("_Roots" "._Finalizers")} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Lisp" :layout-offset-field-names ("_Roots" "._Sysprop")} diff --git a/src/core/corePackage.cc b/src/core/corePackage.cc index 0e36cac9ed..34afeecff9 100644 --- a/src/core/corePackage.cc +++ b/src/core/corePackage.cc @@ -657,7 +657,7 @@ void CoreExposer_O::define_essential_globals(LispPtr lisp) { _sym_STARterminate_hooksSTAR->defparameter(nil()); SimpleBaseString_sp sbsr1 = SimpleBaseString_O::make("SYSPMNR"); SimpleBaseString_sp sbsw1 = SimpleBaseString_O::make("SYSPMNW"); - _lisp->_Roots._Finalizers = WeakKeyHashTable_O::create(); + _lisp->_Roots._Finalizers = HashTable_O::createEqWeakKey(); _lisp->_Roots._Sysprop = HashTable_O::create_thread_safe(cl::_sym_eql, sbsr1, sbsw1); _sym_STARdebug_accessorsSTAR->defparameter(nil()); std::list nicknames; diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 321e59517a..81f93386b3 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -239,6 +239,7 @@ HashTable_sp HashTable_O::create(T_sp test) { } HashTable_sp HashTable_O::createEq(size_t sz) { return HashTableEq_O::create(sz); } +HashTable_sp HashTable_O::createEqWeakKey(size_t sz) { return HashTableEq_O::create(WeakKeyMapping_O::make(sz)); } HashTable_sp HashTable_O::createEql() { return HashTableEql_O::create_default(); } HashTable_sp HashTable_O::createEqual() { return HashTableEqual_O::create_default(); } HashTable_sp HashTable_O::createEqualp() { return HashTableEqualp_O::create_default(); } diff --git a/src/core/hashTableEq.cc b/src/core/hashTableEq.cc index c34f9ea5d4..5d7b09fe4e 100644 --- a/src/core/hashTableEq.cc +++ b/src/core/hashTableEq.cc @@ -39,6 +39,10 @@ HashTableEq_sp HashTableEq_O::create(Mapping_sp mapping, Number_sp rehashSize, d return gctools::GC::allocate(mapping, rehashSize, rehashThreshold); } +HashTableEq_sp HashTableEq_O::create(Mapping_sp mapping) { + return create(mapping, SingleFloat_dummy_O::create(2.0), DEFAULT_REHASH_THRESHOLD); +} + HashTableEq_sp HashTableEq_O::create(uint sz, Number_sp rehashSize, double rehashThreshold) { return create(StrongMapping_O::make(sz), rehashSize, rehashThreshold); } diff --git a/src/gctools/gcFunctions.cc b/src/gctools/gcFunctions.cc index 7f64750ac9..8e52864ccc 100644 --- a/src/gctools/gcFunctions.cc +++ b/src/gctools/gcFunctions.cc @@ -486,7 +486,7 @@ namespace gctools { DOCGROUP(clasp); CL_DEFUN void gctools__finalize(core::T_sp object, core::Function_sp finalizer_callback) { WITH_READ_WRITE_LOCK(globals_->_FinalizersMutex); - core::WeakKeyHashTable_sp ht = _lisp->_Roots._Finalizers; + core::HashTable_sp ht = _lisp->_Roots._Finalizers; core::List_sp orig_finalizers = ht->gethash(object, nil()); core::List_sp finalizers = core::Cons_O::create(finalizer_callback, orig_finalizers); ht->hash_table_setf_gethash(object, finalizers); @@ -497,7 +497,7 @@ CL_DEFUN void gctools__finalize(core::T_sp object, core::Function_sp finalizer_c DOCGROUP(clasp); CL_DEFUN core::T_sp gctools__finalizers(core::T_sp object) { WITH_READ_WRITE_LOCK(globals_->_FinalizersMutex); - core::WeakKeyHashTable_sp ht = _lisp->_Roots._Finalizers; + core::HashTable_sp ht = _lisp->_Roots._Finalizers; return ht->gethash(object, nil()); } @@ -509,7 +509,7 @@ CL_DEFUN void gctools__invoke_finalizers() { DOCGROUP(clasp); CL_DEFUN void gctools__definalize(core::T_sp object) { WITH_READ_WRITE_LOCK(globals_->_FinalizersMutex); - core::WeakKeyHashTable_sp ht = _lisp->_Roots._Finalizers; + core::HashTable_sp ht = _lisp->_Roots._Finalizers; if (ht->gethash(object)) ht->remhash(object); clear_finalizer_list(object); From 40db97da5a74cf352bc833cccc8361a23e3b6743 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 31 Dec 2024 09:38:47 -0500 Subject: [PATCH 26/39] Define hash-table-weakness for new weak hash tables apparently we don't have a test for this. FIXME --- include/clasp/core/hashTable.h | 6 ++++++ src/core/hashTable.cc | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index 4c33fa2b0c..43cecfd3bb 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -70,6 +70,7 @@ class Mapping_O : public General_O { virtual void setValue(size_t, T_sp) = 0; virtual void newEntry(size_t, T_sp, T_sp) = 0; virtual void remove(size_t) = 0; + virtual Symbol_sp weakness() = 0; size_t computeCount() const { size_t count = 0, sz = size(); for (size_t i = 0; i < sz; ++i) { @@ -105,6 +106,7 @@ class StrongMapping_O final : public Mapping_O { _Mapping.remove(i); _Count--; } + virtual Symbol_sp weakness() { return nil(); } }; FORWARD(WeakKeyMapping); @@ -126,6 +128,7 @@ class WeakKeyMapping_O final : public Mapping_O { virtual void setValue(size_t i, T_sp v) { _Mapping.setValue(i, v); } virtual void newEntry(size_t i, T_sp k, T_sp v) { ++_Count; _Mapping.newEntry(i, k, v); } virtual void remove(size_t i) { --_Count; _Mapping.remove(i); } + virtual Symbol_sp weakness() { return kw::_sym_key; } }; FORWARD(HashTable); @@ -207,6 +210,9 @@ class HashTable_O : public HashTableBase_O { size_t hashTableSize() const override; size_t size() { return this->hashTableCount(); }; + // Return a symbol representing the weakness type. + Symbol_sp weakness() { return _Table->weakness(); } + T_sp operator[](const std::string& key); virtual bool keyTest(T_sp entryKey, T_sp searchKey) const; diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 81f93386b3..cd2dcea491 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -227,7 +227,7 @@ CL_DEFUN Symbol_sp core__hash_table_weakness(T_sp ht) { if (gc::IsA(ht)) { return kw::_sym_key; } - return nil(); + return ht.as()->weakness(); } HashTable_sp HashTable_O::create(T_sp test) { From 19acd3e9f82b08c0977781eb147f769d8c08b610 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 31 Dec 2024 11:37:12 -0500 Subject: [PATCH 27/39] Delete old weak hash tables Probably need to make the scanner a little more sophisticated for ephemerons and stuff. weak_scan is busted down to nothing here. --- include/clasp/core/coretypes.h | 1 - include/clasp/core/hashTable.h | 25 +- include/clasp/core/hashTableBase.h | 51 ---- include/clasp/core/sourceFileInfo.h | 2 +- include/clasp/core/weakHashTable.h | 97 ------- include/clasp/gctools/exposeCommon.h | 4 +- include/clasp/gctools/gcalloc.h | 99 ------- include/clasp/gctools/gcalloc_boehm.h | 18 -- include/clasp/gctools/gcweak.h | 304 --------------------- include/clasp/gctools/memoryManagement.h | 10 - src/analysis/clasp_gc.sif | 246 ++++++++--------- src/analysis/clasp_gc_cando.sif | 228 +++++++--------- src/core/bytecode_compiler.cc | 5 +- src/core/corePackage.cc | 1 - src/core/cscript.lisp | 1 - src/core/hashTable.cc | 34 +-- src/core/loadltv.cc | 2 +- src/core/predicates.cc | 5 +- src/core/weakHashTable.cc | 187 ------------- src/gctools/gc_interface.cc | 2 - src/gctools/gcweak.cc | 328 ----------------------- src/gctools/memoryManagement.cc | 6 +- src/gctools/snapshotSaveLoad.cc | 28 +- src/gctools/weak_scan.cc | 66 +---- src/lisp/kernel/cleavir/bir-to-bmir.lisp | 2 +- src/lisp/kernel/cleavir/transform.lisp | 2 +- src/lisp/kernel/cleavir/type.lisp | 2 +- 27 files changed, 249 insertions(+), 1507 deletions(-) delete mode 100644 include/clasp/core/hashTableBase.h delete mode 100644 include/clasp/core/weakHashTable.h delete mode 100644 src/core/weakHashTable.cc diff --git a/include/clasp/core/coretypes.h b/include/clasp/core/coretypes.h index 45964b8b58..2aee47f669 100644 --- a/include/clasp/core/coretypes.h +++ b/include/clasp/core/coretypes.h @@ -62,7 +62,6 @@ class Null_O; class Stream_O; class SourcePosInfo_O; class FileScope_O; -class WeakKeyHashTable_O; class DynamicScopeManager; class Function_O; diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index 43cecfd3bb..16adbd2ccf 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -29,7 +29,6 @@ THE SOFTWARE. #include #include #include -#include #include #include @@ -132,12 +131,12 @@ class WeakKeyMapping_O final : public Mapping_O { }; FORWARD(HashTable); -class HashTable_O : public HashTableBase_O { +class HashTable_O : public General_O { + LISP_CLASS(core, ClPkg, HashTable_O, "HashTable", General_O); friend T_sp cl__make_hash_table(T_sp test, Fixnum_sp size, Number_sp rehash_size, Real_sp orehash_threshold, Symbol_sp weakness, T_sp debug, T_sp thread_safe, T_sp hashf); friend class HashTableReadLock; friend class HashTableWriteLock; - LISP_CLASS(core, ClPkg, HashTable_O, "HashTable", HashTableBase_O); bool fieldsp() const override { return true; }; void fields(Record_sp node) override; @@ -206,8 +205,8 @@ class HashTable_O : public HashTableBase_O { virtual T_sp hashTableTest() const { SUBIMP(); }; /*! Return a count of the number of keys */ - size_t hashTableCount() const override; - size_t hashTableSize() const override; + size_t hashTableCount() const; + size_t hashTableSize() const; size_t size() { return this->hashTableCount(); }; // Return a symbol representing the weakness type. @@ -222,19 +221,19 @@ class HashTable_O : public HashTableBase_O { std::optional find(T_sp key); // gethash but more convenient for C++ - T_mv gethash(T_sp key, T_sp defaultValue = nil()) override; + T_mv gethash(T_sp key, T_sp defaultValue = nil()); gc::Fixnum hashIndex(T_sp key) const; - T_sp hash_table_setf_gethash(T_sp key, T_sp value) override; + T_sp hash_table_setf_gethash(T_sp key, T_sp value); void setf_gethash(T_sp key, T_sp val) { this->hash_table_setf_gethash(key, val); }; - Number_sp rehash_size() const override; - double rehash_threshold() const override; - T_sp hash_table_test() const override; + Number_sp rehash_size() const; + double rehash_threshold() const; + T_sp hash_table_test() const; - T_sp clrhash() override; + T_sp clrhash(); - bool remhash(T_sp key) override; + bool remhash(T_sp key); string __repr__() const override; @@ -242,7 +241,7 @@ class HashTable_O : public HashTableBase_O { void lowLevelMapHash(KeyValueMapper* mapper) const; - void maphash(T_sp fn) const override; + void maphash(T_sp fn) const; void mapHash(std::function const& fn) const; void maphash(std::function const& fn) const { this->mapHash(fn); }; diff --git a/include/clasp/core/hashTableBase.h b/include/clasp/core/hashTableBase.h deleted file mode 100644 index 9cb66a2563..0000000000 --- a/include/clasp/core/hashTableBase.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once -/* - File: hashTable.h -*/ - -/* -Copyright (c) 2014, Christian E. Schafmeister - -CLASP is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -See directory 'clasp/licenses' for full details. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -/* -^- */ - -#include - -namespace core { -FORWARD(HashTableBase); -class HashTableBase_O : public General_O { - LISP_ABSTRACT_CLASS(core, CorePkg, HashTableBase_O, "HashTableBase", core::General_O); - -public: - -public: - virtual T_sp hash_table_setf_gethash(T_sp key, T_sp value) = 0; - virtual T_mv gethash(T_sp key, T_sp default_value) = 0; - virtual bool remhash(T_sp key) = 0; - virtual Number_sp rehash_size() const = 0; - virtual double rehash_threshold() const = 0; - virtual T_sp hash_table_test() const = 0; - virtual void maphash(T_sp function_desig) const = 0; - virtual T_sp clrhash() = 0; - virtual size_t hashTableCount() const = 0; - virtual size_t hashTableSize() const = 0; -}; - -}; // namespace core diff --git a/include/clasp/core/sourceFileInfo.h b/include/clasp/core/sourceFileInfo.h index 82b4850a00..6bf4e37439 100644 --- a/include/clasp/core/sourceFileInfo.h +++ b/include/clasp/core/sourceFileInfo.h @@ -31,7 +31,7 @@ THE SOFTWARE. #include #include #include -#include +#include #include namespace core { diff --git a/include/clasp/core/weakHashTable.h b/include/clasp/core/weakHashTable.h deleted file mode 100644 index bc612be790..0000000000 --- a/include/clasp/core/weakHashTable.h +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once -/* - File: weakHashTable.h -*/ - -/* -Copyright (c) 2014, Christian E. Schafmeister - -CLASP is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -See directory 'clasp/licenses' for full details. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -/* -^- */ - -#include -#include -#include -#include -#include - -namespace cl { -extern core::Symbol_sp& _sym_eq; -}; - -template <> struct gctools::GCInfo { - static bool constexpr NeedsInitialization = true; - static bool constexpr NeedsFinalization = false; - static GCInfo_policy constexpr Policy = normal; -}; - -namespace core { -FORWARD(WeakKeyHashTable); -class WeakKeyHashTable_O : public HashTableBase_O { - LISP_CLASS(core, CorePkg, WeakKeyHashTable_O, "WeakKeyHashTable", HashTableBase_O); - -public: // instance variables here - typedef typename gctools::WeakKeyHashTable::value_type value_type; - typedef typename gctools::WeakKeyHashTable::KeyBucketsType KeyBucketsType; - typedef typename gctools::WeakKeyHashTable::ValueBucketsType ValueBucketsType; - typedef typename gctools::WeakKeyHashTable::KeyBucketsAllocatorType KeyBucketsAllocatorType; - typedef typename gctools::WeakKeyHashTable::ValueBucketsAllocatorType ValueBucketsAllocatorType; - typedef gctools::WeakKeyHashTable HashTableType; - -public: // Fields - HashTableType _HashTable; - -public: - WeakKeyHashTable_O(size_t sz, Number_sp rehashSize, double rehashThreshold) : _HashTable(sz, rehashSize, rehashThreshold){}; - WeakKeyHashTable_O(); - void initialize() override; - -public: - size_t hashTableCount() const override { return this->_HashTable.tableSize(); }; - cl_index size() const { return this->hashTableCount(); }; - size_t hashTableSize() const override { return this->_HashTable.length(); }; - - T_sp hash_table_setf_gethash(T_sp key, T_sp value) override; - - bool fullp(); - - void describe(T_sp stream) override; - virtual T_sp hashTableTest() const { return cl::_sym_eq; }; - bool keyTest(T_sp entryKey, T_sp searchKey) const; - - gc::Fixnum sxhashKey(T_sp key, gc::Fixnum bound, bool willAddKey) const; - - void maphashLowLevel(std::function const& fn); - void maphash(T_sp functionDesig) const override; - - T_mv gethash(T_sp key, T_sp defaultValue = nil()) override; - bool remhash(T_sp key) override; - T_sp clrhash() override; - Number_sp rehash_size() const override; - double rehash_threshold() const override; - T_sp hash_table_test() const override; - - string __repr__() const override; -}; -}; // namespace core - -namespace core { -WeakKeyHashTable_sp core__make_weak_key_hash_table(Fixnum_sp size); -}; diff --git a/include/clasp/gctools/exposeCommon.h b/include/clasp/gctools/exposeCommon.h index 4cc459142b..13eee47b1e 100644 --- a/include/clasp/gctools/exposeCommon.h +++ b/include/clasp/gctools/exposeCommon.h @@ -73,7 +73,8 @@ typedef bool _Bool; #include #include #include -#include +#include +#include #include // #include "core/symbolVector.h" #include @@ -111,7 +112,6 @@ typedef bool _Bool; #include #include #include -#include #include #include #include diff --git a/include/clasp/gctools/gcalloc.h b/include/clasp/gctools/gcalloc.h index fe2afb4c0f..a4d2f19613 100644 --- a/include/clasp/gctools/gcalloc.h +++ b/include/clasp/gctools/gcalloc.h @@ -559,102 +559,3 @@ class GCContainerAllocator /* : public GCAlloc */ { } }; }; // namespace gctools - -namespace gctools { - -struct WeakLinks {}; -struct StrongLinks {}; - -template struct Buckets; - -template class GCBucketAllocator {}; - -template class GCBucketAllocator> { -public: - typedef Buckets TY; - typedef TY container_type; - typedef container_type* container_pointer; - typedef typename container_type::value_type value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - static constexpr bool weakp = std::is_same_v; - - // return maximum number of elements that can be allocated - size_type max_size() const throw() { return std::numeric_limits::max() / sizeof(value_type); } - - // allocate but don't initialize num elements of type value_type - static gctools::tagged_pointer allocate(Header_s::BadgeStampWtagMtag the_header, size_type num, const void* = 0) { - size_t size = sizeof_container_with_header(num); - Header_s* base = do_weak_allocation(the_header, size); - container_pointer myAddress = (container_pointer)HeaderPtrToWeakPtr(base); - if (!myAddress) - throw_hard_error("Out of memory in allocate"); - new (myAddress) container_type(num); -#ifdef DEBUG_GCWEAK - printf("%s:%d Check if Buckets has been initialized to unbound\n", __FILE__, __LINE__); -#endif - return gctools::tagged_pointer(myAddress); - } - - static gctools::tagged_pointer snapshot_save_load_allocate(snapshotSaveLoad::snapshot_save_load_init_s* init) { - size_t size = (init->_clientEnd - init->_clientStart) + SizeofWeakHeader(); - Header_s* base = do_weak_allocation(init->_headStart->_badge_stamp_wtag_mtag, size); -#ifdef DEBUG_GUARD - // Copy the source from the image save/load memory. - base->_source = init->_headStart->_source; -#endif - container_pointer myAddress = (container_pointer)HeaderPtrToWeakPtr(base); - new (myAddress) container_type(init); - return gctools::tagged_pointer(myAddress); - } - - // initialize elements of allocated storage p with value value - template void construct(pointer p, ARGS&&... args) { - // initialize memory with placement new - throw_hard_error("What do I do here"); - // new((void*)p)value_type(std::forward(args)...); - } - - // destroy elements of initialized storage p - void destroy(pointer p) { - // Do nothing - } - - // deallocate storage p of deleted elements - void deallocate(gctools::tagged_pointer p, size_type num) { - // Do nothing - } -}; - -// ---------------------------------------------------------------------- -// ---------------------------------------------------------------------- -// ---------------------------------------------------------------------- -// ---------------------------------------------------------------------- - -template struct Mapping; - -template class GCMappingAllocator /* : public GCAlloc */ {}; - -template class GCMappingAllocator> { -public: - typedef Mapping TY; - typedef TY container_type; - typedef TY* container_pointer; - - // allocate but don't initialize num elements of type value_type - static gctools::tagged_pointer allocate(Header_s::BadgeStampWtagMtag the_header, const VT& val) { - size_t size = sizeof_with_header(); - Header_s* base = do_weak_allocation>(the_header, size); - container_pointer myAddress = (container_pointer)HeaderPtrToWeakPtr(base); - if (!myAddress) - throw_hard_error("Out of memory in allocate"); - new (myAddress) container_type(val); - printf("%s:%d Check if Mapping has been initialized to unbound\n", __FILE__, __LINE__); - return gctools::tagged_pointer(myAddress); - } -}; -}; // namespace gctools diff --git a/include/clasp/gctools/gcalloc_boehm.h b/include/clasp/gctools/gcalloc_boehm.h index f2482a6c43..c3e841171f 100644 --- a/include/clasp/gctools/gcalloc_boehm.h +++ b/include/clasp/gctools/gcalloc_boehm.h @@ -62,24 +62,6 @@ inline Header_s* do_atomic_allocation(const Header_s::StampWtagMtag& the_header, return header; }; -template -inline Header_s* do_weak_allocation(const Header_s::StampWtagMtag& the_header, size_t size) { - size_t true_size = size; - Header_s* header; - if constexpr(weakp) - header = reinterpret_cast(ALIGNED_GC_MALLOC_ATOMIC(true_size)); - else - header = reinterpret_cast(ALIGNED_GC_MALLOC_KIND(true_size, GC_I_NORMAL)); - my_thread_low_level->_Allocations.registerWeakAllocation(the_header._value, true_size); -#ifdef DEBUG_GUARD - memset(header, 0x00, true_size); - new (header) Header_s(the_header, 0, 0, true_size); -#else - new (header) Header_s(the_header); -#endif - return header; -}; - template inline Header_s* do_general_allocation(const Header_s::StampWtagMtag& the_header, size_t size) { RAIIAllocationStage stage(my_thread_low_level); diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index 6a9738a257..1a101d15da 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -75,310 +75,6 @@ THE SOFTWARE. namespace gctools { -#if defined(USE_BOEHM) && !defined(CLASP_THREADS) -#define call_with_alloc_lock GC_call_with_alloc_lock -#else -typedef void* (*fn_type)(void* client_data); -inline void call_with_alloc_lock(fn_type fn, void* client_data) { fn(client_data); } - -#endif - -template requires std::invocable -static void* wrapRun(void* f) { - F* gf = (F*)f; - (*gf)(); - return nullptr; -} - -template requires std::invocable -void safeRun(F&& f) { - call_with_alloc_lock(wrapRun, (void*)&f); -} -}; // namespace gctools - -namespace gctools { - -struct WeakObject { - virtual void* dependentPtr() const { return NULL; }; -}; - -struct weak_fwd_s : public WeakObject { - WeakObject* fwd; /* forwarded object */ - gctools::smart_ptr size; /* total size of this object */ -}; - -struct weak_fwd2_s : public WeakObject { - WeakObject* fwd; /* forwarded object */ -}; - -struct weak_pad_s : public WeakObject { - // WeakObject *fwd; /* forwarded object */ /*WHY!!*// - gctools::smart_ptr size; /* total size of this object */ -}; - -struct weak_pad1_s : public WeakObject {}; - -template struct BucketsBase : public WeakObject { - BucketsBase() = default; - BucketsBase(int l) : _length(l), _used(0), _deleted(0) { - for (size_t i(0); i < l; ++i) { - this->bucket[i] = T((gctools::Tagged)gctools::tag_unbound()); - } - } - - T& operator[](size_t idx) { return this->bucket[idx]; }; - typedef T value_type; - typedef gctools::tagged_pointer> dependent_type; - dependent_type dependent; /* the dependent object */ - size_t _length; /* number of buckets */ - size_t _used; /* number of buckets in use */ - size_t _deleted; /* number of deleted buckets */ - T bucket[0]; /* hash buckets */ - - void* dependentPtr() const { - if (this->dependent) - return reinterpret_cast(&*this->dependent); - return NULL; - }; - - size_t length() const { return _length; } - void setLength(size_t l) { _length = l; } - int used() const { return _used; } - void setUsed(size_t val) { _used = val; } - int deleted() const { return _deleted; } - void setDeleted(size_t val) { _deleted = val; } -}; - -template struct Buckets; - -#ifdef USE_BOEHM -inline bool unboundOrDeletedOrSplatted(core::T_sp bucket) { - return (bucket.unboundp() // unbound - || bucket.deletedp() // deleted - || !bucket // splatted by Boehm - ); -} -#endif - -template struct Buckets : public BucketsBase { - typedef typename BucketsBase::value_type value_type; - Buckets(int l) : BucketsBase(l){}; - Buckets(snapshotSaveLoad::snapshot_save_load_init_s* isl) { isl->fill((void*)this); } - - void set(size_t idx, const value_type& val) { - if (!(val.objectp() || val.deletedp() || val.unboundp())) { - printf("%s:%d Only objectp() objects can be added to Mapping - tried to add %p\n", __FILE__, __LINE__, val.raw_()); - abort(); - } -#if defined(USE_BOEHM) - // printf("%s:%d ---- Buckets set idx: %zu this->bucket[idx] = %p\n", __FILE__, __LINE__, idx, this->bucket[idx].raw_() - //); - if (!unboundOrDeletedOrSplatted(this->bucket[idx])) { - auto& rawRef = this->bucket[idx].rawRef_(); - void** linkAddress = reinterpret_cast(&rawRef); - int result = GC_unregister_disappearing_link(linkAddress); // reinterpret_cast(&this->bucket[idx].rawRef_())); - if (!result) - throw_hard_error("The link was not registered as a disappearing link!"); - } - this->bucket[idx] = val; - // We need the base of the object that we want a weak pointer to... - // general, cons and later weak objects have different header sizes - void* base = NULL; - if (val.generalp()) { - base = gctools::GeneralPtrToHeaderPtr(&*(val)); - } else if (val.consp()) { - base = gctools::ConsPtrToHeaderPtr(&*(val)); - } - if (base) - GC_general_register_disappearing_link(reinterpret_cast(&this->bucket[idx].rawRef_()), base); -#elif defined(USE_MPS) - this->bucket[idx] = val; -#elif defined(USE_MMTK) - THROW_HARD_ERROR("Add support for mmtk"); -#endif - } -}; - -template struct Buckets : public BucketsBase { - typedef typename BucketsBase::value_type value_type; - Buckets(int l) : BucketsBase(l){}; - Buckets(snapshotSaveLoad::snapshot_save_load_init_s* isl) { isl->fill((void*)this); } - void set(size_t idx, const value_type& val) { - this->bucket[idx] = val; - } -}; - -typedef gctools::smart_ptr BucketValueType; -typedef gctools::Buckets WeakBucketsObjectType; -typedef gctools::Buckets StrongBucketsObjectType; - -class WeakKeyHashTable { - friend class core::WeakKeyHashTable_O; - -public: - typedef BucketValueType value_type; - typedef WeakBucketsObjectType KeyBucketsType; - typedef StrongBucketsObjectType ValueBucketsType; - -public: - typedef WeakKeyHashTable MyType; - -public: - typedef gctools::GCBucketAllocator KeyBucketsAllocatorType; - typedef gctools::GCBucketAllocator ValueBucketsAllocatorType; - -public: - size_t _Length; - core::Number_sp _RehashSize; - double _RehashThreshold; - gctools::tagged_pointer _Keys; // hash buckets for keys - gctools::tagged_pointer _Values; // hash buckets for values -#ifdef CLASP_THREADS - mutable mp::SharedMutex_sp _Mutex; -#endif -public: - WeakKeyHashTable(size_t length, core::Number_sp rehashSize, double rehashThreshold) - : _Length(length), _RehashSize(rehashSize), _RehashThreshold(rehashThreshold){}; - void initialize(); - -public: - static uint sxhashKey(const value_type& key); - - /*! Return 0 if there is no more room in the sequence of entries for the key - Return 1 if the element is found or an unbound or deleted entry is found. - Return the entry index in (b) - */ - static size_t find_no_lock(gctools::tagged_pointer keys, const value_type& key, size_t& b); - -public: - void setupThreadSafeHashTable(); - size_t length() const { - if (!this->_Keys) { - throw_hard_error("Keys should never be null"); - } - return this->_Keys->length(); - } - - void swap(MyType& other) { - gctools::tagged_pointer tempKeys = this->_Keys; - gctools::tagged_pointer tempValues = this->_Values; - core::Number_sp rehashSize = this->_RehashSize; - double rehashThreshold = this->_RehashThreshold; - this->_Keys = other._Keys; - this->_Values = other._Values; - this->_RehashSize = other._RehashSize; - this->_RehashThreshold = other._RehashThreshold; - other._Keys = tempKeys; - other._Values = tempValues; - other._RehashSize = rehashSize; - other._RehashThreshold = rehashThreshold; - } - - bool fullp_not_safe() const { - bool fp; - fp = (*this->_Keys).used() >= (this->_RehashThreshold * (*this->_Keys).length()); - return fp; - } - - bool fullp() const { - bool fp; - safeRun([&fp, this]() { fp = (*this->_Keys).used() >= (*this->_Keys).length() / 2; }); - return fp; - } - - int tableSize() const { - int result; - safeRun([&result, this]() { - size_t used, deleted; - used = this->_Keys->used(); - deleted = this->_Keys->deleted(); - GCTOOLS_ASSERT(used >= deleted); - result = used - deleted; - }); - return result; - } - - int rehash_not_safe(const value_type& key, size_t& key_bucket); - int rehash(const value_type& key, size_t& key_bucket); - int trySet(core::T_sp tkey, core::T_sp value); - - string dump(const string& prefix); - - core::T_mv gethash(core::T_sp tkey, core::T_sp defaultValue); - void set(core::T_sp key, core::T_sp value); - void maphash(std::function const& fn) const; - void maphashFn(core::T_sp fn) const; - bool remhash(core::T_sp tkey); - void clrhash(); - core::Vector_sp pairs() const; -}; - -// ====================================================================== -// ---------------------------------------------------------------------- - -template struct MappingBase : public WeakObject { - MappingBase(const T& val) : bucket(val){}; - typedef T value_type; - void* dependentPtr() const { - if (this->dependent) - return reinterpret_cast(&*this->dependent); - return NULL; - }; - typedef gctools::tagged_pointer> dependent_type; - dependent_type dependent; /* the dependent object */ - T bucket; /* single buckets */ -}; - -template struct Mapping; - -template struct Mapping : public MappingBase { - typedef typename MappingBase::value_type value_type; - typedef typename MappingBase::dependent_type dependent_type; - Mapping(const T& val) : MappingBase(val) { - if (!val.objectp()) { - printf("%s:%d Only objectp() objects can be added to Mapping\n", __FILE__, __LINE__); - abort(); - } -#if defined(USE_BOEHM) - GCTOOLS_ASSERT(this->bucket.objectp()); - if (!unboundOrDeletedOrSplatted(this->bucket)) { - // printf("%s:%d Mapping register disappearing link\n", __FILE__, __LINE__); - GC_general_register_disappearing_link(reinterpret_cast(&this->bucket.rawRef_()), - reinterpret_cast(this->bucket.rawRef_())); - } -#else - THROW_HARD_ERROR("Add support for new GC"); -#endif - }; -}; - -template struct Mapping : public MappingBase { - typedef typename MappingBase::value_type value_type; - Mapping(const T& val) : MappingBase(val){}; -}; - -typedef gctools::smart_ptr MappingValueType; -typedef gctools::Mapping WeakMappingObjectType; -typedef gctools::Mapping StrongMappingObjectType; - -template -struct TaggedCast, gctools::smart_ptr>*, FROM> { - typedef gctools::BucketsBase, gctools::smart_ptr>* ToType; - typedef FROM FromType; - inline static bool isA(FromType tagged_client) { - if (tagged_generalp(tagged_client)) { - // Should I have more here? - return dynamic_cast(untag_general(tagged_client)) != NULL; - } - return false; - } - inline static ToType castOrNULL(FromType client) { - if (TaggedCast::isA(client)) - return reinterpret_cast(client); - return NULL; - } -}; - // This structure is meant to be included directly (not as a pointer) in // a weak pointer object, e.g. WeakPointer_O. In order to ensure the pointer // is not scanned, this should be allocated with the "atomic" GC policy. diff --git a/include/clasp/gctools/memoryManagement.h b/include/clasp/gctools/memoryManagement.h index 381fadc25a..418fac00ee 100644 --- a/include/clasp/gctools/memoryManagement.h +++ b/include/clasp/gctools/memoryManagement.h @@ -375,14 +375,6 @@ class BaseHeader_s { // typedef uint32_t badge_t; - typedef enum { - WeakBucketKind = ((1 << mtag_shift) | weak_mtag), - StrongBucketKind = ((2 << mtag_shift) | weak_mtag), - WeakMappingKind = ((3 << mtag_shift) | weak_mtag), - StrongMappingKind = ((4 << mtag_shift) | weak_mtag), - MaxWeakKind = ((5 << mtag_shift) | weak_mtag) - } WeakKinds; - // // struct Dummy_s {}; @@ -392,7 +384,6 @@ class BaseHeader_s { tagged_stamp_t _value; StampWtagMtag() : _value(0){}; StampWtagMtag(Value all) : _value(all){}; - StampWtagMtag(WeakKinds kind) : _value(kind){}; // WHAT IS GOING ON // StampWtagMtag(UnshiftedStamp stamp, badge_t badge) : _value(shift_unshifted_stamp(stamp)), _header_badge(badge) {}; @@ -557,7 +548,6 @@ class BaseHeader_s { } #endif }; - BadgeStampWtagMtag(WeakKinds kind) : StampWtagMtag(kind), _header_badge((uintptr_t)this & 0xFFFFFFFF){}; }; static inline int Stamp(StampWtagMtag stamp_wtag_mtag) { diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index 007f68c366..9f5834ecbd 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -24,7 +24,7 @@ "core::Scope_O" "core::BytecodeDebugLocation_O" "llvmo::InsertPoint_O" "core::FunctionDescription_O" "core::ComplexVector_double_O" "core::StrWNs_O" "core::UnknownDynEnv_O" "core::EchoStream_O" - "core::HashTableBase_O" "core::SimpleMDArrayBit_O" "core::MDArrayBit_O" + "core::SimpleMDArrayBit_O" "core::MDArrayBit_O" "core::ComplexVector_byte16_t_O" "comp::BlockInfo_O" "llvmo::DILocalScope_O" "asttooling::DerivableFrontendActionFactory" "comp::Label_O" "core::ComplexVector_int2_t_O" "llvmo::DILexicalBlock_O" @@ -61,17 +61,17 @@ "core::MDArray_int8_t_O" "core::Ephemeron_O" "core::BytecodeDebugVar_O" "llvmo::ConstantFP_O" "core::BlockDynEnv_O" "core::Cons_O" "clbind::detail::vertex" "llvmo::LLVMContext_O" "core::MDArray_int4_t_O" - "core::WeakKeyHashTable_O" "core::Rack_O" "core::MDArrayBaseChar_O" - "core::UserData_O" "core::ExternalObject_O" "llvmo::DINode_O" - "llvmo::GlobalVariable_O" "core::SimpleVector_short_float_O" - "core::BroadcastStream_O" "core::General_O" "llvmo::MemoryBuffer_O" - "llvmo::ObjectFile_O" "core::BytecodeSimpleFun_O" "llvmo::Library_O" - "core::Closure_O" "core::ComplexVector_size_t_O" "comp::RestoreSPFixup_O" - "mpip::Mpi_O" "llvmo::DINodeArray_O" "llvmo::ConstantDataArray_O" - "core::SmallMap_O" "core::Instance_O" "llvmo::TargetOptions_O" - "core::CoreFunGenerator_O" "clasp_ffi::ForeignTypeSpec_O" - "core::Unused_dummy_O" "llvmo::DWARFContext_O" "core::HashTableEqual_O" - "llvmo::Triple_O" "core::SimpleMDArray_byte64_t_O" "core::BitVectorNs_O" + "core::Rack_O" "core::MDArrayBaseChar_O" "core::UserData_O" + "core::ExternalObject_O" "llvmo::DINode_O" "llvmo::GlobalVariable_O" + "core::SimpleVector_short_float_O" "core::BroadcastStream_O" + "core::General_O" "llvmo::MemoryBuffer_O" "llvmo::ObjectFile_O" + "core::BytecodeSimpleFun_O" "llvmo::Library_O" "core::Closure_O" + "core::ComplexVector_size_t_O" "comp::RestoreSPFixup_O" "mpip::Mpi_O" + "llvmo::DINodeArray_O" "llvmo::ConstantDataArray_O" "core::SmallMap_O" + "core::Instance_O" "llvmo::TargetOptions_O" "core::CoreFunGenerator_O" + "clasp_ffi::ForeignTypeSpec_O" "core::Unused_dummy_O" + "llvmo::DWARFContext_O" "core::HashTableEqual_O" "llvmo::Triple_O" + "core::SimpleMDArray_byte64_t_O" "core::BitVectorNs_O" "core::CoreExposer_O" "core::BytecodeDebugVars_O" "comp::JumpIfSuppliedFixup_O" "llvmo::NamedMDNode_O" "core::SimpleVector_byte16_t_O" "llvmo::ThreadSafeContext_O" @@ -4877,131 +4877,6 @@ :offset-base-ctype "comp::BlockInfo_O" :layout-offset-field-names ("_exit")} {fixed-field :offset-type-cxx-identifier "ctype_int" :offset-ctype "int" :offset-base-ctype "comp::BlockInfo_O" :layout-offset-field-names ("_receiving")} -{class-kind :stamp-name "STAMPWTAG_core__HashTableBase_O" :stamp-key "core::HashTableBase_O" - :parent-class "core::General_O" :lisp-class-base "core::General_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__WeakKeyHashTable_O" :stamp-key "core::WeakKeyHashTable_O" - :parent-class "core::HashTableBase_O" :lisp-class-base "core::HashTableBase_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._Length")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._RehashSize")} -{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer,gctools::smart_ptr,gctools::WeakLinks>>" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._Keys")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer,gctools::smart_ptr,gctools::StrongLinks>>" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._Values")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._Mutex")} -{class-kind :stamp-name "STAMPWTAG_core__HashTable_O" :stamp-key "core::HashTable_O" - :parent-class "core::HashTableBase_O" :lisp-class-base "core::HashTableBase_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_RehashSize")} -{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" - :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Mutex")} -{class-kind :stamp-name "STAMPWTAG_core__HashTableEqualp_O" :stamp-key "core::HashTableEqualp_O" - :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEqualp_O" - :layout-offset-field-names ("_RehashSize")} -{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" - :offset-base-ctype "core::HashTableEqualp_O" - :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Mutex")} -{class-kind :stamp-name "STAMPWTAG_core__HashTableEq_O" :stamp-key "core::HashTableEq_O" - :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_RehashSize")} -{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" - :offset-base-ctype "core::HashTableEq_O" - :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Mutex")} -{class-kind :stamp-name "STAMPWTAG_core__HashTableEql_O" :stamp-key "core::HashTableEql_O" - :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_RehashSize")} -{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" - :offset-base-ctype "core::HashTableEql_O" - :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Mutex")} -{class-kind :stamp-name "STAMPWTAG_core__HashTableEqual_O" :stamp-key "core::HashTableEqual_O" - :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_RehashSize")} -{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" - :offset-base-ctype "core::HashTableEqual_O" - :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Mutex")} -{class-kind :stamp-name "STAMPWTAG_core__HashTableCustom_O" :stamp-key "core::HashTableCustom_O" - :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableCustom_O" - :layout-offset-field-names ("_RehashSize")} -{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" - :offset-base-ctype "core::HashTableCustom_O" - :layout-offset-field-names ("_RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Table")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Mutex")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("comparator")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("hasher")} {class-kind :stamp-name "STAMPWTAG_core__FunctionDescription_O" :stamp-key "core::FunctionDescription_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 @@ -5730,6 +5605,103 @@ {class-kind :stamp-name "STAMPWTAG_core__FileStatus_O" :stamp-key "core::FileStatus_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__HashTable_O" :stamp-key "core::HashTable_O" + :parent-class "core::General_O" :lisp-class-base "core::General_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_RehashSize")} +{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" + :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_RehashThreshold")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Table")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTable_O" :layout-offset-field-names ("_Mutex")} +{class-kind :stamp-name "STAMPWTAG_core__HashTableEqualp_O" :stamp-key "core::HashTableEqualp_O" + :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqualp_O" + :layout-offset-field-names ("_RehashSize")} +{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" + :offset-base-ctype "core::HashTableEqualp_O" + :layout-offset-field-names ("_RehashThreshold")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Table")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqualp_O" :layout-offset-field-names ("_Mutex")} +{class-kind :stamp-name "STAMPWTAG_core__HashTableEq_O" :stamp-key "core::HashTableEq_O" + :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_RehashSize")} +{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" + :offset-base-ctype "core::HashTableEq_O" + :layout-offset-field-names ("_RehashThreshold")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Table")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEq_O" :layout-offset-field-names ("_Mutex")} +{class-kind :stamp-name "STAMPWTAG_core__HashTableEql_O" :stamp-key "core::HashTableEql_O" + :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_RehashSize")} +{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" + :offset-base-ctype "core::HashTableEql_O" + :layout-offset-field-names ("_RehashThreshold")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Table")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Mutex")} +{class-kind :stamp-name "STAMPWTAG_core__HashTableEqual_O" :stamp-key "core::HashTableEqual_O" + :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_RehashSize")} +{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" + :offset-base-ctype "core::HashTableEqual_O" + :layout-offset-field-names ("_RehashThreshold")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Table")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableEqual_O" :layout-offset-field-names ("_Mutex")} +{class-kind :stamp-name "STAMPWTAG_core__HashTableCustom_O" :stamp-key "core::HashTableCustom_O" + :parent-class "core::HashTable_O" :lisp-class-base "core::HashTable_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableCustom_O" + :layout-offset-field-names ("_RehashSize")} +{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" + :offset-base-ctype "core::HashTableCustom_O" + :layout-offset-field-names ("_RehashThreshold")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Table")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("_Mutex")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("comparator")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::HashTableCustom_O" :layout-offset-field-names ("hasher")} {class-kind :stamp-name "STAMPWTAG_comp__FunctionCellInfo_O" :stamp-key "comp::FunctionCellInfo_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index 64dc73832e..1e34c7a285 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -47,7 +47,7 @@ "core::ComplexVector_double_O" "core::StrWNs_O" "chem::Structure_Old_ListEntry_O" "core::UnknownDynEnv_O" "chem::EnergyRigidBodyStaple_O" "core::EchoStream_O" - "core::HashTableBase_O" "core::SimpleMDArrayBit_O" "core::MDArrayBit_O" + "core::SimpleMDArrayBit_O" "core::MDArrayBit_O" "core::ComplexVector_byte16_t_O" "chem::FFStretchDb_O" "comp::BlockInfo_O" "geom::OVector2_O" "chem::AtomPriority" "llvmo::DILocalScope_O" "chem::Branch_O" "geom::OVector3_O" @@ -108,11 +108,11 @@ "core::Cons_O" "clbind::detail::vertex" "chem::ImproperTorsion_O" "chem::ZMatrixAngleInternal_O" "chem::Rotamer_O" "llvmo::LLVMContext_O" "chem::EnergyAnchorRestraint" "core::MDArray_int4_t_O" - "core::WeakKeyHashTable_O" "chem::FFNonbondCrossTerm" "core::Rack_O" - "core::MDArrayBaseChar_O" "core::UserData_O" "core::ExternalObject_O" - "llvmo::DINode_O" "llvmo::GlobalVariable_O" - "core::SimpleVector_short_float_O" "core::BroadcastStream_O" - "chem::FFBaseDb_O" "chem::AbstractLargeSquareMatrix_O" "core::General_O" + "chem::FFNonbondCrossTerm" "core::Rack_O" "core::MDArrayBaseChar_O" + "core::UserData_O" "core::ExternalObject_O" "llvmo::DINode_O" + "llvmo::GlobalVariable_O" "core::SimpleVector_short_float_O" + "core::BroadcastStream_O" "chem::FFBaseDb_O" + "chem::AbstractLargeSquareMatrix_O" "core::General_O" "core::BytecodeSimpleFun_O" "llvmo::MemoryBuffer_O" "llvmo::ObjectFile_O" "chem::ConformationExplorerMatch_O" "llvmo::Library_O" "core::Closure_O" "core::ComplexVector_size_t_O" "chem::RestraintAngle_O" @@ -5896,11 +5896,103 @@ :layout-offset-field-names ("_decls")} {fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" :offset-base-ctype "comp::Lexenv_O" :layout-offset-field-names ("frame_end")} -{class-kind :stamp-name "STAMPWTAG_core__HashTableBase_O" :stamp-key "core::HashTableBase_O" +{class-kind :stamp-name "STAMPWTAG_core__FunctionDescription_O" + :stamp-key "core::FunctionDescription_O" :parent-class "core::General_O" + :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 + :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::FunctionDescription_O" + :layout-offset-field-names ("_functionName")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::FunctionDescription_O" + :layout-offset-field-names ("_sourcePathname")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::FunctionDescription_O" + :layout-offset-field-names ("_lambdaList")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::FunctionDescription_O" + :layout-offset-field-names ("_docstring")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" + :offset-base-ctype "core::FunctionDescription_O" + :layout-offset-field-names ("_declares")} +{fixed-field :offset-type-cxx-identifier "ctype_int" :offset-ctype "int" + :offset-base-ctype "core::FunctionDescription_O" :layout-offset-field-names ("lineno")} +{fixed-field :offset-type-cxx-identifier "ctype_int" :offset-ctype "int" + :offset-base-ctype "core::FunctionDescription_O" :layout-offset-field-names ("column")} +{fixed-field :offset-type-cxx-identifier "ctype_int" :offset-ctype "int" + :offset-base-ctype "core::FunctionDescription_O" + :layout-offset-field-names ("filepos")} +{class-kind :stamp-name "STAMPWTAG_llvmo__InsertPoint_O" :stamp-key "llvmo::InsertPoint_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__Number_O" :stamp-key "core::Number_O" + :parent-class "core::General_O" :lisp-class-base "core::General_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__Real_O" :stamp-key "core::Real_O" + :parent-class "core::Number_O" :lisp-class-base "core::Number_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__Rational_O" :stamp-key "core::Rational_O" + :parent-class "core::Real_O" :lisp-class-base "core::Real_O" :root-class "core::T_O" + :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__Ratio_O" :stamp-key "core::Ratio_O" + :parent-class "core::Rational_O" :lisp-class-base "core::Rational_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Ratio_O" + :layout-offset-field-names ("_numerator")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Ratio_O" + :layout-offset-field-names ("_denominator")} +{class-kind :stamp-name "STAMPWTAG_core__Integer_O" :stamp-key "core::Integer_O" + :parent-class "core::Rational_O" :lisp-class-base "core::Rational_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__Bignum_O" :stamp-key "core::Bignum_O" + :parent-class "core::Integer_O" :lisp-class-base "core::Integer_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{variable-array0 :offset-base-ctype "core::Bignum_O" :field-names ("_limbs" "._Data")} +{variable-capacity :ctype "unsigned long" :offset-base-ctype "core::Bignum_O" + :length-field-names ("_limbs" "._MaybeSignedLength") + :end-field-names ("_limbs" "._MaybeSignedLength")} +{variable-field-only :offset-type-cxx-identifier "ctype_unsigned_long" :fixup-type "unsigned long"} +{class-kind :stamp-name "STAMPWTAG_core__Fixnum_dummy_O" :stamp-key "core::Fixnum_dummy_O" + :parent-class "core::Integer_O" :lisp-class-base "core::Integer_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__Float_O" :stamp-key "core::Float_O" + :parent-class "core::Real_O" :lisp-class-base "core::Real_O" :root-class "core::T_O" + :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__DoubleFloat_O" :stamp-key "core::DoubleFloat_O" + :parent-class "core::Float_O" :lisp-class-base "core::Float_O" :root-class "core::T_O" + :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" + :offset-base-ctype "core::DoubleFloat_O" :layout-offset-field-names ("_Value")} +{class-kind :stamp-name "STAMPWTAG_core__SingleFloat_dummy_O" + :stamp-key "core::SingleFloat_dummy_O" :parent-class "core::Float_O" + :lisp-class-base "core::Float_O" :root-class "core::T_O" :stamp-wtag 3 + :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__LongFloat_O" :stamp-key "core::LongFloat_O" + :parent-class "core::Float_O" :lisp-class-base "core::Float_O" :root-class "core::T_O" + :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_long_double" :offset-ctype "long double" + :offset-base-ctype "core::LongFloat_O" :layout-offset-field-names ("_Value")} +{class-kind :stamp-name "STAMPWTAG_core__ShortFloat_O" :stamp-key "core::ShortFloat_O" + :parent-class "core::Float_O" :lisp-class-base "core::Float_O" :root-class "core::T_O" + :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{class-kind :stamp-name "STAMPWTAG_core__Complex_O" :stamp-key "core::Complex_O" + :parent-class "core::Number_O" :lisp-class-base "core::Number_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Complex_O" + :layout-offset-field-names ("_real")} +{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" + :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Complex_O" + :layout-offset-field-names ("_imaginary")} {class-kind :stamp-name "STAMPWTAG_core__HashTable_O" :stamp-key "core::HashTable_O" - :parent-class "core::HashTableBase_O" :lisp-class-base "core::HashTableBase_O" + :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" @@ -5996,126 +6088,6 @@ {fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::HashTableEql_O" :layout-offset-field-names ("_Mutex")} -{class-kind :stamp-name "STAMPWTAG_core__WeakKeyHashTable_O" :stamp-key "core::WeakKeyHashTable_O" - :parent-class "core::HashTableBase_O" :lisp-class-base "core::HashTableBase_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._Length")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._RehashSize")} -{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._RehashThreshold")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer,gctools::smart_ptr,gctools::WeakLinks>>" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._Keys")} -{fixed-field :offset-type-cxx-identifier "TAGGED_POINTER_OFFSET" - :offset-ctype "gctools::tagged_pointer,gctools::smart_ptr,gctools::StrongLinks>>" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._Values")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::WeakKeyHashTable_O" - :layout-offset-field-names ("_HashTable" "._Mutex")} -{class-kind :stamp-name "STAMPWTAG_core__FunctionDescription_O" - :stamp-key "core::FunctionDescription_O" :parent-class "core::General_O" - :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 - :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::FunctionDescription_O" - :layout-offset-field-names ("_functionName")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::FunctionDescription_O" - :layout-offset-field-names ("_sourcePathname")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::FunctionDescription_O" - :layout-offset-field-names ("_lambdaList")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::FunctionDescription_O" - :layout-offset-field-names ("_docstring")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" - :offset-base-ctype "core::FunctionDescription_O" - :layout-offset-field-names ("_declares")} -{fixed-field :offset-type-cxx-identifier "ctype_int" :offset-ctype "int" - :offset-base-ctype "core::FunctionDescription_O" :layout-offset-field-names ("lineno")} -{fixed-field :offset-type-cxx-identifier "ctype_int" :offset-ctype "int" - :offset-base-ctype "core::FunctionDescription_O" :layout-offset-field-names ("column")} -{fixed-field :offset-type-cxx-identifier "ctype_int" :offset-ctype "int" - :offset-base-ctype "core::FunctionDescription_O" - :layout-offset-field-names ("filepos")} -{class-kind :stamp-name "STAMPWTAG_llvmo__InsertPoint_O" :stamp-key "llvmo::InsertPoint_O" - :parent-class "core::General_O" :lisp-class-base "core::General_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__Number_O" :stamp-key "core::Number_O" - :parent-class "core::General_O" :lisp-class-base "core::General_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__Real_O" :stamp-key "core::Real_O" - :parent-class "core::Number_O" :lisp-class-base "core::Number_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__Rational_O" :stamp-key "core::Rational_O" - :parent-class "core::Real_O" :lisp-class-base "core::Real_O" :root-class "core::T_O" - :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__Ratio_O" :stamp-key "core::Ratio_O" - :parent-class "core::Rational_O" :lisp-class-base "core::Rational_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Ratio_O" - :layout-offset-field-names ("_numerator")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Ratio_O" - :layout-offset-field-names ("_denominator")} -{class-kind :stamp-name "STAMPWTAG_core__Integer_O" :stamp-key "core::Integer_O" - :parent-class "core::Rational_O" :lisp-class-base "core::Rational_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__Bignum_O" :stamp-key "core::Bignum_O" - :parent-class "core::Integer_O" :lisp-class-base "core::Integer_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{variable-array0 :offset-base-ctype "core::Bignum_O" :field-names ("_limbs" "._Data")} -{variable-capacity :ctype "unsigned long" :offset-base-ctype "core::Bignum_O" - :length-field-names ("_limbs" "._MaybeSignedLength") - :end-field-names ("_limbs" "._MaybeSignedLength")} -{variable-field-only :offset-type-cxx-identifier "ctype_unsigned_long" :fixup-type "unsigned long"} -{class-kind :stamp-name "STAMPWTAG_core__Fixnum_dummy_O" :stamp-key "core::Fixnum_dummy_O" - :parent-class "core::Integer_O" :lisp-class-base "core::Integer_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__Float_O" :stamp-key "core::Float_O" - :parent-class "core::Real_O" :lisp-class-base "core::Real_O" :root-class "core::T_O" - :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__DoubleFloat_O" :stamp-key "core::DoubleFloat_O" - :parent-class "core::Float_O" :lisp-class-base "core::Float_O" :root-class "core::T_O" - :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "ctype_double" :offset-ctype "double" - :offset-base-ctype "core::DoubleFloat_O" :layout-offset-field-names ("_Value")} -{class-kind :stamp-name "STAMPWTAG_core__SingleFloat_dummy_O" - :stamp-key "core::SingleFloat_dummy_O" :parent-class "core::Float_O" - :lisp-class-base "core::Float_O" :root-class "core::T_O" :stamp-wtag 3 - :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__LongFloat_O" :stamp-key "core::LongFloat_O" - :parent-class "core::Float_O" :lisp-class-base "core::Float_O" :root-class "core::T_O" - :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "ctype_long_double" :offset-ctype "long double" - :offset-base-ctype "core::LongFloat_O" :layout-offset-field-names ("_Value")} -{class-kind :stamp-name "STAMPWTAG_core__ShortFloat_O" :stamp-key "core::ShortFloat_O" - :parent-class "core::Float_O" :lisp-class-base "core::Float_O" :root-class "core::T_O" - :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{class-kind :stamp-name "STAMPWTAG_core__Complex_O" :stamp-key "core::Complex_O" - :parent-class "core::Number_O" :lisp-class-base "core::Number_O" - :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Complex_O" - :layout-offset-field-names ("_real")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Complex_O" - :layout-offset-field-names ("_imaginary")} {class-kind :stamp-name "STAMPWTAG_comp__FunctionCellInfo_O" :stamp-key "comp::FunctionCellInfo_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/core/bytecode_compiler.cc b/src/core/bytecode_compiler.cc index a15f0a417b..0b78f935f6 100644 --- a/src/core/bytecode_compiler.cc +++ b/src/core/bytecode_compiler.cc @@ -5,6 +5,7 @@ #include // calledFunctionDesignator #include // gensym, function_block_name #include // source info stuff +#include // also for source info #include #include #include // max @@ -1455,8 +1456,8 @@ static void warn_ignorance(List_sp bindings) { static T_sp source_location_for(T_sp form, T_sp fallback) { if (_sym_STARsourceLocationsSTAR->boundP()) { T_sp table = _sym_STARsourceLocationsSTAR->symbolValue(); - if (gc::IsA(table)) - return gc::As_unsafe(table)->gethash(form, fallback); + if (gc::IsA(table)) + return gc::As_unsafe(table)->gethash(form, fallback); } return fallback; } diff --git a/src/core/corePackage.cc b/src/core/corePackage.cc index 34afeecff9..4537427ff7 100644 --- a/src/core/corePackage.cc +++ b/src/core/corePackage.cc @@ -87,7 +87,6 @@ THE SOFTWARE. #include #include #include -#include #include #include #include diff --git a/src/core/cscript.lisp b/src/core/cscript.lisp index 2eb53a94ed..543ae3feab 100644 --- a/src/core/cscript.lisp +++ b/src/core/cscript.lisp @@ -6,7 +6,6 @@ #~"function.cc" #~"creator.cc" #~"sharpEqualWrapper.cc" - #~"weakHashTable.cc" #~"weakPointer.cc" #~"compiler.cc" #~"instance.cc" diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index cd2dcea491..c9cc1a1cdc 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -78,7 +78,6 @@ THE SOFTWARE. #include #include #include -#include #include #ifdef CLASP_THREADS #ifdef _TARGET_OS_LINUX @@ -155,14 +154,8 @@ Vector_sp HashTable_O::pairs() const { } DOCGROUP(clasp); -CL_DEFUN Vector_sp core__hash_table_pairs(HashTableBase_sp hash_table_base) { - if (gc::IsA(hash_table_base)) { - return hash_table_base.as_unsafe()->pairs(); - } else if (gc::IsA(hash_table_base)) { - WeakKeyHashTable_sp hash_table = gc::As_unsafe(hash_table_base); - return hash_table->_HashTable.pairs(); - } - TYPE_ERROR(hash_table_base, Cons_O::createList(cl::_sym_or, cl::_sym_HashTable_O, core::_sym_WeakKeyHashTable_O)); +CL_DEFUN Vector_sp core__hash_table_pairs(HashTable_sp hash_table) { + return hash_table->pairs(); } // ---------------------------------------------------------------------- @@ -224,9 +217,6 @@ CL_DECLARE(); CL_DOCSTRING(R"dx(hash_table_weakness)dx"); DOCGROUP(clasp); CL_DEFUN Symbol_sp core__hash_table_weakness(T_sp ht) { - if (gc::IsA(ht)) { - return kw::_sym_key; - } return ht.as()->weakness(); } @@ -283,7 +273,7 @@ CL_LAMBDA(function-desig hash-table); CL_DECLARE(); CL_DOCSTRING(R"dx(see CLHS)dx"); DOCGROUP(clasp); -CL_DEFUN T_sp cl__maphash(T_sp function_desig, HashTableBase_sp hash_table) { +CL_DEFUN T_sp cl__maphash(T_sp function_desig, HashTable_sp hash_table) { if (hash_table.nilp()) { SIMPLE_ERROR("maphash called with nil hash-table"); } @@ -295,7 +285,7 @@ CL_LAMBDA(hash-table); CL_DECLARE(); CL_DOCSTRING(R"dx(See CLHS)dx"); DOCGROUP(clasp); -CL_DEFUN T_sp cl__clrhash(HashTableBase_sp hash_table) { +CL_DEFUN T_sp cl__clrhash(HashTable_sp hash_table) { hash_table->clrhash(); return hash_table; }; @@ -330,7 +320,7 @@ CL_LAMBDA(key hashtable); CL_DECLARE(); CL_DOCSTRING(R"dx(remhash)dx"); DOCGROUP(clasp); -CL_DEFUN bool cl__remhash(T_sp key, HashTableBase_sp ht) { return ht->remhash(key); }; +CL_DEFUN bool cl__remhash(T_sp key, HashTable_sp ht) { return ht->remhash(key); }; T_sp HashTable_O::clrhash() { HT_WRITE_LOCK(this); @@ -415,7 +405,7 @@ CL_LAMBDA(arg); CL_DECLARE(); CL_DOCSTRING(R"dx(hash-table-count)dx"); DOCGROUP(clasp); -CL_DEFUN uint cl__hash_table_count(HashTableBase_sp ht) { return ht->hashTableCount(); } +CL_DEFUN uint cl__hash_table_count(HashTable_sp ht) { return ht->hashTableCount(); } size_t HashTable_O::hashTableCount() const { HT_READ_LOCK(this); @@ -431,7 +421,7 @@ CL_LAMBDA(arg); CL_DECLARE(); CL_DOCSTRING(R"dx(hash-table-size)dx"); DOCGROUP(clasp); -CL_DEFUN uint cl__hash_table_size(HashTableBase_sp ht) { return ht->hashTableSize(); } +CL_DEFUN uint cl__hash_table_size(HashTable_sp ht) { return ht->hashTableSize(); } T_sp HashTable_O::operator[](const std::string& key) { T_sp tkey = _lisp->internKeyword(key); @@ -461,7 +451,7 @@ gc::Fixnum HashTable_O::sxhashKey(T_sp obj) const { CL_LAMBDA(key hash-table &optional default-value); CL_DOCSTRING(R"dx(gethash)dx"); DOCGROUP(clasp); -CL_DEFUN T_mv cl__gethash(T_sp key, HashTableBase_sp hashTable, T_sp default_value) { +CL_DEFUN T_mv cl__gethash(T_sp key, HashTable_sp hashTable, T_sp default_value) { return hashTable->gethash(key, default_value); }; @@ -593,7 +583,7 @@ T_sp HashTable_O::hash_table_setf_gethash(T_sp key, T_sp value) { CL_LISPIFY_NAME("gethash") CL_LAMBDA(new-value key hash-table &optional default); DOCGROUP(clasp); -CL_DEFUN_SETF T_sp setf_gethash(T_sp value, T_sp key, HashTableBase_sp hash_table, T_sp default_value) { +CL_DEFUN_SETF T_sp setf_gethash(T_sp value, T_sp key, HashTable_sp hash_table, T_sp default_value) { (void)default_value; return hash_table->hash_table_setf_gethash(key, value); } @@ -697,19 +687,19 @@ CL_LAMBDA(arg); CL_DECLARE(); CL_DOCSTRING(R"dx(hash-table-rehash-size)dx"); DOCGROUP(clasp); -CL_DEFUN Number_sp cl__hash_table_rehash_size(HashTableBase_sp ht) { return ht->rehash_size(); }; +CL_DEFUN Number_sp cl__hash_table_rehash_size(HashTable_sp ht) { return ht->rehash_size(); }; CL_LAMBDA(arg); CL_DECLARE(); CL_DOCSTRING(R"dx(hash-table-rehash-threshold)dx"); DOCGROUP(clasp); -CL_DEFUN double cl__hash_table_rehash_threshold(HashTableBase_sp ht) { return ht->rehash_threshold(); }; +CL_DEFUN double cl__hash_table_rehash_threshold(HashTable_sp ht) { return ht->rehash_threshold(); }; CL_LAMBDA(arg); CL_DECLARE(); CL_DOCSTRING(R"dx(hash-table-test)dx"); DOCGROUP(clasp); -CL_DEFUN T_sp cl__hash_table_test(HashTableBase_sp ht) { return ht->hash_table_test(); }; +CL_DEFUN T_sp cl__hash_table_test(HashTable_sp ht) { return ht->hash_table_test(); }; T_mv clasp_gethash_safe(T_sp key, T_sp thashTable, T_sp default_) { HashTable_sp hashTable = gc::As(thashTable); diff --git a/src/core/loadltv.cc b/src/core/loadltv.cc index 63d98e588a..e10c44855e 100644 --- a/src/core/loadltv.cc +++ b/src/core/loadltv.cc @@ -558,7 +558,7 @@ struct loadltv { } void op_shash() { - HashTableBase_sp ht = gc::As(get_ltv(read_index())); + HashTable_sp ht = gc::As(get_ltv(read_index())); T_sp key = get_ltv(read_index()); T_sp val = get_ltv(read_index()); ht->hash_table_setf_gethash(key, val); diff --git a/src/core/predicates.cc b/src/core/predicates.cc index 240c26dfa7..efe2c5dc74 100644 --- a/src/core/predicates.cc +++ b/src/core/predicates.cc @@ -196,10 +196,7 @@ CL_DECLARE(); CL_DOCSTRING(R"dx(hashTableP)dx"); DOCGROUP(clasp); CL_DEFUN bool cl__hash_table_p(T_sp obj) { - if (gc::IsA(obj)) { - return true; - } - return false; + return obj.isA(); }; CL_LAMBDA(arg); diff --git a/src/core/weakHashTable.cc b/src/core/weakHashTable.cc deleted file mode 100644 index 2a42cb0dca..0000000000 --- a/src/core/weakHashTable.cc +++ /dev/null @@ -1,187 +0,0 @@ -/* - File: weakHashTable.cc -*/ - -/* -Copyright (c) 2014, Christian E. Schafmeister - -CLASP is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -See directory 'clasp/licenses' for full details. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -/* -^- */ -#include -#include -#include -#include -#include - -#define WEAK_LOG(x) printf("%s:%d %s\n", __FILE__, __LINE__, (x).str().c_str()) - -namespace core { - -WeakKeyHashTable_O::WeakKeyHashTable_O() : _HashTable(16, core::make_single_float(2.0), 0.5){}; - -void WeakKeyHashTable_O::initialize() { this->_HashTable.initialize(); } -}; // namespace core - -namespace core { - -Number_sp WeakKeyHashTable_O::rehash_size() const { return this->_HashTable._RehashSize; } - -double WeakKeyHashTable_O::rehash_threshold() const { return this->_HashTable._RehashThreshold; } - -T_sp WeakKeyHashTable_O::hash_table_test() const { return cl::_sym_eq; } - -void WeakKeyHashTable_O::describe(T_sp stream) { - KeyBucketsType& keys = *this->_HashTable._Keys; - ValueBucketsType& values = *this->_HashTable._Values; - stringstream ss; - ss << fmt::format("WeakKeyHashTable size: {}u\n", this->_HashTable.length()); - ss << fmt::format(" keys memory range: {} - {} \n", (void*)&keys[0].rawRef_(), - (void*)&keys[this->_HashTable.length()].rawRef_()); - ss << fmt::format(" _HashTable.length = {}\n", keys.length()); - ss << fmt::format(" _HashTable.used = {}\n", keys.used()); - ss << fmt::format(" _HashTable.deleted = {}\n", keys.deleted()); - for (int i(0), iEnd(this->_HashTable.length()); i < iEnd; ++i) { - value_type& key = keys[i]; - stringstream sentry; - sentry.width(3); - sentry << i << " key.px@" << (void*)(&key.rawRef_()) << " "; - if (!key) { - sentry << "splatted"; - } else if (key.unboundp()) { - sentry << "unbound"; - } else if (key.deletedp()) { - sentry << "deleted"; - } else { - // key.base_ref().nilp() ) { - T_sp okey = key; - sentry << _rep_(okey); - sentry << "@" << (void*)(key.raw_()); - sentry << " --> "; - value_type val = values[i]; - if (val.same_as_keyP()) { - sentry << "same_as_key!!!"; - } else { - sentry << _rep_(val); - } - } - ss << " " << sentry.str(); - clasp_write_string(ss.str(), stream); - } -} - -SYMBOL_EXPORT_SC_(KeywordPkg, splatted); -SYMBOL_EXPORT_SC_(KeywordPkg, unbound); -SYMBOL_EXPORT_SC_(KeywordPkg, deleted); - -/* %%MPS: If we fail to find 'key' in the table, and if mps_ld_isstale - * returns true, then some of the keys in the table might have been - * moved by the garbage collector: in this case we need to re-hash the - * table. See topic/location. - * Return (values value t) or (values nil nil) - */ -T_mv WeakKeyHashTable_O::gethash(T_sp key, T_sp defaultValue) { return this->_HashTable.gethash(key, defaultValue); } - -void WeakKeyHashTable_O::maphashLowLevel(std::function const& fn) { this->_HashTable.maphash(fn); } - -void WeakKeyHashTable_O::maphash(T_sp func) const { this->_HashTable.maphashFn(func); } - -bool WeakKeyHashTable_O::remhash(T_sp tkey) { return this->_HashTable.remhash(tkey); } - -T_sp WeakKeyHashTable_O::clrhash() { - this->_HashTable.clrhash(); - return this->asSmartPtr(); -} - -string WeakKeyHashTable_O::__repr__() const { - stringstream ss; - ss << "#<" << this->className() << " :size " << this->_HashTable.tableSize() << ">"; - return ss.str(); -} - -CL_LAMBDA(&optional (size 16)); -CL_DECLARE(); -CL_DOCSTRING(R"dx(makeWeakKeyHashTable)dx"); -DOCGROUP(clasp); -CL_DEFUN WeakKeyHashTable_sp core__make_weak_key_hash_table(Fixnum_sp size) { - int sz = unbox_fixnum(size); - WeakKeyHashTable_sp ht = gctools::GC::allocate(sz, DoubleFloat_O::create(2.0), 0.5); - return ht; -} - -CL_LAMBDA(key hash-table &optional default-value); -CL_DECLARE(); -CL_DOCSTRING(R"dx(weakGethash)dx"); -DOCGROUP(clasp); -CL_DEFUN T_mv core__weak_gethash(T_sp tkey, WeakKeyHashTable_sp ht, T_sp defaultValue) { return ht->gethash(tkey, defaultValue); }; - -T_sp WeakKeyHashTable_O::hash_table_setf_gethash(T_sp key, T_sp value) { - this->_HashTable.set(key, value); - return value; -} - -CL_LAMBDA(ht key value); -CL_DECLARE(); -CL_DOCSTRING(R"dx(weakSetfGethash)dx"); -DOCGROUP(clasp); -CL_DEFUN void core__weak_setf_gethash(T_sp key, WeakKeyHashTable_sp ht, T_sp val) { ht->hash_table_setf_gethash(key, val); }; - -CL_LAMBDA(ht key); -CL_DECLARE(); -CL_DOCSTRING(R"dx(weakRemhash)dx"); -DOCGROUP(clasp); -CL_DEFUN void core__weak_remhash(WeakKeyHashTable_sp ht, T_sp key) { ht->remhash(key); }; - -CL_LAMBDA(ht); -CL_DECLARE(); -CL_DOCSTRING(R"dx(weakClrhash)dx"); -DOCGROUP(clasp); -CL_DEFUN void core__weak_clrhash(WeakKeyHashTable_sp ht) { ht->clrhash(); }; - -CL_LAMBDA(ht idx); -CL_DECLARE(); -CL_DOCSTRING(R"dx(weakSplat)dx"); -DOCGROUP(clasp); -CL_DEFUN void core__weak_splat(WeakKeyHashTable_sp ht, Fixnum_sp idx) { - T_sp splatted; // This will be NULL - splatted.reset_(); // This will force it to be NULL - TESTING(); // Test the NULL value - (*ht->_HashTable._Keys).set(unbox_fixnum(idx), WeakKeyHashTable_O::value_type(splatted)); -}; -CL_LAMBDA(ht &optional sz); -CL_DECLARE(); -CL_DOCSTRING(R"dx(weakRehash)dx"); -DOCGROUP(clasp); -CL_DEFUN void core__weak_rehash(WeakKeyHashTable_sp ht, T_sp sz) { - size_t newLength; - if (sz.nilp()) { - newLength = ht->_HashTable._Keys->length() * 2; - } else { - newLength = unbox_fixnum(gc::As(sz)); - // newLength = unbox_fixnum(As(sz)); - } - WeakKeyHashTable_O::value_type dummyKey; - size_t dummyPos; - ht->_HashTable.rehash(dummyKey, dummyPos); -}; -}; // namespace core - -SYMBOL_EXPORT_SC_(KeywordPkg, splatted); -SYMBOL_EXPORT_SC_(KeywordPkg, unbound); -SYMBOL_EXPORT_SC_(KeywordPkg, deleted); diff --git a/src/gctools/gc_interface.cc b/src/gctools/gc_interface.cc index f74c9a515a..0884258de3 100644 --- a/src/gctools/gc_interface.cc +++ b/src/gctools/gc_interface.cc @@ -612,8 +612,6 @@ void dumpBoehmLayoutTables(std::ostream& fout) { Init_class_kind(llvmo::Linker_O); Init_class_kind(core::SmallMultimap_O); Init_class_kind(core::RandomState_O); - Init_class_kind(core::HashTableBase_O); - Init_class_kind(core::WeakKeyHashTable_O); Init_class_kind(core::HashTable_O); Init_class_kind(core::HashTableEqualp_O); Init_class_kind(core::HashTableEq_O); diff --git a/src/gctools/gcweak.cc b/src/gctools/gcweak.cc index 835402df76..600090c6f7 100644 --- a/src/gctools/gcweak.cc +++ b/src/gctools/gcweak.cc @@ -1,11 +1,3 @@ -/* NOTES: - -(1) _deleted is not being used or updated properly. -(2) There is something wrong with WeakKeyHashTable - weak pointers end up pointing to memory that is not the start of an object -(3) The other weak objects (weak pointer, weak mapping) are doing allocations in their constructors. - -*/ - /* File: gcweak.cc */ @@ -41,326 +33,6 @@ THE SOFTWARE. namespace gctools { -#ifdef CLASP_THREADS -struct WeakKeyHashTableReadLock { - const WeakKeyHashTable* _hashTable; - WeakKeyHashTableReadLock(const WeakKeyHashTable* ht) : _hashTable(ht) { - if (this->_hashTable->_Mutex) { - this->_hashTable->_Mutex->lock_shared(); - } - } - ~WeakKeyHashTableReadLock() { - if (this->_hashTable->_Mutex) { - this->_hashTable->_Mutex->unlock_shared(); - } - } -}; -struct WeakKeyHashTableWriteLock { - const WeakKeyHashTable* _hashTable; - WeakKeyHashTableWriteLock(const WeakKeyHashTable* ht, bool upgrade = false) : _hashTable(ht) { - if (this->_hashTable->_Mutex) { - this->_hashTable->_Mutex->lock(upgrade); - } - } - ~WeakKeyHashTableWriteLock() { - if (this->_hashTable->_Mutex) { - this->_hashTable->_Mutex->unlock(); - } - } -}; -#endif - -#ifdef CLASP_THREADS -#define HT_READ_LOCK(me) WeakKeyHashTableReadLock _zzz(me) -#define HT_WRITE_LOCK(me) WeakKeyHashTableWriteLock _zzz(me) -#define HT_UPGRADE_WRITE_LOCK(me) WeakKeyHashTableWriteLock _zzz(me, true) -#else -#define HT_READ_LOCK(me) -#define HT_WRITE_LOCK(me) -#define HT_UPGRADE_WRITE_LOCK(me) -#endif - -void WeakKeyHashTable::initialize() { - int length = this->_Length; - /* round up to next power of 2 */ - if (length == 0) - length = 2; - size_t l; - for (l = 1; l < length; l *= 2) - ; - this->_Keys = KeyBucketsAllocatorType::allocate(Header_s::BadgeStampWtagMtag(Header_s::WeakBucketKind), l); - this->_Values = ValueBucketsAllocatorType::allocate(Header_s::BadgeStampWtagMtag(Header_s::StrongBucketKind), l); - this->_Keys->dependent = this->_Values; - // GCTOOLS_ASSERT((reinterpret_cast(this->_Keys->dependent) & 0x3) == 0); - this->_Values->dependent = this->_Keys; -} - -void WeakKeyHashTable::setupThreadSafeHashTable() { -#ifdef CLASP_THREADS - core::SimpleBaseString_sp sbsread = core::SimpleBaseString_O::make("WEAKHSHR"); - core::SimpleBaseString_sp sbswrite = core::SimpleBaseString_O::make("WEAKHSHW"); - this->_Mutex = mp::SharedMutex_O::make_shared_mutex(sbsread, sbswrite); -#endif -} - -uint WeakKeyHashTable::sxhashKey(const value_type& key) { - return core::lisp_hash(static_cast(gctools::lisp_badge(key))); -} - -/*! Return 0 if there is no more room in the sequence of entries for the key - Return 1 if the element is found or an unbound or deleted entry is found. - Return the entry index in (b) - */ -size_t WeakKeyHashTable::find_no_lock(gctools::tagged_pointer keys, const value_type& key, size_t& b) { - unsigned long i, h, probe; - unsigned long l = keys->length() - 1; - int result = 0; - h = WeakKeyHashTable::sxhashKey(key); - - probe = (h >> 8) | 1; - h &= l; - i = h; - do { - value_type& k = (*keys)[i]; - if (k.unboundp() || k == key) { - b = i; - return 1; - } -#if defined(USE_BOEHM) - // Handle splatting - if (!k.raw_()) { - auto deleted = value_type(gctools::make_tagged_deleted()); - keys->set(i, deleted); - ValueBucketsType* values = dynamic_cast(&*keys->dependent); - (*values)[i] = value_type(gctools::make_tagged_unbound()); - } -#else - MISSING_GC_SUPPORT(); -#endif - if (result == 0 && (k.deletedp())) { - b = i; - result = 1; - } - i = (i + probe) & l; - } while (i != h); - return result; -} -int WeakKeyHashTable::rehash_not_safe(const value_type& key, size_t& key_bucket) { - HT_WRITE_LOCK(this); - size_t newLength; - if (this->_RehashSize.fixnump()) { - newLength = this->_Keys->length() + this->_RehashSize.unsafe_fixnum(); - } else if (gc::IsA(this->_RehashSize)) { - double size = core::clasp_to_double(this->_RehashSize); - newLength = this->_Keys->length() * size; - } else { - SIMPLE_ERROR("Illegal rehash size {}", _rep_(this->_RehashSize)); - } - int result; - size_t i, length; - // buckets_t new_keys, new_values; - result = 0; - length = this->_Keys->length(); - MyType newHashTable(newLength, this->_RehashSize, this->_RehashThreshold); - newHashTable.initialize(); - for (i = 0; i < length; ++i) { - value_type& old_key = (*this->_Keys)[i]; - if (!old_key.unboundp() && !old_key.deletedp() && old_key.raw_()) { - size_t found; - size_t b; - found = WeakKeyHashTable::find_no_lock(newHashTable._Keys, old_key, b); - GCTOOLS_ASSERT(found); /* new table shouldn't be full */ - GCTOOLS_ASSERT((*newHashTable._Keys)[b].unboundp()); /* shouldn't be in new table */ - newHashTable._Keys->set(b, old_key); - (*newHashTable._Values)[b] = (*this->_Values)[i]; - if (key && old_key == key) { - key_bucket = b; - result = 1; - } - (*newHashTable._Keys).setUsed((*newHashTable._Keys).used() + 1); // TAG_COUNT(UNTAG_COUNT(new_keys->used) + 1); - } - } - GCTOOLS_ASSERT((*newHashTable._Keys).used() == (newHashTable.tableSize())); - // assert(UNTAG_COUNT(new_keys->used) == table_size(tbl)); - this->swap(newHashTable); - return result; -} - -int WeakKeyHashTable::rehash(const value_type& key, size_t& key_bucket) { - int result; - safeRun([&result, this, &key, &key_bucket]() { result = this->rehash_not_safe(key, key_bucket); }); - return result; -} - -/*! trySet returns 0 only if there is no room in the hash-table */ -int WeakKeyHashTable::trySet(core::T_sp tkey, core::T_sp value) { - HT_WRITE_LOCK(this); - size_t b; - if (tkey == value) { - value = gctools::make_tagged_same_as_key(); - } - value_type key(tkey); - size_t result = WeakKeyHashTable::find_no_lock(this->_Keys, key, b); - if ((*this->_Keys)[b].unboundp()) { - this->_Keys->set(b, key); - (*this->_Keys).setUsed((*this->_Keys).used() + 1); - } else if ((*this->_Keys)[b].deletedp()) { - this->_Keys->set(b, key); - GCTOOLS_ASSERT((*this->_Keys).deleted() > 0); - (*this->_Keys).setDeleted((*this->_Keys).deleted() - 1); - } - (*this->_Values).set(b, value_type(value)); - return 1; -} - -string WeakKeyHashTable::dump(const string& prefix) { - stringstream sout; - safeRun([this, &prefix, &sout]() { - HT_READ_LOCK(this); - size_t i, length; - length = this->_Keys->length(); - sout << "===== Dumping WeakKeyHashTable length = " << length << std::endl; - for (i = 0; i < length; ++i) { - value_type& old_key = (*this->_Keys)[i]; - sout << prefix << " [" << i << "] key= " << old_key.raw_() << " value = " << (*this->_Values)[i].raw_() << std::endl; - } - }); - return sout.str(); -}; - -// ---------------------------------------------------------------------- -// ---------------------------------------------------------------------- -// ---------------------------------------------------------------------- -// -// Use safeRun from here on down -// -// ---------------------------------------------------------------------- -// ---------------------------------------------------------------------- -// ---------------------------------------------------------------------- - -core::T_mv WeakKeyHashTable::gethash(core::T_sp tkey, core::T_sp defaultValue) { - core::T_mv result_mv; - safeRun([&result_mv, this, tkey, defaultValue]() { - HT_READ_LOCK(this); - value_type key(tkey); - size_t pos; - size_t result = gctools::WeakKeyHashTable::find_no_lock(this->_Keys, key, pos); - if (result) { - value_type& k = (*this->_Keys)[pos]; - if (k.raw_() && !k.unboundp() && !k.deletedp()) { - core::T_sp value = smart_ptr((*this->_Values)[pos]); - if (value.same_as_keyP()) { - value = smart_ptr(k); - } - result_mv = Values(value, core::lisp_true()); - return; - } - } - result_mv = Values(defaultValue, nil()); - return; - }); - return result_mv; -} - -void WeakKeyHashTable::set(core::T_sp key, core::T_sp value) { - safeRun([key, value, this]() { - if (this->fullp_not_safe() || !this->trySet(key, value)) { - int res; - value_type dummyKey; - size_t dummyPos; - this->rehash(dummyKey, dummyPos); - res = this->trySet(key, value); - GCTOOLS_ASSERT(res); - } - }); -} - -#define HASH_TABLE_ITER(table_type, tablep, key, value) \ - gctools::tagged_pointer iter_Keys; \ - gctools::tagged_pointer iter_Values; \ - core::T_sp key; \ - core::T_sp value; \ - { \ - HT_READ_LOCK(tablep); \ - iter_Keys = tablep->_Keys; \ - iter_Values = tablep->_Values; \ - } \ - for (size_t it(0), itEnd(iter_Keys->length()); it < itEnd; ++it) { \ - { \ - HT_READ_LOCK(tablep); \ - key = (*iter_Keys)[it]; \ - value = (*iter_Values)[it]; \ - } \ - if (key.raw_() && !key.unboundp() && !key.deletedp()) - -#define HASH_TABLE_ITER_END } - -void WeakKeyHashTable::maphash(std::function const& fn) const { - safeRun([fn, this]() { - HASH_TABLE_ITER(WeakKeyHashTable, this, key, value) { fn(key, value); } - HASH_TABLE_ITER_END; - }); -} - -void WeakKeyHashTable::maphashFn(core::T_sp fn) const { - safeRun([fn, this]() { - HASH_TABLE_ITER(WeakKeyHashTable, this, key, value) { core::eval::funcall(fn, key, value); } - HASH_TABLE_ITER_END; - }); -} - -bool WeakKeyHashTable::remhash(core::T_sp tkey) { - bool bresult = false; - safeRun([this, tkey, &bresult]() { - HT_WRITE_LOCK(this); - size_t b; - value_type key(tkey); - size_t result = gctools::WeakKeyHashTable::find_no_lock(this->_Keys, key, b); - if (!result || !((*this->_Keys)[b]).raw_() || (*this->_Keys)[b].unboundp() || (*this->_Keys)[b].deletedp()) { - if (!this->rehash(key, b)) { - bresult = false; - return; - } - } - if ((*this->_Keys)[b].raw_() && !(*this->_Keys)[b].unboundp() && !(*this->_Keys)[b].deletedp()) { - auto deleted = value_type(gctools::make_tagged_deleted()); - this->_Keys->set(b, deleted); - (*this->_Keys).setDeleted((*this->_Keys).deleted() + 1); - (*this->_Values)[b] = value_type(gctools::make_tagged_unbound()); - bresult = true; - return; - } - bresult = false; - }); - return bresult; -} - -void WeakKeyHashTable::clrhash() { - safeRun([this]() { - HT_WRITE_LOCK(this); - size_t len = (*this->_Keys).length(); - for (size_t i(0); i < len; ++i) { - this->_Keys->set(i, value_type(gctools::make_tagged_deleted())); - (*this->_Values)[i] = value_type(gctools::make_tagged_unbound()); - } - (*this->_Keys).setUsed(0); - (*this->_Keys).setDeleted(0); - }); -}; - -core::Vector_sp WeakKeyHashTable::pairs() const { - size_t len = (*_Keys).length(); - core::ComplexVector_T_sp keyvalues = core::ComplexVector_T_O::make(len * 2, nil(), core::make_fixnum(0)); - HT_READ_LOCK(this); - for (size_t i(0); i < len; ++i) { - if ((*_Keys)[i].raw_() && !(*_Keys)[i].unboundp() && !(*_Keys)[i].deletedp()) { - keyvalues->vectorPushExtend((*_Keys)[i], 16); - keyvalues->vectorPushExtend((*_Values)[i], 16); - } - } - return keyvalues; -}; - #ifdef USE_BOEHM WeakPointer::WeakPointer(core::T_sp o) : _value(o.tagged_()) { if (o.objectp()) { // pointer, so we're actually weak diff --git a/src/gctools/memoryManagement.cc b/src/gctools/memoryManagement.cc index 1fb5334683..d15ac2ffe7 100644 --- a/src/gctools/memoryManagement.cc +++ b/src/gctools/memoryManagement.cc @@ -671,11 +671,7 @@ bool BaseHeader_s::preciseIsPolymorphic() const { } else if (this->_badge_stamp_wtag_mtag.consObjectP()) { return false; } else if (this->_badge_stamp_wtag_mtag.weakObjectP()) { - if (this->_badge_stamp_wtag_mtag._value == WeakBucketKind) { - return std::is_polymorphic(); - } else if (this->_badge_stamp_wtag_mtag._value == StrongBucketKind) { - return std::is_polymorphic(); - } + return false; } return false; } diff --git a/src/gctools/snapshotSaveLoad.cc b/src/gctools/snapshotSaveLoad.cc index 98290a5092..f9710c372d 100644 --- a/src/gctools/snapshotSaveLoad.cc +++ b/src/gctools/snapshotSaveLoad.cc @@ -3396,32 +3396,8 @@ void snapshot_load(void* maybeStartOfSnapshot, void* maybeEndOfSnapshot, const s gctools::clasp_ptr_t clientStart = (gctools::clasp_ptr_t)(weakHeader + 1); gctools::clasp_ptr_t clientEnd = clientStart + weakHeader->_Size; snapshot_save_load_init_s init(header, clientStart, clientEnd); - gctools::Header_s::WeakKinds kind = (gctools::Header_s::WeakKinds)header->_badge_stamp_wtag_mtag._value; - switch (kind) { - case gctools::Header_s::WeakBucketKind: { - auto obj = gctools::GCBucketAllocator< - gctools::Buckets>::snapshot_save_load_allocate(&init); - gctools::Tagged fwd = (gctools::Tagged)gctools::untag_object((gctools::clasp_ptr_t)obj.raw_()); - set_forwarding_pointer(header, ((char*)fwd), &islInfo); - DBG_SL_ALLOCATE(BF("allocated weak %p header: %p stamp: %lu fwd: %p\n") % (void*)obj.raw_() % (void*)header % - (uintptr_t)kind % (void*)fwd); - root_holder.add((void*)obj.raw_()); - break; - } - case gctools::Header_s::StrongBucketKind: { - auto obj = gctools::GCBucketAllocator< - gctools::Buckets>::snapshot_save_load_allocate(&init); - gctools::Tagged fwd = (gctools::Tagged)gctools::untag_object((gctools::clasp_ptr_t)obj.raw_()); - set_forwarding_pointer(header, ((char*)fwd), &islInfo); - DBG_SL_ALLOCATE(BF("allocated weak %p header: %p stamp: %lu fwd: %p\n") % (void*)obj.raw_() % (void*)header % - (uintptr_t)kind % (void*)fwd); - root_holder.add((void*)obj.raw_()); - break; - } - default: - printf("%s:%d:%s Handle allocate weak objects\n", __FILE__, __LINE__, __FUNCTION__); - break; - } + printf("%s:%d:%s Handle allocate weak objects\n", __FILE__, __LINE__, __FUNCTION__); + break; } else { printf("%s:%d:%s Unknown header at offset 0x%lx qword: 0x%lx\n", __FILE__, __LINE__, __FUNCTION__, (uintptr_t)cur_header - (uintptr_t)fileHeader, *(uintptr_t*)cur_header); diff --git a/src/gctools/weak_scan.cc b/src/gctools/weak_scan.cc index 58890c2110..55c068f577 100644 --- a/src/gctools/weak_scan.cc +++ b/src/gctools/weak_scan.cc @@ -21,46 +21,7 @@ #ifdef WEAK_SCAN ADDR_T WEAK_SCAN(ADDR_T client EXTRA_ARGUMENTS) { const gctools::Header_s& header = *reinterpret_cast(WEAK_PTR_TO_HEADER_PTR(client)); - gctools::WeakObject* weakObj = reinterpret_cast(client); switch (header._badge_stamp_wtag_mtag._value) { - case gctools::Header_s::WeakBucketKind: { - gctools::WeakBucketsObjectType* obj = reinterpret_cast(weakObj); - // Fix the obj->dependent pointer - POINTER_FIX((core::T_O**)&obj->dependent.rawRef_()); - for (int i(0), iEnd(obj->length()); i < iEnd; ++i) { - POINTER_FIX((core::T_O**)&obj->bucket[i].rawRef_()); - } - client = (ADDR_T)((char*)client + sizeof(gctools::WeakBucketsObjectType) + - sizeof(typename gctools::WeakBucketsObjectType::value_type) * obj->length() + sizeof(gctools::Header_s)); - } break; - case gctools::Header_s::StrongBucketKind: { - gctools::StrongBucketsObjectType* obj = reinterpret_cast(client); - // fix the obj->dependent pointer - POINTER_FIX((core::T_O**)&obj->dependent.rawRef_()); - for (int i(0), iEnd(obj->length()); i < iEnd; ++i) { - core::T_O** objptr = (core::T_O**)&obj->bucket[i].rawRef_(); - // printf("%s:%d [%d of %d] objptr@ %p -> %p\n", __FILE__, __LINE__, i, obj->length(), objptr, (void*)(*objptr) - // ); - POINTER_FIX(objptr); - } - client = - (ADDR_T)((char*)client + sizeof(gctools::StrongBucketsObjectType) + - sizeof(typename gctools::StrongBucketsObjectType::value_type) * obj->length() + sizeof(gctools::Header_s)); - } break; - case gctools::Header_s::WeakMappingKind: { - gctools::WeakMappingObjectType* obj = reinterpret_cast(weakObj); - // fix the obj->dependent pointer - POINTER_FIX((core::T_O**)&obj->dependent.rawRef_()); - POINTER_FIX((core::T_O**)&obj->bucket.rawRef_()); - client = (ADDR_T)((char*)client + sizeof(gctools::WeakMappingObjectType) + sizeof(gctools::Header_s)); - } break; - case gctools::Header_s::StrongMappingKind: { - gctools::StrongMappingObjectType* obj = reinterpret_cast(client); - // fix the obj->dependent pointer - POINTER_FIX((core::T_O**)&obj->dependent.rawRef_()); - POINTER_FIX((core::T_O**)&obj->bucket.rawRef_()); - client = (ADDR_T)((char*)client + sizeof(gctools::StrongMappingObjectType) + sizeof(gctools::Header_s)); - } break; default: THROW_HARD_ERROR("handle other weak kind {}", header._badge_stamp_wtag_mtag._value); } @@ -72,25 +33,6 @@ ADDR_T WEAK_SCAN(ADDR_T client EXTRA_ARGUMENTS) { ADDR_T WEAK_SKIP(ADDR_T client, bool dbg, size_t& objectSize) { const gctools::Header_s& header = *reinterpret_cast(WEAK_PTR_TO_HEADER_PTR(client)); if (header._badge_stamp_wtag_mtag.weakObjectP()) { - switch (header._badge_stamp_wtag_mtag._value) { - case gctools::Header_s::WeakBucketKind: { - gctools::WeakBucketsObjectType* obj = reinterpret_cast(client); - objectSize = gctools::AlignUp(sizeof(gctools::WeakBucketsObjectType) + - sizeof(typename gctools::WeakBucketsObjectType::value_type) * obj->length()); - } break; - case gctools::Header_s::StrongBucketKind: { - gctools::StrongBucketsObjectType* obj = reinterpret_cast(client); - objectSize = gctools::AlignUp(sizeof(gctools::StrongBucketsObjectType) + - sizeof(typename gctools::StrongBucketsObjectType::value_type) * obj->length()); - } break; - case gctools::Header_s::WeakMappingKind: { - objectSize = gctools::AlignUp(sizeof(gctools::WeakMappingObjectType)); - } break; - case gctools::Header_s::StrongMappingKind: { - objectSize = gctools::AlignUp(sizeof(gctools::StrongMappingObjectType)); - } break; - } - } else { THROW_HARD_ERROR("Handle weak_obj_skip other weak kind {}", header._badge_stamp_wtag_mtag._value); } client = (ADDR_T)((char*)client + objectSize + sizeof(gctools::Header_s)); @@ -105,11 +47,7 @@ void WEAK_FWD(ADDR_T old_client, ADDR_T new_client) { ADDR_T limit = WEAK_SKIP_IN_WEAK_FWD(old_client, false, objectSize); size_t size = (char*)limit - (char*)old_client; assert(size >= Align(sizeof(weak_fwd2_s))); - if (size == gctools::Align(sizeof(gctools::weak_fwd2_s))) { - header._badge_stamp_wtag_mtag.setFwdPointer((void*)new_client); - } else { - header._badge_stamp_wtag_mtag.setFwdPointer((void*)new_client); - header._badge_stamp_wtag_mtag.setFwdSize(size); - } + header._badge_stamp_wtag_mtag.setFwdPointer((void*)new_client); + header._badge_stamp_wtag_mtag.setFwdSize(size); } #endif diff --git a/src/lisp/kernel/cleavir/bir-to-bmir.lisp b/src/lisp/kernel/cleavir/bir-to-bmir.lisp index dc87092570..7ea6de20ce 100644 --- a/src/lisp/kernel/cleavir/bir-to-bmir.lisp +++ b/src/lisp/kernel/cleavir/bir-to-bmir.lisp @@ -170,7 +170,7 @@ (deftransform core:data-vector-p (core::headerq core:abstract-simple-vector) t) -(deftransform hash-table-p (core::headerq core:hash-table-base) t) +(deftransform hash-table-p (core::headerq hash-table) t) (deftransform pathnamep (core::headerq pathname) t) diff --git a/src/lisp/kernel/cleavir/transform.lisp b/src/lisp/kernel/cleavir/transform.lisp index 284d699f7d..0248865a08 100644 --- a/src/lisp/kernel/cleavir/transform.lisp +++ b/src/lisp/kernel/cleavir/transform.lisp @@ -677,7 +677,7 @@ Optimizations are available for any of: ;;; ;;; (18) HASH TABLES -(deftransform-type-predicate hash-table-p core:hash-table-base) +(deftransform-type-predicate hash-table-p hash-table) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; diff --git a/src/lisp/kernel/cleavir/type.lisp b/src/lisp/kernel/cleavir/type.lisp index ac17658e60..c4a93de24c 100644 --- a/src/lisp/kernel/cleavir/type.lisp +++ b/src/lisp/kernel/cleavir/type.lisp @@ -1539,7 +1539,7 @@ ;;; (18) HASH TABLES (define-deriver hash-table-p (object) - (derive-type-predicate object 'core:hash-table-base *clasp-system*)) + (derive-type-predicate object 'hash-table *clasp-system*)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; From 2b34cb386d79e8eb1e9cec422ea18ad3a468fb33 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 14 Jan 2025 15:00:39 -0500 Subject: [PATCH 28/39] remove weak_mtag I don't think it really does us any good. Each kind of weak object pretty much needs to be scanned (or not) in its own special way so grouping them doesn't accomplish anything. If we ever have separate pools for them like we did with MPS, they can just have normal general headers. --- include/clasp/gctools/gc_boot.h | 1 - include/clasp/gctools/gcalloc.h | 4 - include/clasp/gctools/memoryManagement.h | 18 ++--- include/clasp/gctools/smart_pointers.h | 4 - src/gctools/gc_boot.cc | 3 - src/gctools/memoryManagement.cc | 63 +++++----------- src/gctools/obj_scan.cc | 6 +- src/gctools/snapshotSaveLoad.cc | 96 +----------------------- src/gctools/startRunStop.cc | 6 -- src/gctools/weak_scan.cc | 53 ------------- 10 files changed, 33 insertions(+), 221 deletions(-) delete mode 100644 src/gctools/weak_scan.cc diff --git a/include/clasp/gctools/gc_boot.h b/include/clasp/gctools/gc_boot.h index 1b69884216..5ed84411bf 100644 --- a/include/clasp/gctools/gc_boot.h +++ b/include/clasp/gctools/gc_boot.h @@ -83,7 +83,6 @@ extern uintptr_t global_class_kind; extern uintptr_t global_container_kind; extern uintptr_t global_code_kind; extern uintptr_t global_atomic_kind; -extern uintptr_t global_strong_weak_kind; extern int global_container_proc_index; diff --git a/include/clasp/gctools/gcalloc.h b/include/clasp/gctools/gcalloc.h index a4d2f19613..e07d0f5af9 100644 --- a/include/clasp/gctools/gcalloc.h +++ b/include/clasp/gctools/gcalloc.h @@ -42,10 +42,6 @@ THE SOFTWARE. #define STACK_ALIGNMENT alignof(char*) #define STACK_ALIGN_UP(size) (((size) + STACK_ALIGNMENT - 1) & ~(STACK_ALIGNMENT - 1)) -namespace gctools { -extern uintptr_t global_strong_weak_kind; -}; - namespace gctools { template static void initializeIfNeeded(smart_ptr sp) { diff --git a/include/clasp/gctools/memoryManagement.h b/include/clasp/gctools/memoryManagement.h index 418fac00ee..efa40f5147 100644 --- a/include/clasp/gctools/memoryManagement.h +++ b/include/clasp/gctools/memoryManagement.h @@ -265,9 +265,9 @@ template inline size_t sizeof_with_header(); #B001 == invalid0_mtag This is an illegal value for the two lsbs, it indictates that this is not a valid header. This pattern is used to indicate a CONS header - #B010 == (MPS specific) weak_mtag - A weak object + #B010 == invalid1_mtag #B011 == cons_mtag This indicates that what follows is a cons cell. - #B100 == invalid1_mtag + #B100 == invalid2_mtag #B101 == fwd_mtag - This tag indicates that the remaining data bits in the header contains a forwarding pointer. The uintptr_t in additional_data[0] contains the length of the block from the client pointer. @@ -328,16 +328,11 @@ class BaseHeader_s { static const tagged_stamp_t general_mtag_mask = 0b11; #endif static const size_t general_mtag_shift = general_mtag_width; // MUST ALWAYS BE >=2 to match Fixnum shift - /*! - * It is important that weak_mtag is the same value as CHARACTER_TAG so that - * it looks like an immediate value in AWL pools and doesn't break the - * MPS invariant that only valid tagged pointers are allowed in AWL pools. - */ static const tagged_stamp_t general_mtag = 0b000; static const tagged_stamp_t invalid0_mtag = 0b001; - static const tagged_stamp_t weak_mtag = 0b010; + static const tagged_stamp_t invalid1_mtag = 0b010; static const tagged_stamp_t cons_mtag = 0b011; - static const tagged_stamp_t invalid1_mtag = 0b100; + static const tagged_stamp_t invalid2_mtag = 0b100; static const tagged_stamp_t fwd_mtag = 0b101; static const tagged_stamp_t pad_mtag = 0b110; static const tagged_stamp_t pad1_mtag = 0b111; @@ -469,11 +464,10 @@ class BaseHeader_s { if (!(this->_value & general_mtag_mask)) return false; tagged_stamp_t val = (this->_value & general_mtag_mask); - return (val == invalid0_mtag) || (val == invalid1_mtag); + return (val == invalid0_mtag) || (val == invalid1_mtag) || (val == invalid2_mtag); }; bool stampP() const { return (this->_value & general_mtag_mask) == general_mtag; }; bool generalObjectP() const { return this->stampP(); }; - bool weakObjectP() const { return (this->_value & mtag_mask) == weak_mtag; }; bool consObjectP() const { return (this->_value & mtag_mask) == cons_mtag; }; bool fwdP() const { return (this->_value & mtag_mask) == fwd_mtag; }; bool fwdV() const { return (this->_value & mtag_mask); }; @@ -612,8 +606,6 @@ class BaseHeader_s { return ss.str(); } else if (this->_badge_stamp_wtag_mtag.consObjectP()) { return "Header_CONS"; - } else if (this->_badge_stamp_wtag_mtag.weakObjectP()) { - return "Header_WEAK"; } else if (this->_badge_stamp_wtag_mtag.fwdP()) { std::stringstream ss; ss << "Fwd/ptr=" << this->_badge_stamp_wtag_mtag.fwdPointer() << "/sz=" << this->_badge_stamp_wtag_mtag.fwdSize(); diff --git a/include/clasp/gctools/smart_pointers.h b/include/clasp/gctools/smart_pointers.h index 2398f49523..306713f4b8 100644 --- a/include/clasp/gctools/smart_pointers.h +++ b/include/clasp/gctools/smart_pointers.h @@ -238,8 +238,6 @@ template class base_ptr { and you are sure that it will not be interpreted as a Fixnum!!! List actual uses here: - gcweak.h>>Mapping(const Type& val) - gcweak.h>>Buckets::set intrinsics.cc>>cc_loadTimeValueReference */ Type*& rawRef_() { return this->theObject; }; @@ -433,8 +431,6 @@ template <> class smart_ptr { /*! This should almost NEVER be used!!!!!! List all uses of rawRef_ here: - gcweak.h>>Mapping(const Type& val) - gcweak.h>>Buckets::set intrinsics.cc>>cc_loadTimeValueReference record.h>>field specialized on gc::smart_ptr& SMART_PTR_FIX and smart_ptr fixing in general when SMART_PTR_FIX is replaced diff --git a/src/gctools/gc_boot.cc b/src/gctools/gc_boot.cc index a202659ea6..9acc3ef04c 100644 --- a/src/gctools/gc_boot.cc +++ b/src/gctools/gc_boot.cc @@ -37,7 +37,6 @@ uintptr_t global_class_kind; uintptr_t global_container_kind; uintptr_t global_code_kind; uintptr_t global_atomic_kind; -uintptr_t global_strong_weak_kind; // int global_container_proc_index; size_t global_stamp_max; Stamp_info* global_stamp_info; @@ -107,7 +106,6 @@ void dump_data_types(std::ostream& fout, const std::string& indent) { Init_global_ints("MTAG_MASK", (int)Header_s::mtag_mask); Init_global_ints("GENERAL_MTAG", (int)Header_s::general_mtag); Init_global_ints("CONS_MTAG", (int)Header_s::cons_mtag); - Init_global_ints("WEAK_MTAG", (int)Header_s::weak_mtag); Init_global_ints("REF_CLASS_CLASS_NAME", (int)core::Instance_O::REF_CLASS_CLASS_NAME); Init_global_size_t("VASLIST-ARGS-OFFSET", core::Vaslist::args_offset()); @@ -463,7 +461,6 @@ void walk_stamp_field_layout_tables(WalkKind walk, std::ostream& fout) { 1); // */ GC_new_kind(GC_new_free_list(), GC_MAKE_PROC(global_container_proc_index,0),0,1); // GC_DS_LENGTH, 1, 1); global_code_kind = GC_new_kind(GC_new_free_list(), GC_DS_LENGTH, 1, 1); global_atomic_kind = GC_I_PTRFREE; // GC_new_kind(GC_new_free_list(), GC_DS_LENGTH, 0, 1); - global_strong_weak_kind = GC_new_kind(GC_new_free_list(), GC_DS_LENGTH, 1, 1); for (cur_stamp = 0; cur_stamp <= local_stamp_max; ++cur_stamp) { if (local_stamp_layout[cur_stamp].layout_op != undefined_op) { #ifdef DUMP_PRECISE_CALC diff --git a/src/gctools/memoryManagement.cc b/src/gctools/memoryManagement.cc index d15ac2ffe7..db44719181 100644 --- a/src/gctools/memoryManagement.cc +++ b/src/gctools/memoryManagement.cc @@ -384,7 +384,8 @@ void rawHeaderDescribe(const uintptr_t* headerP) { uintptr_t headerTag = (*headerP) & Header_s::mtag_mask; switch (headerTag) { case Header_s::invalid0_mtag: - case Header_s::invalid1_mtag: { + case Header_s::invalid1_mtag: + case Header_s::invalid2_mtag: { printf(" %p : %" PRIuPTR "(%p) %" PRIuPTR "(%p)\n", headerP, *headerP, (void*)*headerP, *(headerP + 1), (void*)*(headerP + 1)); printf(" Not an object header!\n"); break; @@ -603,8 +604,6 @@ bool Header_s::isValidGeneralObject() const { goto bad; } #endif - } else if (!this->_badge_stamp_wtag_mtag.weakObjectP()) { - goto bad; } return true; bad: @@ -670,8 +669,6 @@ bool BaseHeader_s::preciseIsPolymorphic() const { return global_stamp_layout[stamp].flags & IS_POLYMORPHIC; } else if (this->_badge_stamp_wtag_mtag.consObjectP()) { return false; - } else if (this->_badge_stamp_wtag_mtag.weakObjectP()) { - return false; } return false; } @@ -873,8 +870,6 @@ void walkRoots(RootWalkCallback&& callback) { #define GENERAL_PTR_TO_HEADER_PTR(_general_) GeneralPtrToHeaderPtr((void*)_general_) // #define HEADER_PTR_TO_GENERAL_PTR(_header_) headerPointerToGeneralPointer((gctools::Header_s*)_header_) -#define WEAK_PTR_TO_HEADER_PTR(_general_) WeakPtrToHeaderPtr((void*)_general_) -// #define HEADER_PTR_TO_WEAK_PTR(_header_) headerPointerToGeneralPointer((gctools::Header_s*)_header_) #define ADDR_T uintptr_t #define EXTRA_ARGUMENTS , std::stack& markStack @@ -893,12 +888,6 @@ void walkRoots(RootWalkCallback&& callback) { #undef CONS_SKIP #undef CONS_SCAN -#define WEAK_SCAN mw_weak_scan -#define WEAK_SKIP mw_weak_skip -#include "weak_scan.cc" -#undef WEAK_SKIP -#undef WEAK_SCAN - #undef POINTER_FIX #undef ADDR_T #undef EXTRA_ARGUMENTS @@ -915,16 +904,14 @@ static void mapAllObjectsInternal(std::set& markSet, Tagged tagged = *field; switch(ptag(tagged)) { - case general_tag: { // general object: check weakness + case general_tag: { // general object if (!markSet.contains(tagged)) { // only process each object once markSet.insert(tagged); uintptr_t client = untag_object(tagged); Header_s* header = (Header_s*)GeneralPtrToHeaderPtr((void*)client); // the mw_foo_scan functions push all fields of the object // onto the markStack to keep the loop going. - if (header->_badge_stamp_wtag_mtag.weakObjectP()) - mw_weak_scan(client, markStack); - else mw_obj_scan(client, markStack); + mw_obj_scan(client, markStack); // now's the time to callback. Could also go before the scan callback(tagged); } @@ -978,28 +965,24 @@ std::set memtest(std::set& dladdrFailed) { uintptr_t client = tagged & ptr_mask; Header_s* header = (Header_s*)GeneralPtrToHeaderPtr((void*)client); if (header->isValidGeneralObject()) { - if (header->_badge_stamp_wtag_mtag.weakObjectP()) - mw_weak_scan(client, markStack); - else { - mw_obj_scan(client, markStack); + mw_obj_scan(client, markStack); // If this is a function, check its dladdrability. - core::T_sp tobj(tagged); - if (tobj.isA()) { - auto sfun = tobj.as_unsafe(); - if (!sfun->dladdrablep(uniqueEntryPoints)) - dladdrFailed.insert(sfun); - } - // This CoreFun check seems like it should work, but - // snapshots in a FASO build trip it. - // TODO figure that out? - // Snapshots seem to work without this test, anyway. - /* - else if (tobj.isA()) { - auto sfun = tobj.as_unsafe(); - if (!sfun->dladdrablep(uniqueEntryPoints)) - dladdrFailed.insert(sfun); - }*/ + core::T_sp tobj(tagged); + if (tobj.isA()) { + auto sfun = tobj.as_unsafe(); + if (!sfun->dladdrablep(uniqueEntryPoints)) + dladdrFailed.insert(sfun); } + // This CoreFun check seems like it should work, but + // snapshots in a FASO build trip it. + // TODO figure that out? + // Snapshots seem to work without this test, anyway. + /* + else if (tobj.isA()) { + auto sfun = tobj.as_unsafe(); + if (!sfun->dladdrablep(uniqueEntryPoints)) + dladdrFailed.insert(sfun); + }*/ } else corrupt.insert(tagged); } } break; @@ -1046,12 +1029,6 @@ size_t objectSize(BaseHeader_s* header) { uintptr_t client = (uintptr_t)HeaderPtrToConsPtr(header); [[maybe_unused]] uintptr_t clientLimit = mw_cons_skip(client, consSize); return consSize; - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { - // It's a weak object - size_t objectSize; - uintptr_t client = (uintptr_t)HeaderPtrToWeakPtr(header); - [[maybe_unused]] uintptr_t clientLimit = mw_weak_skip(client, false, objectSize); - return objectSize; } else { // It's a general object - walk it size_t objectSize; diff --git a/src/gctools/obj_scan.cc b/src/gctools/obj_scan.cc index 72857a2f47..0d4156625d 100644 --- a/src/gctools/obj_scan.cc +++ b/src/gctools/obj_scan.cc @@ -197,7 +197,8 @@ ADDR_T OBJECT_SCAN(ADDR_T client EXTRA_ARGUMENTS) { } #endif // USE_MPS case gctools::Header_s::invalid0_mtag: - case gctools::Header_s::invalid1_mtag: { + case gctools::Header_s::invalid1_mtag: + case gctools::Header_s::invalid2_mtag: { throw_hard_error_bad_client((void*)client); } } @@ -358,7 +359,8 @@ ADDR_T OBJECT_SKIP(ADDR_T client, bool dbg, size_t& obj_size) { break; } case gctools::Header_s::invalid0_mtag: - case gctools::Header_s::invalid1_mtag: { + case gctools::Header_s::invalid1_mtag: + case gctools::Header_s::invalid2_mtag: { throw_hard_error_bad_client((void*)client); break; } diff --git a/src/gctools/snapshotSaveLoad.cc b/src/gctools/snapshotSaveLoad.cc index f9710c372d..c4be5bf6f2 100644 --- a/src/gctools/snapshotSaveLoad.cc +++ b/src/gctools/snapshotSaveLoad.cc @@ -872,8 +872,6 @@ gctools::clasp_ptr_t headerPointerToGeneralPointer(gctools::Header_s* header) { #define GENERAL_PTR_TO_HEADER_PTR(_general_) generalPointerToHeaderPointer((gctools::clasp_ptr_t)_general_) #define HEADER_PTR_TO_GENERAL_PTR(_header_) headerPointerToGeneralPointer((gctools::Header_s*)_header_) -#define WEAK_PTR_TO_HEADER_PTR(_general_) generalPointerToHeaderPointer((gctools::clasp_ptr_t)_general_) -#define HEADER_PTR_TO_WEAK_PTR(_header_) headerPointerToGeneralPointer((gctools::Header_s*)_header_) typedef gctools::clasp_ptr_t (*PointerFix)(gctools::clasp_ptr_t* clientAddress, gctools::clasp_ptr_t client, uintptr_t tag, void* user_data); @@ -1000,8 +998,6 @@ gctools::clasp_ptr_t test_pointer(gctools::clasp_ptr_t* clientAddress, gctools:: header = GENERAL_PTR_TO_HEADER_PTR(client); } else if (tag == gctools::cons_tag) { header = (gctools::Header_s*)gctools::ConsPtrToHeaderPtr(client); - } else { - header = WEAK_PTR_TO_HEADER_PTR(client); } auto found = islInfo->_forwarding.find(header); if (found == islInfo->_forwarding.end()) { @@ -1032,8 +1028,6 @@ gctools::clasp_ptr_t maybe_follow_forwarding_pointer(gctools::clasp_ptr_t* clien header = GENERAL_PTR_TO_HEADER_PTR(client); } else if (tag == gctools::cons_tag) { header = (gctools::Header_s*)gctools::ConsPtrToHeaderPtr(client); - } else { - header = WEAK_PTR_TO_HEADER_PTR(client); } DBG_SL_FFWD((" maybe_follow_forwarding_pointer client %p header: %p\n"), (void*)client, (void*)header); if (islInfo->_operation == SaveOp && !is_forwarding_pointer(header, islInfo)) { @@ -1129,15 +1123,6 @@ gctools::clasp_ptr_t maybe_follow_forwarding_pointer(gctools::clasp_ptr_t* clien #undef CONS_SKIP #undef CONS_SCAN -#define WEAK_SCAN isl_weak_scan -#define WEAK_SKIP isl_weak_skip -#define WEAK_FWD isl_weak_fwd -#define WEAK_SKIP_IN_WEAK_FWD isl_weak_skip -#include "weak_scan.cc" -#undef WEAK_FWD -#undef WEAK_SKIP -#undef WEAK_SCAN - #undef ADDR_T #undef EXTRA_ARGUMENTS @@ -1194,7 +1179,6 @@ namespace snapshotSaveLoad { typedef enum { General = 0xbedabb1e01010101, // !OBJECT! Cons = 0xbedabb1e02020202, - Weak = 0xbedabb1e03030303, Library = 0xbedabb1e04040404, Roots = 0xbedabb1e05050505, // ROOTS End = 0xbedabb1e06060606 @@ -1322,8 +1306,7 @@ void boehm_walker_callback(void* ptr, size_t sz, void* client_data) { kind = GC_get_kind_and_size((void*)ptr, &psize); // On boehm sometimes I get unknown objects that I'm trying to avoid with the next test. if (kind == gctools::global_lisp_kind || kind == gctools::global_cons_kind || kind == gctools::global_class_kind || - kind == gctools::global_container_kind || kind == gctools::global_code_kind || kind == gctools::global_atomic_kind || - kind == gctools::global_strong_weak_kind) { + kind == gctools::global_container_kind || kind == gctools::global_code_kind || kind == gctools::global_atomic_kind) { // Either there is a tag in the low 3 bits of the ptr or the second word is not zero // Blocks can be passed to us that have a boehm free-list pointer in the first word and zero everywhere else // a free-list pointer will have zero in the low 3 bits @@ -1375,12 +1358,6 @@ struct ISLConsHeader_s : public ISLHeader_s { } }; -struct ISLWeakHeader_s : public ISLHeader_s { - gctools::Header_s _Header; - ISLWeakHeader_s(ISLKind k, uintptr_t sz, gctools::Header_s* head) : ISLHeader_s(k, sz), _Header(head){}; - gctools::Header_s* header() const { return (gctools::Header_s*)((char*)this + offsetof(ISLWeakHeader_s, _Header)); } -}; - struct ISLGeneralHeader_s : public ISLHeader_s { gctools::Header_s _Header; ISLGeneralHeader_s(ISLKind k, uintptr_t sz, gctools::Header_s* head, bool verbose) : ISLHeader_s(k, sz), _Header(head, verbose) { @@ -1419,8 +1396,6 @@ ISLHeader_s* ISLHeader_s::next(ISLKind k) const { headerSize = sizeof(ISLGeneralHeader_s); } else if (k == Cons) { headerSize = sizeof(ISLConsHeader_s); - } else if (k == Weak) { - headerSize = sizeof(ISLWeakHeader_s); } else { SIMPLE_ERROR("Add support to calculate size of ISLKind {}", (int)k); } @@ -1439,9 +1414,6 @@ gctools::BaseHeader_s::BadgeStampWtagMtag* ISLHeader_s::stamp_wtag_mtag_P(ISLKin ISLConsHeader_s* consCur = (ISLConsHeader_s*)this; gctools::ConsHeader_s* header = consCur->header(); return &header->_badge_stamp_wtag_mtag; - } else if (k == Weak) { - gctools::Header_s* header = (gctools::Header_s*)((char*)this + offsetof(ISLWeakHeader_s, _Header)); - return &header->_badge_stamp_wtag_mtag; } SIMPLE_ERROR("Add support to get _badge_stamp_wtag_mtag of ISLKind {}", (int)k); } @@ -1462,9 +1434,6 @@ struct ensure_forward_t : public walker_callback_t { } else if (header->_badge_stamp_wtag_mtag.consObjectP()) { printf("%s:%d:%s The ISL cons %p %s is not a forwarding pointer\n", __FILE__, __LINE__, __FUNCTION__, (void*)header, header->description().c_str()); - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { - printf("%s:%d:%s The ISL weak %p %s is not a forwarding pointer\n", __FILE__, __LINE__, __FUNCTION__, (void*)header, - header->description().c_str()); } } } @@ -1486,8 +1455,6 @@ struct gather_info_for_snapshot_save_t : public walker_callback_t { } } else if (header->_badge_stamp_wtag_mtag.consObjectP()) { // Nothing - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { - // Nothing } } gather_info_for_snapshot_save_t(Fixup* fixup, ISLInfo* info) : walker_callback_t(info), _fixup(fixup){}; @@ -1525,8 +1492,6 @@ struct prepare_for_snapshot_save_t : public walker_callback_t { } } else if (header->_badge_stamp_wtag_mtag.consObjectP()) { // Nothing - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { - // Nothing } } prepare_for_snapshot_save_t(Fixup* fixup, ISLInfo* info) : walker_callback_t(info), _fixup(fixup){}; @@ -1545,7 +1510,6 @@ struct calculate_size_t : public walker_callback_t { size_t _ObjectFileTotalSize; size_t _general_count; size_t _cons_count; - size_t _weak_count; size_t _ObjectFileCount; size_t _CodeCount; void callback(gctools::BaseHeader_s* header) { @@ -1584,18 +1548,11 @@ struct calculate_size_t : public walker_callback_t { size_t consSize; isl_cons_skip(client, consSize); this->_TotalSize += sizeof(ISLConsHeader_s) + consSize; - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { - gctools::clasp_ptr_t client = (gctools::clasp_ptr_t)HEADER_PTR_TO_WEAK_PTR(header); - this->_weak_count++; - DBG_SL1(("weak object header %p client: %p\n") , (void*)header , (void*)client); - size_t objectSize; - [[maybe_unused]] gctools::clasp_ptr_t nextClient = isl_weak_skip(client, false, objectSize); - this->_TotalSize += sizeof(ISLWeakHeader_s) + objectSize; } } calculate_size_t(ISLInfo* info) - : walker_callback_t(info), _TotalSize(0), _ObjectFileTotalSize(0), _general_count(0), _cons_count(0), _weak_count(0), + : walker_callback_t(info), _TotalSize(0), _ObjectFileTotalSize(0), _general_count(0), _cons_count(0), _ObjectFileCount(0), _CodeCount(0){}; }; @@ -1754,21 +1711,6 @@ struct copy_objects_t : public walker_callback_t { DBG_SAVECOPY(" copied cons header %p to %p | CAR: %p CDR: %p\n", header, (void*)islh, (void*)cons->_Car.load().raw_(), (void*)cons->_Cdr.load().raw_()); DBG_SL_FWD("setFwdPointer cons header %p new_addr -> %p\n", (void*)header, (void*)new_addr); - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { - // printf("%s:%d:%s weak_skip\n", __FILE__, __LINE__, __FUNCTION__ ); - gctools::clasp_ptr_t clientStart = (gctools::clasp_ptr_t)HEADER_PTR_TO_WEAK_PTR(header); - size_t weakSize; - [[maybe_unused]] gctools::clasp_ptr_t dummyNextClient = isl_weak_skip(clientStart, false, weakSize); - if (weakSize == 0) - ISL_ERROR(fmt::format("A zero size weak object at {} was encountered", (void*)clientStart)); - gctools::clasp_ptr_t clientEnd = clientStart + weakSize; - ISLWeakHeader_s islheader(Weak, clientEnd - clientStart, (gctools::Header_s*)header); - char* islh = this->_objects->write_buffer((char*)&islheader, sizeof(ISLWeakHeader_s)); - char* new_addr = this->_objects->write_buffer((char*)clientStart, clientEnd - clientStart); - set_forwarding_pointer(header, new_addr, this->_info); - this->_progress.update((uintptr_t)islh); - DBG_SAVECOPY(" copied weak header %p to %p\n", header, (void*)islh); - DBG_SL_FWD("setFwdPointer weak header %p new_addr -> %p\n", (void*)header, (void*)new_addr); } this->_NumberOfObjects++; } @@ -1795,11 +1737,6 @@ template void walk_snapshot_save_load_objects(ISLHeader_s* sta DBG_SL_WALK_SL(BF("cons header: %p %s next: %p\n") % header % header->description() % (void*)consCur->next()); walker.callback(header); - } else if (cur->_Kind == Weak) { - gctools::Header_s* header = (gctools::Header_s*)((char*)cur + offsetof(ISLWeakHeader_s, _Header)); - DBG_SL_WALK_SL(BF("weak header: %p %s next: %p\n") % header % header->description() % - (void*)weakCur->next()); - walker.callback(header); } else { printf("%s:%d:%s Hit header@%p with unexpected kind: %lu\n", __FILE__, __LINE__, __FUNCTION__, (void*)cur, cur->_Kind); abort(); @@ -1832,9 +1769,6 @@ struct fixup_objects_t : public walker_callback_t { } else if (header->_badge_stamp_wtag_mtag.consObjectP()) { gctools::clasp_ptr_t client = (gctools::clasp_ptr_t)gctools::HeaderPtrToConsPtr(header); isl_cons_scan(client, (void*)this->_info); - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { - gctools::clasp_ptr_t clientStart = (gctools::clasp_ptr_t)HEADER_PTR_TO_WEAK_PTR(header); - isl_weak_scan(clientStart, (void*)this->_info); } } }; @@ -1872,7 +1806,6 @@ struct fixup_internals_t : public walker_callback_t { } } } else if (header->_badge_stamp_wtag_mtag.consObjectP()) { - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { } } }; @@ -1912,15 +1845,6 @@ struct fixup_vtables_t : public walker_callback_t { } } else if (header->_badge_stamp_wtag_mtag.consObjectP()) { // Do nothing - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { - if (header->preciseIsPolymorphic()) { - uintptr_t client = (uintptr_t)HEADER_PTR_TO_WEAK_PTR(header); - uintptr_t vtable; - uintptr_t new_vtable; - this->do_vtable((gctools::Header_s*)header, (core::T_O*)client, vtable, new_vtable); - DBG_SL_VTABLE(BF(" wrote weak base %p vtable in memory at %p value: %p to %p %s\n") % (void*)this->_vtableRegionStart % - (void*)client % (void*)vtable % (void*)new_vtable % header->description()); - } } } }; @@ -2292,7 +2216,6 @@ void* snapshot_save_impl(void* data) { fmt::print(" size = {}\n", calc_size._TotalSize); fmt::print(" general_count = {}\n", calc_size._general_count); fmt::print(" cons_count = {}\n", calc_size._cons_count); - fmt::print(" weak_count = {}\n", calc_size._weak_count); fmt::print(" ObjectFileCount = {}\n", calc_size._ObjectFileCount); fmt::print(" CodeCount = {}\n", calc_size._CodeCount); @@ -2714,11 +2637,11 @@ template void walk_temporary_root_objects(const temporary_root DBG_SL_WALK_TEMP(BF("Starting walk of %lu roots at %p\n") % roots._Number % (void*)roots._buffer); for (size_t idx = 0; idx < roots._Number; idx++) { core::T_O* tagged_client = (core::T_O*)roots._buffer[idx]; - // This will handle general and weak objects + // This will handle general objects if (gctools::tagged_generalp(tagged_client)) { core::T_O* untagged_client = gctools::untag_general(tagged_client); gctools::Header_s* header = (gctools::Header_s*)gctools::GeneralPtrToHeaderPtr(untagged_client); - DBG_SL_WALK_TEMP(BF("Walking to GC[%lu/%lu] managed general or weak header %p %s\n") % idx % roots._Number % (void*)header % + DBG_SL_WALK_TEMP(BF("Walking to GC[%lu/%lu] managed general header %p %s\n") % idx % roots._Number % (void*)header % header->description()); walker.callback(header); } else if (gctools::tagged_consp(tagged_client)) { @@ -2758,9 +2681,6 @@ struct relocate_objects_t : public walker_callback_t { isl_cons_scan(client, (void*)this->_info); // printf("%s:%d:%s The object @ %p %s isPolymorphic->%d\n", __FILE__, __LINE__, __FUNCTION__, (void*)header, // header->description().c_str(), header->preciseIsPolymorphic()); - } else if (header->_badge_stamp_wtag_mtag.weakObjectP()) { - gctools::clasp_ptr_t clientStart = (gctools::clasp_ptr_t)HEADER_PTR_TO_WEAK_PTR(header); - isl_weak_scan(clientStart, (void*)this->_info); } } }; @@ -3390,14 +3310,6 @@ void snapshot_load(void* maybeStartOfSnapshot, void* maybeEndOfSnapshot, const s DBG_SL_ALLOCATE(BF("---- Allocated Cons %p copy from %p header: %p set fwd to %p\n") % (void*)obj.raw_() % (void*)header % (void*)clientStart % (void*)fwd); root_holder.add((void*)obj.raw_()); - } else if (cur_header->_Kind == Weak) { - ISLWeakHeader_s* weakHeader = (ISLWeakHeader_s*)cur_header; - gctools::Header_s* header = (gctools::Header_s*)&weakHeader->_Header; - gctools::clasp_ptr_t clientStart = (gctools::clasp_ptr_t)(weakHeader + 1); - gctools::clasp_ptr_t clientEnd = clientStart + weakHeader->_Size; - snapshot_save_load_init_s init(header, clientStart, clientEnd); - printf("%s:%d:%s Handle allocate weak objects\n", __FILE__, __LINE__, __FUNCTION__); - break; } else { printf("%s:%d:%s Unknown header at offset 0x%lx qword: 0x%lx\n", __FILE__, __LINE__, __FUNCTION__, (uintptr_t)cur_header - (uintptr_t)fileHeader, *(uintptr_t*)cur_header); diff --git a/src/gctools/startRunStop.cc b/src/gctools/startRunStop.cc index 69331cd6a4..818cf0efda 100644 --- a/src/gctools/startRunStop.cc +++ b/src/gctools/startRunStop.cc @@ -179,12 +179,6 @@ CL_DEFUN void gctools__register_loaded_objects() { extern "C" { int startup_clasp(void** stackMarker, gctools::ClaspInfo* claspInfo, int* exitCode) { - - if (gctools::Header_s::weak_mtag != gctools::character_tag) { - printf("%s:%d:%s The Header_s::weak_mtag (%lu) MUST have the same value as gctools::character_tag(%lu)\n", __FILE__, __LINE__, - __FUNCTION__, (uintptr_t)gctools::Header_s::weak_mtag, (uintptr_t)gctools::character_tag); - abort(); - } gctools::_global_stack_max_size = claspInfo->_stackMax; gctools::global_alignup_sizeof_header = gctools::AlignUp(sizeof(gctools::Header_s)); gctools::global_sizeof_fwd = gctools::AlignUp(sizeof(gctools::Header_s)); diff --git a/src/gctools/weak_scan.cc b/src/gctools/weak_scan.cc deleted file mode 100644 index 55c068f577..0000000000 --- a/src/gctools/weak_scan.cc +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Object scanner - include this and modify the following macros - * to customize this code for different purposes. - * - * -#define ADDR_T mps_addr_t // Type of addresses -#define OBJECT_SCAN fixup_objects // Name of function -#define POINTER_FIX(field) // Macro to fix pointer at field -#define WEAK_SCAN // Macro to turn on #ifdef inclusion of code -#define WEAK_SKIP // Macro to turn on #ifdef inclusion of code -#define WEAK_FWD // Macro to turn on #ifdef inclusion of code - */ - -// !!!!! DEBUG_OBJECT_SCAN can only be on when DEBUG_GUARD_VALIDATE is on!!!!!! -// #define DEBUG_OBJECT_SCAN 1 -// #define DEBUG_POINTER_BITMAPS 1 - -// #define DEBUG_CONTAINER_SCAN 1 -// #define DEBUG_CONTAINER_POINTER_BITMAPS 1 - -#ifdef WEAK_SCAN -ADDR_T WEAK_SCAN(ADDR_T client EXTRA_ARGUMENTS) { - const gctools::Header_s& header = *reinterpret_cast(WEAK_PTR_TO_HEADER_PTR(client)); - switch (header._badge_stamp_wtag_mtag._value) { - default: - THROW_HARD_ERROR("handle other weak kind {}", header._badge_stamp_wtag_mtag._value); - } - return client; -} -#endif - -#ifdef WEAK_SKIP -ADDR_T WEAK_SKIP(ADDR_T client, bool dbg, size_t& objectSize) { - const gctools::Header_s& header = *reinterpret_cast(WEAK_PTR_TO_HEADER_PTR(client)); - if (header._badge_stamp_wtag_mtag.weakObjectP()) { - THROW_HARD_ERROR("Handle weak_obj_skip other weak kind {}", header._badge_stamp_wtag_mtag._value); - } - client = (ADDR_T)((char*)client + objectSize + sizeof(gctools::Header_s)); - return client; -}; -#endif - -#ifdef WEAK_FWD -void WEAK_FWD(ADDR_T old_client, ADDR_T new_client) { - gctools::Header_s& header = *reinterpret_cast(WEAK_PTR_TO_HEADER_PTR(old_client)); - size_t objectSize; - ADDR_T limit = WEAK_SKIP_IN_WEAK_FWD(old_client, false, objectSize); - size_t size = (char*)limit - (char*)old_client; - assert(size >= Align(sizeof(weak_fwd2_s))); - header._badge_stamp_wtag_mtag.setFwdPointer((void*)new_client); - header._badge_stamp_wtag_mtag.setFwdSize(size); -} -#endif From b431bcc54d68ac8842f45113079ef3dc33f45803 Mon Sep 17 00:00:00 2001 From: Bike Date: Thu, 16 Jan 2025 16:59:04 -0500 Subject: [PATCH 29/39] Teach static analyzer about weak pointers Not useful yet but it took me a while to figure it out --- include/clasp/gctools/gc_boot.h | 3 ++- src/analysis/clasp_gc.sif | 8 ++----- src/analysis/clasp_gc_cando.sif | 8 ++----- .../clasp-analyzer/clasp-analyzer.lisp | 22 ++++++++++++++++++- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/include/clasp/gctools/gc_boot.h b/include/clasp/gctools/gc_boot.h index 5ed84411bf..8d4a704792 100644 --- a/include/clasp/gctools/gc_boot.h +++ b/include/clasp/gctools/gc_boot.h @@ -34,6 +34,7 @@ enum Data_types { SMART_PTR_OFFSET, ATOMIC_SMART_PTR_OFFSET, TAGGED_POINTER_OFFSET, + WEAK_PTR_OFFSET, RAW_POINTER_OFFSET, ARRAY_OFFSET, POINTER_OFFSET, @@ -75,7 +76,7 @@ enum Data_types { // // Use powers of two for the flags // -enum ClassFlags { IS_POLYMORPHIC = 1 }; +enum ClassFlags { IS_POLYMORPHIC = 1, COMPLEX_SCAN = 2 }; extern uintptr_t global_lisp_kind; extern uintptr_t global_cons_kind; diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index 9f5834ecbd..a4fdf7e5df 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -840,12 +840,8 @@ {class-kind :stamp-name "STAMPWTAG_core__WeakPointer_O" :stamp-key "core::WeakPointer_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::WeakPointer_O" - :layout-offset-field-names ("_Link" "._value")} -{fixed-field :offset-type-cxx-identifier "ctype__Bool" :offset-ctype "_Bool" - :offset-base-ctype "core::WeakPointer_O" - :layout-offset-field-names ("_Link" "._splattablep")} +{fixed-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" :offset-ctype "gctools::WeakPointer" + :offset-base-ctype "core::WeakPointer_O" :layout-offset-field-names ("_Link")} {class-kind :stamp-name "STAMPWTAG_llvmo__DebugLoc_O" :stamp-key "llvmo::DebugLoc_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index 1e34c7a285..e459cec32f 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -6484,12 +6484,8 @@ {class-kind :stamp-name "STAMPWTAG_core__WeakPointer_O" :stamp-key "core::WeakPointer_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::WeakPointer_O" - :layout-offset-field-names ("_Link" "._value")} -{fixed-field :offset-type-cxx-identifier "ctype__Bool" :offset-ctype "_Bool" - :offset-base-ctype "core::WeakPointer_O" - :layout-offset-field-names ("_Link" "._splattablep")} +{fixed-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" :offset-ctype "gctools::WeakPointer" + :offset-base-ctype "core::WeakPointer_O" :layout-offset-field-names ("_Link")} {class-kind :stamp-name "STAMPWTAG_llvmo__DebugLoc_O" :stamp-key "llvmo::DebugLoc_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/lisp/modules/clasp-analyzer/clasp-analyzer.lisp b/src/lisp/modules/clasp-analyzer/clasp-analyzer.lisp index 1667d5d433..b58f7dfeeb 100644 --- a/src/lisp/modules/clasp-analyzer/clasp-analyzer.lisp +++ b/src/lisp/modules/clasp-analyzer/clasp-analyzer.lisp @@ -412,6 +412,8 @@ This could change the value of stamps for specific classes - but that would brea (defstruct (tagged-pointer-ctype (:include ctype)) specializer) +(defstruct (weak-ptr-ctype (:include ctype))) + (defstruct (pointer-ctype (:include ctype)) pointee) @@ -512,6 +514,9 @@ This could change the value of stamps for specific classes - but that would brea (defclass tagged-pointer-offset (copyable-offset) ()) +(defclass weak-ptr-offset (copyable-offset) + ()) + (defclass pointer-offset (copyable-offset) ()) @@ -944,6 +949,10 @@ to expose to C++. (declare (ignore analysis)) (list (make-instance 'tagged-pointer-offset :base base :offset-type x))) +(defmethod linearize-class-layout-impl ((x weak-ptr-ctype) base analysis) + (declare (ignore analysis)) + (list (make-instance 'weak-ptr-offset :base base :offset-type x))) + (defun linearize-constant-array-contents (array element-type elements) "* Arguments - array :: A constant-array-ctype. @@ -1198,6 +1207,8 @@ can be saved and reloaded within the project for later analysis" (make-mutex-ctype :key decl-key :name name)) ((string= name "SharedMutex") (make-shared-mutex-ctype :key decl-key :name name)) + ((string= name "WeakPointer") + (make-weak-ptr-ctype :key decl-key)) (t (make-cxxrecord-ctype :key decl-key :name name)))) (cast:record-decl (warn "classify-decl found ~a decl-key: ~a name: ~a - this means that the mostDerivedType code isn't working!!!!" (type-of decl) decl-key name) @@ -1427,7 +1438,6 @@ can be saved and reloaded within the project for later analysis" (or *field-submatcher* (error "Problem encountered compiling *field-submatcher*")) - (defun setup-cclass-search (mtool) (symbol-macrolet ((results (project-classes (clang-tool:multitool-results mtool)))) @@ -1877,6 +1887,9 @@ so that they don't have to be constantly recalculated" (defmethod contains-fixptr-impl-p ((x tagged-pointer-ctype) project) (declare (ignore project)) t) +(defmethod contains-fixptr-impl-p ((x weak-ptr-ctype) project) + (declare (ignore project)) + t) (defmethod contains-fixptr-impl-p ((x pointer-ctype) project) (cond ((container-p (pointer-ctype-pointee x)) t) @@ -1924,6 +1937,9 @@ so that they don't have to be constantly recalculated" (defmethod expand-forwards-with-template-arguments ((forwards t) (alloc-ctype tagged-pointer-ctype)) nil) +(defmethod expand-forwards-with-template-arguments + ((forwards t) (alloc-ctype weak-ptr-ctype)) + nil) (defmethod expand-forwards-with-template-arguments (forwards (alloc-ctype cxxrecord-ctype)) (add-ctype forwards (ctype-key alloc-ctype) alloc-ctype)) (defmethod expand-forwards-with-template-arguments (forwards (alloc-ctype pointer-ctype)) @@ -2432,6 +2448,10 @@ Recursively analyze x and return T if x contains fixable pointers." (declare (ignore analysis)) :tagged-pointer-fix) +(defmethod fixable-instance-variables-impl ((x weak-ptr-ctype) analysis) + (declare (ignore analysis)) + :weak-ptr-fix) + (defmethod fixable-instance-variables-impl ((x constant-array-ctype) analysis) (when (contains-fixptr-p x (analysis-project analysis)) (fixable-instance-variables-impl (constant-array-ctype-element-type x) analysis))) From 0f3373a3711d3840f1bd7e964f32b342895275f9 Mon Sep 17 00:00:00 2001 From: Bike Date: Thu, 16 Jan 2025 17:56:58 -0500 Subject: [PATCH 30/39] Generalize core::Lisp special case in scanner This should allow us to smoothly support objects with Lisp pointers more than 62 words in. Also, I don't think the Lisp object is even actually that big right now - presumably it used to be - so this might save us a microsecond of scanning time as we use the bitmap. --- src/gctools/gc_boot.cc | 23 +++++++++-------------- src/gctools/obj_scan.cc | 5 +++-- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/gctools/gc_boot.cc b/src/gctools/gc_boot.cc index 9acc3ef04c..3a6453f13c 100644 --- a/src/gctools/gc_boot.cc +++ b/src/gctools/gc_boot.cc @@ -117,12 +117,8 @@ void dump_data_types(std::ostream& fout, const std::string& indent) { inline int bitmap_field_index(size_t start, size_t offset) { int bitindex = start - (offset / 8); - if (bitindex > 63 || bitindex < 2) { - printf("%s:%d The bit position %d for offset %lu will not fit in a 64-bit word - the class has pointers beyond the reach of a " - "62-bit bitmap\n", - __FILE__, __LINE__, bitindex, offset); - } - return bitindex; + if (bitindex > 63 || bitindex < 2) return -1; + else return bitindex; } inline uintptr_t bitmap_field_bitmap(size_t bitindex) { return (uintptr_t)1 << bitindex; } @@ -253,21 +249,20 @@ void walk_stamp_field_layout_tables(WalkKind walk, std::ostream& fout) { if ((data_type == SMART_PTR_OFFSET || data_type == ATOMIC_SMART_PTR_OFFSET || data_type == TAGGED_POINTER_OFFSET || data_type == POINTER_OFFSET)) { GCTOOLS_ASSERT(cur_field_layout < max_field_layout); - // Handle Lisp object specially - // There is a corresponding change to obj_scan.cc #ifdef USE_PRECISE_GC int bit_index; uintptr_t field_bitmap; - if (cur_stamp != STAMP_UNSHIFT_WTAG(gctools::STAMPWTAG_core__Lisp)) { // wasMTAG - bit_index = bitmap_field_index(63, field_offset); - field_bitmap = bitmap_field_bitmap(bit_index); - local_stamp_layout[cur_stamp].class_field_pointer_bitmap |= field_bitmap; + bit_index = bitmap_field_index(63, field_offset); + if (bit_index == -1) { + // We have a field we need to fix that is beyond the range of a bitmap. + // Flag this class to tell the scanner to use the field layouts instead. + local_stamp_layout[cur_stamp].flags |= COMPLEX_SCAN; } else { - // Do the same for STAMPWTAG_core__Lisp - but if it doesn't fit in a 64bit word then we will skip this. - bit_index = bitmap_field_index(63, field_offset); + // Otherwise (normal case) just put it in the bitmap. field_bitmap = bitmap_field_bitmap(bit_index); local_stamp_layout[cur_stamp].class_field_pointer_bitmap |= field_bitmap; } + if (local_stamp_layout[cur_stamp].field_layout_start == NULL) local_stamp_layout[cur_stamp].field_layout_start = cur_field_layout; DGC_PRINT("%s:%d fixed_field %s : cur_stamp = %d field_offset = %lu bit_index =%d bitmap = 0x%lX\n", __FILE__, __LINE__, diff --git a/src/gctools/obj_scan.cc b/src/gctools/obj_scan.cc index 0d4156625d..6ded875496 100644 --- a/src/gctools/obj_scan.cc +++ b/src/gctools/obj_scan.cc @@ -51,9 +51,10 @@ ADDR_T OBJECT_SCAN(ADDR_T client EXTRA_ARGUMENTS) { size = stamp_layout.size; } if (stamp_layout.field_layout_start) { - // Handle Lisp object specially because it's bitmask will be too large #ifdef USE_PRECISE_GC - if (stamp_index == STAMP_UNSHIFT_WTAG(gctools::STAMPWTAG_core__Lisp)) { // wasMTAG + if (stamp_layout.flags & gctools::COMPLEX_SCAN) { + // This object is too big for the bitmap, or has something weird in it + // like weak references. Scan by iterating over the fields. int num_fields = stamp_layout.number_of_fields; const gctools::Field_layout* field_layout_cur = stamp_layout.field_layout_start; core::T_O** prevField = NULL; From ee6a72b11d040a6fd8926361d5438ef25db5f801 Mon Sep 17 00:00:00 2001 From: Bike Date: Fri, 17 Jan 2025 15:49:43 -0500 Subject: [PATCH 31/39] Get weak pointers working with snapshot load Kind of inelegant but seems to work. The separate weak pointer scanning could be used for implementing a garbage collector. Also clears out some of the debugging stuff - we can do the field check when we set up the field info, not every single time we scan --- include/clasp/core/weakPointer.h | 4 + include/clasp/gctools/gcweak.h | 6 ++ src/gctools/gc_boot.cc | 10 ++- src/gctools/gcweak.cc | 29 +++++++ src/gctools/obj_scan.cc | 135 +++++++++++++++++-------------- src/gctools/snapshotSaveLoad.cc | 1 + 6 files changed, 122 insertions(+), 63 deletions(-) diff --git a/include/clasp/core/weakPointer.h b/include/clasp/core/weakPointer.h index 032b923a4c..f9e460a987 100644 --- a/include/clasp/core/weakPointer.h +++ b/include/clasp/core/weakPointer.h @@ -56,6 +56,10 @@ class WeakPointer_O : public General_O { /*! Return true if the object referenced by this still exists, otherwise return false */ bool valid() const; + + void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) override { + _Link.fixupInternalsForSnapshotSaveLoad(fixup); + } }; // WARNING: Not a real ephemeron on some GCs (boehm). See notes in gcweak.h. diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index 1a101d15da..504d128b43 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -73,6 +73,9 @@ THE SOFTWARE. #include #include +// Caution: This file is included by obj_scan.cc which is pretty low level. +// Don't put complicated includes in here. + namespace gctools { // This structure is meant to be included directly (not as a pointer) in @@ -82,6 +85,9 @@ struct WeakPointer { public: WeakPointer(core::T_sp o); std::optional value() const; + std::optional value_no_lock() const; // used by scanner + void store_no_lock(core::T_sp); // ditto. + void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup*); public: // has to be public for precise GC reasons even though it's not scanned? // This is a Tagged rather than a T_sp because something in gc_boot seems to // check for T_sps in atomic (pointerless) objects. Rather than lie harder we diff --git a/src/gctools/gc_boot.cc b/src/gctools/gc_boot.cc index 3a6453f13c..7e2797fd6d 100644 --- a/src/gctools/gc_boot.cc +++ b/src/gctools/gc_boot.cc @@ -246,16 +246,20 @@ void walk_stamp_field_layout_tables(WalkKind walk, std::ostream& fout) { if (data_type == CXX_SHARED_MUTEX_OFFSET || data_type == CXX_FIXUP_OFFSET || data_type == ctype_opaque_ptr) { local_stamp_layout[cur_stamp].snapshot_save_load_poison++; } - if ((data_type == SMART_PTR_OFFSET || data_type == ATOMIC_SMART_PTR_OFFSET || data_type == TAGGED_POINTER_OFFSET || - data_type == POINTER_OFFSET)) { + if ((data_type == SMART_PTR_OFFSET || data_type == ATOMIC_SMART_PTR_OFFSET + || data_type == TAGGED_POINTER_OFFSET + || data_type == POINTER_OFFSET + || data_type == WEAK_PTR_OFFSET)) { GCTOOLS_ASSERT(cur_field_layout < max_field_layout); #ifdef USE_PRECISE_GC int bit_index; uintptr_t field_bitmap; bit_index = bitmap_field_index(63, field_offset); - if (bit_index == -1) { + if (data_type == WEAK_PTR_OFFSET || bit_index == -1) { // We have a field we need to fix that is beyond the range of a bitmap. // Flag this class to tell the scanner to use the field layouts instead. + // Alternately we have a weak reference that needs to be + // scanned specially. local_stamp_layout[cur_stamp].flags |= COMPLEX_SCAN; } else { // Otherwise (normal case) just put it in the bitmap. diff --git a/src/gctools/gcweak.cc b/src/gctools/gcweak.cc index 600090c6f7..a9def91fa5 100644 --- a/src/gctools/gcweak.cc +++ b/src/gctools/gcweak.cc @@ -57,11 +57,40 @@ std::optional WeakPointer::value() const { GC_call_with_alloc_lock(value_helper, &vhs); return vhs.result; } +std::optional WeakPointer::value_no_lock() const { + if (_value || !_splattablep) + return core::T_sp(_value); + else return std::nullopt; +} +void WeakPointer::store_no_lock(core::T_sp o) { + _value = o.tagged_(); + _splattablep = o.objectp(); + // links set up in fixupInternals below. +} + +void WeakPointer::fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) { + if (snapshotSaveLoad::operation(fixup) == snapshotSaveLoad::LoadOp) { + // We do this later rather than in store_no_lock because register/deregister + // unconditionally grab a lock. This is a bit of a KLUDGE. + core::T_sp o(_value); + if (o.objectp()) { + _splattablep = true; + // Implicitly removes any previous registration, per boehm docs. + GC_general_register_disappearing_link((void**)&_value, &*o); + } else { + _splattablep = false; + GC_unregister_disappearing_link((void**)&_value); + } + } +} #else // not-actually-weak pointers - TODO for your other GC! WeakPointer::WeakPointer(core::T_sp o) : _value(o.tagged_()) {} // always valid std::optional WeakPointer::value() const { return core::T_sp(_value); } +std::optional WeakPointer::value_no_lock() const { return value(); } +void WeakPointer::store_no_lock(core::T_sp o) { _value = o.tagged_(); } +void WeakPointer::fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup*) {} #endif #ifdef USE_BOEHM diff --git a/src/gctools/obj_scan.cc b/src/gctools/obj_scan.cc index 6ded875496..185478db29 100644 --- a/src/gctools/obj_scan.cc +++ b/src/gctools/obj_scan.cc @@ -1,4 +1,4 @@ - +//#include /* * Object scanner - include this and modify the following macros @@ -8,6 +8,7 @@ #define ADDR_T mps_addr_t // Type of addresses #define OBJECT_SCAN fixup_objects // Name of function #define POINTER_FIX(field) // Macro to fix pointer at field +#define WEAK_POINTER_FIX(field) // Macro for a weak ptr - ok to leave undefined #define OBJECT_SCAN // Macro to turn on #ifdef inclusion of code #define CLIENT_PTR_TO_HEADER_PTR(client) // Replace with function to get base pointer from client */ @@ -57,27 +58,29 @@ ADDR_T OBJECT_SCAN(ADDR_T client EXTRA_ARGUMENTS) { // like weak references. Scan by iterating over the fields. int num_fields = stamp_layout.number_of_fields; const gctools::Field_layout* field_layout_cur = stamp_layout.field_layout_start; - core::T_O** prevField = NULL; + const gctools::Field_info* field_info_cur = gctools::global_stamp_info[stamp_index].field_info_ptr; for (int i = 0; i < num_fields; ++i) { - core::T_O** field = (core::T_O**)((const char*)client + field_layout_cur->field_offset); - if (field == prevField) { - printf("%s:%d:%s ---- scanning object %p stamp %lu field %p is about to be POINTER_FIXed for a second time\n", - __FILE__, __LINE__, __FUNCTION__, (void*)client, stamp_index, field); - printf("%s:%d:%s field_layout_cur = %p field_layout_cur->field_offset = %p field_layout_cur->field_offset = %lu\n", - __FILE__, __LINE__, __FUNCTION__, field_layout_cur, &field_layout_cur->field_offset, - field_layout_cur->field_offset); - printf("%s:%d:%s prev field_layout_cur = %p prev &field_layout_cur->field_offset = %p prev " - "field_layout_cur->field_offset = %lu\n", - __FILE__, __LINE__, __FUNCTION__, (field_layout_cur - 1), &(field_layout_cur - 1)->field_offset, - (field_layout_cur - 1)->field_offset); - abort(); + if (field_info_cur->data_type == gctools::WEAK_PTR_OFFSET) [[unlikely]] { +#ifdef WEAK_POINTER_FIX + gctools::WeakPointer* weak = (gctools::WeakPointer*)((const char*)client + field_layout_cur->field_offset); + std::optional v = weak->value_no_lock(); + if (v) { + core::T_O* raw = v->raw_(); + WEAK_POINTER_FIX(&raw); + // Store it back in the weak pointer - this is needed for when the + // object scanner is used in image save as it needs to alter + // pointers. + weak->store_no_lock(core::T_sp((gctools::Tagged)raw)); + } +#endif + } else { + core::T_O** field = (core::T_O**)((const char*)client + field_layout_cur->field_offset); + POINTER_FIX(field); } - POINTER_FIX(field); - prevField = field; ++field_layout_cur; + ++field_info_cur; } } else { -#if 1 // Use pointer bitmaps uintptr_t pointer_bitmap = stamp_layout.class_field_pointer_bitmap; #ifdef DEBUG_POINTER_BITMAPS @@ -97,15 +100,6 @@ ADDR_T OBJECT_SCAN(ADDR_T client EXTRA_ARGUMENTS) { POINTER_FIX((core::T_O**)addr); } } -#else - int num_fields = stamp_layout.number_of_fields; - const gctools::Field_layout* field_layout_cur = stamp_layout.field_layout_start; - for (int i = 0; i < num_fields; ++i) { - core::T_O** field = (core::T_O**)((const char*)client + field_layout_cur->field_offset); - POINTER_FIX(field); - ++field_layout_cur; - } -#endif } #endif } @@ -121,23 +115,69 @@ ADDR_T OBJECT_SCAN(ADDR_T client EXTRA_ARGUMENTS) { // Use new way with pointer bitmaps uintptr_t start_pointer_bitmap = stamp_layout.container_layout->container_field_pointer_bitmap; if (header._badge_stamp_wtag_mtag._value == DO_SHIFT_STAMP(gctools::STAMPWTAG_llvmo__ObjectFile_O)) { - // printf("%s:%d:%s obj_scan for Code_o object with header %p\n", __FILE__, __LINE__, __FUNCTION__, &header - // ); llvmo::ObjectFile_O* code = (llvmo::ObjectFile_O*)client; core::T_O** addr = (core::T_O**)code->literalsStart(); core::T_O** addrEnd = addr + (code->literalsSize() / sizeof(core::T_O*)); for (; addr < addrEnd; addr++) { POINTER_FIX(addr); } + } else if (stamp_layout.flags & gctools::COMPLEX_SCAN) { + const gctools::Stamp_info& stamp_info = gctools::global_stamp_info[stamp_index]; + const char* element = ((const char*)client + stamp_layout.data_offset); + for (int i = 0; i < end; ++i, element += stamp_layout.element_size) { + size_t nfields = stamp_layout.container_layout->number_of_fields; + const gctools::Field_layout* field_layout = stamp_layout.container_layout->field_layout_start; + const gctools::Container_info* field_info = stamp_info.container_info_ptr; + for (size_t j = 0; j < nfields; ++j, ++field_layout, ++field_info) { + const char* field = element + field_layout->field_offset; + if (field_info->data_type == gctools::WEAK_PTR_OFFSET) [[unlikely]] { +#ifdef WEAK_POINTER_FIX + gctools::WeakPointer* weak = (gctools::WeakPointer*)field; + std::optional v = weak->value_no_lock(); + if (v) { + core::T_O* raw = v->raw_(); + WEAK_POINTER_FIX(&raw); + weak->store_no_lock(core::T_sp((gctools::Tagged)raw)); + } +#endif + } else { + core::T_O** tfield = (core::T_O**)field; + POINTER_FIX(tfield); + } + } + } + } else if (!start_pointer_bitmap) { + // nothing to scan + } else if (!(start_pointer_bitmap << 1)) { + // Trivial case - there is a single pointer to fix in every element and its the only element + const char* element = ((const char*)client + stamp_layout.data_offset); + for (int i = 0; i < end; ++i, element += (stamp_layout.element_size)) { + uintptr_t* addr = (uintptr_t*)element; +#ifdef DEBUG_POINTER_BITMAPS + gctools::Field_layout* field_layout_cur = container_layout.field_layout_start; + const char* element = ((const char*)client + stamp_layout.data_offset + stamp_layout.element_size * i); + core::T_O** field = (core::T_O**)((const char*)element + field_layout_cur->field_offset); + if (addr != (uintptr_t*)field) { + printf("%s:%d stamp: %lu element@%p i = %d start_pointer_bitmap=0x%lX bitmap[%p]/field[%p] address " + "mismatch!!!! field_layout_cur->field_offset=%lu\n", + __FILE__, __LINE__, stamp_index, element, i, start_pointer_bitmap, addr, field, + field_layout_cur->field_offset); + } + ++field_layout_cur; +#endif + POINTER_FIX((core::T_O**)addr); + } } else { - if (start_pointer_bitmap) { - if (!(start_pointer_bitmap << 1)) { - // Trivial case - there is a single pointer to fix in every element and its the only element - const char* element = ((const char*)client + stamp_layout.data_offset); - for (int i = 0; i < end; ++i, element += (stamp_layout.element_size)) { - uintptr_t* addr = (uintptr_t*)element; + // Multiple fields we can scan with a bitmap + const char* element = ((const char*)client + stamp_layout.data_offset); + for (int i = 0; i < end; ++i, element += (stamp_layout.element_size)) { +#ifdef DEBUG_POINTER_BITMAPS + gctools::Field_layout* field_layout_cur = container_layout.field_layout_start; +#endif + uintptr_t pointer_bitmap = start_pointer_bitmap; + for (uintptr_t* addr = (uintptr_t*)element; pointer_bitmap; addr++, pointer_bitmap <<= 1) { + if ((intptr_t)pointer_bitmap < 0) { #ifdef DEBUG_POINTER_BITMAPS - gctools::Field_layout* field_layout_cur = container_layout.field_layout_start; const char* element = ((const char*)client + stamp_layout.data_offset + stamp_layout.element_size * i); core::T_O** field = (core::T_O**)((const char*)element + field_layout_cur->field_offset); if (addr != (uintptr_t*)field) { @@ -150,31 +190,6 @@ ADDR_T OBJECT_SCAN(ADDR_T client EXTRA_ARGUMENTS) { #endif POINTER_FIX((core::T_O**)addr); } - } else { - // The contents of the container are more complicated - so use the bitmap to scan pointers within them - const char* element = ((const char*)client + stamp_layout.data_offset); - for (int i = 0; i < end; ++i, element += (stamp_layout.element_size)) { -#ifdef DEBUG_POINTER_BITMAPS - gctools::Field_layout* field_layout_cur = container_layout.field_layout_start; -#endif - uintptr_t pointer_bitmap = start_pointer_bitmap; - for (uintptr_t* addr = (uintptr_t*)element; pointer_bitmap; addr++, pointer_bitmap <<= 1) { - if ((intptr_t)pointer_bitmap < 0) { -#ifdef DEBUG_POINTER_BITMAPS - const char* element = ((const char*)client + stamp_layout.data_offset + stamp_layout.element_size * i); - core::T_O** field = (core::T_O**)((const char*)element + field_layout_cur->field_offset); - if (addr != (uintptr_t*)field) { - printf("%s:%d stamp: %lu element@%p i = %d start_pointer_bitmap=0x%lX bitmap[%p]/field[%p] address " - "mismatch!!!! field_layout_cur->field_offset=%lu\n", - __FILE__, __LINE__, stamp_index, element, i, start_pointer_bitmap, addr, field, - field_layout_cur->field_offset); - } - ++field_layout_cur; -#endif - POINTER_FIX((core::T_O**)addr); - } - } - } } } } diff --git a/src/gctools/snapshotSaveLoad.cc b/src/gctools/snapshotSaveLoad.cc index c4be5bf6f2..fe568d1a09 100644 --- a/src/gctools/snapshotSaveLoad.cc +++ b/src/gctools/snapshotSaveLoad.cc @@ -1097,6 +1097,7 @@ gctools::clasp_ptr_t maybe_follow_forwarding_pointer(gctools::clasp_ptr_t* clien }; \ }; \ } +#define WEAK_POINTER_FIX(_ptr_) POINTER_FIX(_ptr_) #define ADDR_T gctools::clasp_ptr_t #define EXTRA_ARGUMENTS , void* user_data From 8d533b19ed7c59d50aca71fc77d2a70721a05ddb Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 21 Jan 2025 11:26:10 -0500 Subject: [PATCH 32/39] Preserve ephemerons in snapshot save/load and make them traversable through ROOM There may be an issue with the previous commit alone - it may not allocate enough field infos/layouts in gc_boot. The fact the memory walker uses T_O** fields is kind of dicey since not all fields are actually pointers to pointers. We have the hidden pointers in ephemerons, but also atomics in conses etc. --- include/clasp/core/hashTable.h | 3 ++ include/clasp/core/weakPointer.h | 3 ++ include/clasp/gctools/gc_boot.h | 1 + include/clasp/gctools/gc_interface.h | 4 ++ include/clasp/gctools/gcweak.h | 8 ++++ src/analysis/clasp_gc.sif | 38 ++++++---------- src/analysis/clasp_gc_cando.sif | 42 +++++++----------- src/gctools/gc_boot.cc | 19 +++++--- src/gctools/gcweak.cc | 23 ++++++++++ src/gctools/memoryManagement.cc | 19 ++++---- src/gctools/obj_scan.cc | 43 ++++++++++++++++--- src/gctools/snapshotSaveLoad.cc | 1 + .../clasp-analyzer/clasp-analyzer.lisp | 17 ++++++++ 13 files changed, 149 insertions(+), 72 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index 16adbd2ccf..e93a5b0a2d 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -128,6 +128,9 @@ class WeakKeyMapping_O final : public Mapping_O { virtual void newEntry(size_t i, T_sp k, T_sp v) { ++_Count; _Mapping.newEntry(i, k, v); } virtual void remove(size_t i) { --_Count; _Mapping.remove(i); } virtual Symbol_sp weakness() { return kw::_sym_key; } + virtual void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) override { + _Mapping.fixupInternalsForSnapshotSaveLoad(fixup); + } }; FORWARD(HashTable); diff --git a/include/clasp/core/weakPointer.h b/include/clasp/core/weakPointer.h index f9e460a987..316367270f 100644 --- a/include/clasp/core/weakPointer.h +++ b/include/clasp/core/weakPointer.h @@ -78,6 +78,9 @@ class Ephemeron_O : public General_O { T_sp key() const; T_sp value() const; bool valid() const; + void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) override { + _ephemeron.fixupInternalsForSnapshotSaveLoad(fixup); + } }; }; // namespace core diff --git a/include/clasp/gctools/gc_boot.h b/include/clasp/gctools/gc_boot.h index 8d4a704792..e53efa962e 100644 --- a/include/clasp/gctools/gc_boot.h +++ b/include/clasp/gctools/gc_boot.h @@ -35,6 +35,7 @@ enum Data_types { ATOMIC_SMART_PTR_OFFSET, TAGGED_POINTER_OFFSET, WEAK_PTR_OFFSET, + EPHEMERON_OFFSET, RAW_POINTER_OFFSET, ARRAY_OFFSET, POINTER_OFFSET, diff --git a/include/clasp/gctools/gc_interface.h b/include/clasp/gctools/gc_interface.h index 0c89f4e453..c5f6abd1c4 100644 --- a/include/clasp/gctools/gc_interface.h +++ b/include/clasp/gctools/gc_interface.h @@ -49,6 +49,10 @@ namespace clbind { class ConstructorCreator_O; class ClassRep_O; }; // namespace clbind +namespace gctools { +class WeakPointer; +class Ephemeron; +}; // namespace gctools ////////////////////////////////////////////////////////////////////// // diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index 504d128b43..c9bdf83973 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -150,6 +150,10 @@ struct Ephemeron { // or else the value could remain while the key dies (memory leak) void setValue(core::T_sp v) { _value = v; } void reinit(core::T_sp k, core::T_sp v); + // Used in obj_scan.cc + KVPair get_no_lock() const; + void reinit_no_lock(core::T_sp k, core::T_sp v); + void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup); public: #ifdef USE_BOEHM GC_hidden_pointer _key; @@ -213,6 +217,10 @@ struct EphemeronMapping { void setValue(size_t i, core::T_sp v) { _Data[i].setValue(v); } void newEntry(size_t i, core::T_sp k, core::T_sp v) { _Data[i].reinit(k, v); } void remove(size_t i) { _Data[i].reinit(deleted(), deleted()); } + void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) { + for (size_t i = 0; i < _Data.length(); ++i) + _Data[i].fixupInternalsForSnapshotSaveLoad(fixup); + } }; }; // namespace gctools diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index a4fdf7e5df..31d46bbf18 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -83,13 +83,13 @@ "comp::SpecialVarInfo_O" "core::SimpleMDArray_int16_t_O" "comp::ControlLabelFixup_O" "llvmo::StructLayout_O" "core::SimpleMDArrayT_O" "core::StrongMapping_O" "llvmo::LoadInst_O" - "llvmo::ConstantStruct_O" "core::Exposer_O" "gctools::Ephemeron" - "core::DirectoryIterator_O" "core::MDArray_byte2_t_O" - "llvmo::DISubroutineType_O" "comp::LabelFixup_O" "comp::Cfunction_O" - "llvmo::MetadataAsValue_O" "core::SimpleBitVector_O" - "core::SimpleVector_int8_t_O" "llvmo::ResumeInst_O" "llvmo::Function_O" - "llvmo::DIType_O" "comp::TagInfo_O" "core::Readtable_O" - "llvmo::IRBuilder_O" "llvmo::ClaspJIT_O" "core::SimpleVector_byte8_t_O" + "llvmo::ConstantStruct_O" "core::Exposer_O" "core::DirectoryIterator_O" + "core::MDArray_byte2_t_O" "llvmo::DISubroutineType_O" + "comp::LabelFixup_O" "comp::Cfunction_O" "llvmo::MetadataAsValue_O" + "core::SimpleBitVector_O" "core::SimpleVector_int8_t_O" + "llvmo::ResumeInst_O" "llvmo::Function_O" "llvmo::DIType_O" + "comp::TagInfo_O" "core::Readtable_O" "llvmo::IRBuilder_O" + "llvmo::ClaspJIT_O" "core::SimpleVector_byte8_t_O" "llvmo::DILexicalBlockBase_O" "llvmo::MDNode_O" "core::ComplexVector_fixnum_O" "mp::RecursiveMutex_O" "core::BytecodeAstIf_O" "core::Vaslist_dummy_O" "core::CoreFun_O" @@ -4702,12 +4702,8 @@ {class-kind :stamp-name "STAMPWTAG_core__Ephemeron_O" :stamp-key "core::Ephemeron_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::Ephemeron_O" - :layout-offset-field-names ("_ephemeron" "._key")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Ephemeron_O" - :layout-offset-field-names ("_ephemeron" "._value")} +{fixed-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" :offset-ctype "gctools::Ephemeron" + :offset-base-ctype "core::Ephemeron_O" :layout-offset-field-names ("_ephemeron")} {class-kind :stamp-name "STAMPWTAG_core__SmallMultimap_O" :stamp-key "core::SmallMultimap_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} @@ -4777,12 +4773,8 @@ {variable-capacity :ctype "gctools::Ephemeron" :offset-base-ctype "core::WeakKeyMapping_O" :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} -{variable-field :offset-type-cxx-identifier "ctype_unsigned_long" - :fixup-ctype-offset-type-key "unsigned long" :fixup-ctype-key "gctools::Ephemeron" - :layout-offset-field-names ("_key")} -{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :fixup-ctype-offset-type-key "gctools::smart_ptr" - :fixup-ctype-key "gctools::Ephemeron" :layout-offset-field-names ("_value")} +{variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-type "gctools::Ephemeron"} {class-kind :stamp-name "STAMPWTAG_core__StrongMapping_O" :stamp-key "core::StrongMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} @@ -6089,12 +6081,8 @@ :offset-base-ctype "gctools::GCArray_moveable" :length-field-names ("_MaybeSignedLength") :end-field-names ("_MaybeSignedLength")} -{variable-field :offset-type-cxx-identifier "ctype_unsigned_long" - :fixup-ctype-offset-type-key "unsigned long" :fixup-ctype-key "gctools::Ephemeron" - :layout-offset-field-names ("_key")} -{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :fixup-ctype-offset-type-key "gctools::smart_ptr" - :fixup-ctype-key "gctools::Ephemeron" :layout-offset-field-names ("_value")} +{variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-type "gctools::Ephemeron"} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_std__pair_gctools__smart_ptr_core__T_O__gctools__smart_ptr_core__T_O___" :stamp-key "gctools::GCVector_moveable,gctools::smart_ptr>>" :parent-class "gctools::GCContainer" :lisp-class-base nil diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index e459cec32f..475f604ba2 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -145,15 +145,15 @@ "chem::Logical_O" "comp::ControlLabelFixup_O" "llvmo::StructLayout_O" "core::SimpleMDArrayT_O" "chem::ConformationExplorer_O" "core::StrongMapping_O" "chem::BondList_O" "llvmo::LoadInst_O" - "core::Exposer_O" "llvmo::ConstantStruct_O" "gctools::Ephemeron" - "chem::MacroModelFile_O" "core::MDArray_byte2_t_O" - "core::DirectoryIterator_O" "chem::Angle_O" "llvmo::DISubroutineType_O" - "chem::EnergyComponents_O" "comp::LabelFixup_O" "comp::Cfunction_O" - "llvmo::MetadataAsValue_O" "kinematics::JumpJoint_O" - "core::SimpleBitVector_O" "core::SimpleVector_int8_t_O" "chem::CDNode_O" - "llvmo::ResumeInst_O" "llvmo::Function_O" "llvmo::DIType_O" - "chem::AddIonOctree_O" "kinematics::StubJoint_O" "chem::ZMatrixEntry_O" - "comp::TagInfo_O" "geom::BoundingCuboid_O" "core::Readtable_O" + "core::Exposer_O" "llvmo::ConstantStruct_O" "chem::MacroModelFile_O" + "core::MDArray_byte2_t_O" "core::DirectoryIterator_O" "chem::Angle_O" + "llvmo::DISubroutineType_O" "chem::EnergyComponents_O" + "comp::LabelFixup_O" "comp::Cfunction_O" "llvmo::MetadataAsValue_O" + "kinematics::JumpJoint_O" "core::SimpleBitVector_O" + "core::SimpleVector_int8_t_O" "chem::CDNode_O" "llvmo::ResumeInst_O" + "llvmo::Function_O" "llvmo::DIType_O" "chem::AddIonOctree_O" + "kinematics::StubJoint_O" "chem::ZMatrixEntry_O" "comp::TagInfo_O" + "geom::BoundingCuboid_O" "core::Readtable_O" "chem::CalculatePositionRelativeToOrigin_O" "chem::AtomIndexer_O" "chem::ChemInfoMatch_O" "chem::Restraint_O" "units::Quantity_O" "llvmo::IRBuilder_O" "chem::AtomPdbRec" "llvmo::ClaspJIT_O" @@ -5858,12 +5858,8 @@ {class-kind :stamp-name "STAMPWTAG_core__Ephemeron_O" :stamp-key "core::Ephemeron_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} -{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" - :offset-base-ctype "core::Ephemeron_O" - :layout-offset-field-names ("_ephemeron" "._key")} -{fixed-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :offset-ctype "gctools::smart_ptr" :offset-base-ctype "core::Ephemeron_O" - :layout-offset-field-names ("_ephemeron" "._value")} +{fixed-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" :offset-ctype "gctools::Ephemeron" + :offset-base-ctype "core::Ephemeron_O" :layout-offset-field-names ("_ephemeron")} {class-kind :stamp-name "STAMPWTAG_comp__VariableCellInfo_O" :stamp-key "comp::VariableCellInfo_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} @@ -9863,12 +9859,8 @@ {variable-capacity :ctype "gctools::Ephemeron" :offset-base-ctype "core::WeakKeyMapping_O" :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} -{variable-field :offset-type-cxx-identifier "ctype_unsigned_long" - :fixup-ctype-offset-type-key "unsigned long" :fixup-ctype-key "gctools::Ephemeron" - :layout-offset-field-names ("_key")} -{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :fixup-ctype-offset-type-key "gctools::smart_ptr" - :fixup-ctype-key "gctools::Ephemeron" :layout-offset-field-names ("_value")} +{variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-type "gctools::Ephemeron"} {class-kind :stamp-name "STAMPWTAG_core__StrongMapping_O" :stamp-key "core::StrongMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} @@ -11658,12 +11650,8 @@ :offset-base-ctype "gctools::GCArray_moveable" :length-field-names ("_MaybeSignedLength") :end-field-names ("_MaybeSignedLength")} -{variable-field :offset-type-cxx-identifier "ctype_unsigned_long" - :fixup-ctype-offset-type-key "unsigned long" :fixup-ctype-key "gctools::Ephemeron" - :layout-offset-field-names ("_key")} -{variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" - :fixup-ctype-offset-type-key "gctools::smart_ptr" - :fixup-ctype-key "gctools::Ephemeron" :layout-offset-field-names ("_value")} +{variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-type "gctools::Ephemeron"} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_chem__EnergyOutOfZPlane_" :stamp-key "gctools::GCVector_moveable" :parent-class "gctools::GCContainer" :lisp-class-base nil diff --git a/src/gctools/gc_boot.cc b/src/gctools/gc_boot.cc index 7e2797fd6d..8e26f1c374 100644 --- a/src/gctools/gc_boot.cc +++ b/src/gctools/gc_boot.cc @@ -159,7 +159,8 @@ void walk_stamp_field_layout_tables(WalkKind walk, std::ostream& fout) { } } else if ((codes[idx].cmd == fixed_field || codes[idx].cmd == variable_field) && (codes[idx].data0 == SMART_PTR_OFFSET || codes[idx].data0 == ATOMIC_SMART_PTR_OFFSET || - codes[idx].data0 == TAGGED_POINTER_OFFSET || codes[idx].data0 == POINTER_OFFSET)) { + codes[idx].data0 == TAGGED_POINTER_OFFSET || codes[idx].data0 == POINTER_OFFSET + || codes[idx].data0 == WEAK_PTR_OFFSET || codes[idx].data0 == EPHEMERON_OFFSET)) { ++number_of_fixable_fields; } else if ((codes[idx].cmd == fixed_field) && (codes[idx].data0 == CONSTANT_ARRAY_OFFSET)) { // Ignore the Array_O size_t _Length[0] array @@ -249,13 +250,14 @@ void walk_stamp_field_layout_tables(WalkKind walk, std::ostream& fout) { if ((data_type == SMART_PTR_OFFSET || data_type == ATOMIC_SMART_PTR_OFFSET || data_type == TAGGED_POINTER_OFFSET || data_type == POINTER_OFFSET - || data_type == WEAK_PTR_OFFSET)) { + || data_type == WEAK_PTR_OFFSET || data_type == EPHEMERON_OFFSET)) { GCTOOLS_ASSERT(cur_field_layout < max_field_layout); #ifdef USE_PRECISE_GC int bit_index; uintptr_t field_bitmap; bit_index = bitmap_field_index(63, field_offset); - if (data_type == WEAK_PTR_OFFSET || bit_index == -1) { + if (data_type == WEAK_PTR_OFFSET || data_type == EPHEMERON_OFFSET + || bit_index == -1) { // We have a field we need to fix that is beyond the range of a bitmap. // Flag this class to tell the scanner to use the field layouts instead. // Alternately we have a weak reference that needs to be @@ -381,11 +383,18 @@ void walk_stamp_field_layout_tables(WalkKind walk, std::ostream& fout) { local_stamp_layout[cur_stamp].snapshot_save_load_poison++; } if (((data_type) == SMART_PTR_OFFSET || (data_type) == ATOMIC_SMART_PTR_OFFSET || (data_type) == TAGGED_POINTER_OFFSET || - (data_type) == POINTER_OFFSET)) { + (data_type) == POINTER_OFFSET + || data_type == WEAK_PTR_OFFSET || data_type == EPHEMERON_OFFSET)) { int bit_index = bitmap_field_index(63, field_offset); uintptr_t field_bitmap = bitmap_field_bitmap(bit_index); GCTOOLS_ASSERT(cur_field_layout < max_field_layout); - local_stamp_layout[cur_stamp].container_layout->container_field_pointer_bitmap |= field_bitmap; + if (data_type == WEAK_PTR_OFFSET || data_type == EPHEMERON_OFFSET + || bit_index == -1) { + local_stamp_layout[cur_stamp].flags |= COMPLEX_SCAN; + } else { + uintptr_t field_bitmap = bitmap_field_bitmap(bit_index); + local_stamp_layout[cur_stamp].container_layout->container_field_pointer_bitmap |= field_bitmap; + } local_stamp_layout[cur_stamp].container_layout->container_field_pointer_count++; DGC_PRINT("%s:%d variable_field %s cur_stamp = %d field_offset = %lu field_bit_index = %d field_bitmap = 0x%lX\n", __FILE__, __LINE__, field_name, cur_stamp, field_offset, bit_index, field_bitmap); diff --git a/src/gctools/gcweak.cc b/src/gctools/gcweak.cc index a9def91fa5..c9226f069d 100644 --- a/src/gctools/gcweak.cc +++ b/src/gctools/gcweak.cc @@ -140,14 +140,37 @@ KVPair Ephemeron::get() const { GC_call_with_alloc_lock(get_helper, &rhs); return rhs.result; } + +KVPair Ephemeron::get_no_lock() const { + return KVPair(core::T_sp((Tagged)GC_REVEAL_POINTER(_key)), _value); +} +void Ephemeron::reinit_no_lock(core::T_sp k, core::T_sp v) { + _key = GC_HIDE_POINTER(k.tagged_()); + _value = v; +} +void Ephemeron::fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) { + if (snapshotSaveLoad::operation(fixup) == snapshotSaveLoad::LoadOp) { + core::T_sp k((Tagged)GC_REVEAL_POINTER(_key)); + if (k.objectp()) { + GC_general_register_disappearing_link((void**)&_key, &*k); + GC_general_register_disappearing_link((void**)&_value, &*k); + } else { + GC_unregister_disappearing_link((void**)&_key); + GC_unregister_disappearing_link((void**)&_value); + } + } +} #else // not-actually-weak ephemeron default - FIXME for your GC! Ephemeron::Ephemeron(core::T_sp key, core::T_sp value) : _key(key), _value(value) {} void Ephemeron::reinit(core::T_sp k, core::T_sp v) { _key = k; _value = v; } +void Ephemeron::reinit_no_lock(core::T_sp k, core::T_sp v) { reinit(k, v); } KVPair Ephemeron::get() const { return KVPair(_key, _value); } +KVPair Ephemeron::get_no_lock() const { return get(); } +void Ephemeron::fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup*) {} #endif // Clang says this definition has to be out-of-line. Sure whatever. diff --git a/src/gctools/memoryManagement.cc b/src/gctools/memoryManagement.cc index db44719181..40826f99a2 100644 --- a/src/gctools/memoryManagement.cc +++ b/src/gctools/memoryManagement.cc @@ -872,12 +872,13 @@ void walkRoots(RootWalkCallback&& callback) { // #define HEADER_PTR_TO_GENERAL_PTR(_header_) headerPointerToGeneralPointer((gctools::Header_s*)_header_) #define ADDR_T uintptr_t -#define EXTRA_ARGUMENTS , std::stack& markStack +#define EXTRA_ARGUMENTS , std::stack& markStack -#define POINTER_FIX(_ptr_) markStack.push(reinterpret_cast(_ptr_)) +#define POINTER_FIX(_ptr_) markStack.push(*reinterpret_cast(_ptr_)) #define OBJECT_SCAN mw_obj_scan #define OBJECT_SKIP mw_obj_skip +#define EPHEMERON_FIX(a, b) #include "obj_scan.cc" #undef OBJECT_SKIP #undef OBJECT_SCAN @@ -895,13 +896,12 @@ void walkRoots(RootWalkCallback&& callback) { template static void mapAllObjectsInternal(std::set& markSet, Callback callback) { - std::stack markStack; + std::stack markStack; - walkRoots([&](Tagged* rootf) { markStack.push(rootf); }); // process all roots + walkRoots([&](Tagged* rootf) { markStack.push(*rootf); }); // process all roots while (!markStack.empty()) { - Tagged* field = markStack.top(); markStack.pop(); // pop a field - Tagged tagged = *field; + Tagged tagged = markStack.top(); markStack.pop(); // pop a pointer switch(ptag(tagged)) { case general_tag: { // general object @@ -946,17 +946,16 @@ std::set setOfAllObjects() { // important for snapshot save. // Return the set of tagged pointers located in fields that are not valid. std::set memtest(std::set& dladdrFailed) { - std::stack markStack; + std::stack markStack; std::set markSet; std::set corrupt; std::set uniqueEntryPoints; - walkRoots([&](Tagged* rootAddr) { markStack.push(rootAddr); }); + walkRoots([&](Tagged* rootAddr) { markStack.push(*rootAddr); }); while (!markStack.empty()) { - Tagged* field = markStack.top(); markStack.pop(); - gctools::Tagged tagged = *field; + Tagged tagged = markStack.top(); markStack.pop(); switch (tagged & ptag_mask) { case general_tag: { diff --git a/src/gctools/obj_scan.cc b/src/gctools/obj_scan.cc index 185478db29..0e9ce5168e 100644 --- a/src/gctools/obj_scan.cc +++ b/src/gctools/obj_scan.cc @@ -8,9 +8,15 @@ #define ADDR_T mps_addr_t // Type of addresses #define OBJECT_SCAN fixup_objects // Name of function #define POINTER_FIX(field) // Macro to fix pointer at field -#define WEAK_POINTER_FIX(field) // Macro for a weak ptr - ok to leave undefined #define OBJECT_SCAN // Macro to turn on #ifdef inclusion of code #define CLIENT_PTR_TO_HEADER_PTR(client) // Replace with function to get base pointer from client + * Macros for weak pointers and ephemerons. + * If left undefined, weak pointers are ignored and ephemerons have their + * values scanned. HOWEVER this is done using temporary, fake "field" + * pointers as the weak ptrs/ephemerons may not actually contain a T_O**. + * SO make sure you don't try to store those pointers for later! +#define WEAK_POINTER_FIX(field) +#define EPHEMERON_FIX(key, value) */ // !!!!! DEBUG_OBJECT_SCAN can only be on when DEBUG_GUARD_VALIDATE is on!!!!!! @@ -26,6 +32,10 @@ #ifdef OBJECT_SCAN +#ifndef EPHEMERON_FIX +#define EPHEMERON_FIX(key, value) POINTER_FIX(value) +#endif + ADDR_T OBJECT_SCAN(ADDR_T client EXTRA_ARGUMENTS) { size_t stamp_index; @@ -68,12 +78,24 @@ ADDR_T OBJECT_SCAN(ADDR_T client EXTRA_ARGUMENTS) { core::T_O* raw = v->raw_(); WEAK_POINTER_FIX(&raw); // Store it back in the weak pointer - this is needed for when the - // object scanner is used in image save as it needs to alter - // pointers. + // object scanner is used in image save/load as it needs to + // alter pointers. + // Do not change the pointer outside of image save/load. weak->store_no_lock(core::T_sp((gctools::Tagged)raw)); } #endif - } else { + } else if (field_info_cur->data_type == gctools::EPHEMERON_OFFSET) [[unlikely]] { + gctools::Ephemeron* eph = (gctools::Ephemeron*)((const char*)client + field_layout_cur->field_offset); + auto kv = eph->get_no_lock(); + if (!kv.key.deletedp()) { + core::T_O* rkey = kv.key.raw_(); + core::T_O* rval = kv.value.raw_(); + EPHEMERON_FIX(&rkey, &rval); + // See comment on weak pointers above. + eph->reinit_no_lock(core::T_sp((gctools::Tagged)rkey), + core::T_sp((gctools::Tagged)rval)); + } + } else [[likely]] { core::T_O** field = (core::T_O**)((const char*)client + field_layout_cur->field_offset); POINTER_FIX(field); } @@ -140,7 +162,18 @@ ADDR_T OBJECT_SCAN(ADDR_T client EXTRA_ARGUMENTS) { weak->store_no_lock(core::T_sp((gctools::Tagged)raw)); } #endif - } else { + } else if (field_info->data_type == gctools::EPHEMERON_OFFSET) [[unlikely]] { + gctools::Ephemeron* eph = (gctools::Ephemeron*)field; + auto kv = eph->get_no_lock(); + if (!kv.key.deletedp()) { + core::T_O* rkey = kv.key.raw_(); + core::T_O* rval = kv.value.raw_(); + EPHEMERON_FIX(&rkey, &rval); + // See comment on weak pointers above. + eph->reinit_no_lock(core::T_sp((gctools::Tagged)rkey), + core::T_sp((gctools::Tagged)rval)); + } + } else [[likely]] { core::T_O** tfield = (core::T_O**)field; POINTER_FIX(tfield); } diff --git a/src/gctools/snapshotSaveLoad.cc b/src/gctools/snapshotSaveLoad.cc index fe568d1a09..aabb40ae15 100644 --- a/src/gctools/snapshotSaveLoad.cc +++ b/src/gctools/snapshotSaveLoad.cc @@ -1098,6 +1098,7 @@ gctools::clasp_ptr_t maybe_follow_forwarding_pointer(gctools::clasp_ptr_t* clien }; \ } #define WEAK_POINTER_FIX(_ptr_) POINTER_FIX(_ptr_) +#define EPHEMERON_FIX(key, val) do { POINTER_FIX(key); POINTER_FIX(val); } while (false) #define ADDR_T gctools::clasp_ptr_t #define EXTRA_ARGUMENTS , void* user_data diff --git a/src/lisp/modules/clasp-analyzer/clasp-analyzer.lisp b/src/lisp/modules/clasp-analyzer/clasp-analyzer.lisp index b58f7dfeeb..2ea0f965d9 100644 --- a/src/lisp/modules/clasp-analyzer/clasp-analyzer.lisp +++ b/src/lisp/modules/clasp-analyzer/clasp-analyzer.lisp @@ -413,6 +413,7 @@ This could change the value of stamps for specific classes - but that would brea specializer) (defstruct (weak-ptr-ctype (:include ctype))) +(defstruct (ephemeron-ctype (:include ctype))) (defstruct (pointer-ctype (:include ctype)) pointee) @@ -516,6 +517,8 @@ This could change the value of stamps for specific classes - but that would brea (defclass weak-ptr-offset (copyable-offset) ()) +(defclass ephemeron-offset (copyable-offset) + ()) (defclass pointer-offset (copyable-offset) ()) @@ -952,6 +955,9 @@ to expose to C++. (defmethod linearize-class-layout-impl ((x weak-ptr-ctype) base analysis) (declare (ignore analysis)) (list (make-instance 'weak-ptr-offset :base base :offset-type x))) +(defmethod linearize-class-layout-impl ((x ephemeron-ctype) base analysis) + (declare (ignore analysis)) + (list (make-instance 'ephemeron-offset :base base :offset-type x))) (defun linearize-constant-array-contents (array element-type elements) "* Arguments @@ -1209,6 +1215,8 @@ can be saved and reloaded within the project for later analysis" (make-shared-mutex-ctype :key decl-key :name name)) ((string= name "WeakPointer") (make-weak-ptr-ctype :key decl-key)) + ((string= name "Ephemeron") + (make-ephemeron-ctype :key decl-key)) (t (make-cxxrecord-ctype :key decl-key :name name)))) (cast:record-decl (warn "classify-decl found ~a decl-key: ~a name: ~a - this means that the mostDerivedType code isn't working!!!!" (type-of decl) decl-key name) @@ -1890,6 +1898,9 @@ so that they don't have to be constantly recalculated" (defmethod contains-fixptr-impl-p ((x weak-ptr-ctype) project) (declare (ignore project)) t) +(defmethod contains-fixptr-impl-p ((x ephemeron-ctype) project) + (declare (ignore project)) + t) (defmethod contains-fixptr-impl-p ((x pointer-ctype) project) (cond ((container-p (pointer-ctype-pointee x)) t) @@ -1940,6 +1951,9 @@ so that they don't have to be constantly recalculated" (defmethod expand-forwards-with-template-arguments ((forwards t) (alloc-ctype weak-ptr-ctype)) nil) +(defmethod expand-forwards-with-template-arguments + ((forwards t) (alloc-ctype ephemeron-ctype)) + nil) (defmethod expand-forwards-with-template-arguments (forwards (alloc-ctype cxxrecord-ctype)) (add-ctype forwards (ctype-key alloc-ctype) alloc-ctype)) (defmethod expand-forwards-with-template-arguments (forwards (alloc-ctype pointer-ctype)) @@ -2451,6 +2465,9 @@ Recursively analyze x and return T if x contains fixable pointers." (defmethod fixable-instance-variables-impl ((x weak-ptr-ctype) analysis) (declare (ignore analysis)) :weak-ptr-fix) +(defmethod fixable-instance-variables-impl ((x ephemeron-ctype) analysis) + (declare (ignore analysis)) + :ephemeron-fix) (defmethod fixable-instance-variables-impl ((x constant-array-ctype) analysis) (when (contains-fixptr-p x (analysis-project analysis)) From 027f85f8bf5221fd80f60d99fd2eae24040099c3 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 21 Jan 2025 13:11:42 -0500 Subject: [PATCH 33/39] Grab hash value simultaneously with index Saves us a dumb lookup (in find) and will be nice for keeping the value alive when doing weak tables. --- include/clasp/core/hashTable.h | 8 +++++++- src/core/hashTable.cc | 11 ++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index e93a5b0a2d..aa79f06b04 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -26,6 +26,8 @@ THE SOFTWARE. */ /* -^- */ +#include // pair +#include #include #include #include @@ -182,7 +184,11 @@ class HashTable_O : public General_O { T_sp setf_gethash_no_write_lock(T_sp key, T_sp value); gc::Fixnum sxhashKey(T_sp key) const; // NOTE: Only call with (read) lock held - std::optional searchTable_no_read_lock(T_sp key, cl_index index); + // Returns a pair of the index and the value at that index. + // This lets us gethash without a double lookup, and also lets us keep the + // value alive, which can be important for weak tables. + std::optional> + searchTable_no_read_lock(T_sp key, cl_index index); inline size_t count_no_lock() const { return _Table->count(); } diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index c9cc1a1cdc..03ed3973b8 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -462,7 +462,8 @@ CL_DEFUN T_mv core__gethash3(T_sp key, T_sp hashTable, T_sp default_value) { return ht->gethash(key, default_value); }; -__attribute__((optnone)) std::optional HashTable_O::searchTable_no_read_lock(T_sp key, cl_index index) { +std::optional> +HashTable_O::searchTable_no_read_lock(T_sp key, cl_index index) { size_t tableSize = this->_Table->size(); size_t cur = index; do { @@ -470,7 +471,7 @@ __attribute__((optnone)) std::optional HashTable_O::searchTable_no_read_ if (pair.key.no_keyp()) break; if (!pair.key.deletedp()) { if (keyTest(pair.key, key)) - return cur; + return std::pair(cur, pair.value); } cur = (cur + 1) % tableSize; } while (cur != index); // loop over the whole table if necessary @@ -501,7 +502,7 @@ std::optional HashTable_O::find(T_sp key) { cl_index index = this->sxhashKey(key); auto found = this->searchTable_no_read_lock(key, index); if (!found) return std::nullopt; - else return this->_Table->get(*found).value; + else return found->second; } bool HashTable_O::contains(T_sp key) { @@ -513,7 +514,7 @@ bool HashTable_O::remhash(T_sp key) { cl_index index = this->sxhashKey(key); auto found = this->searchTable_no_read_lock(key, index); if (found) { - _Table->remove(*found); + _Table->remove(found->first); return true; } return false; @@ -532,7 +533,7 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { auto found = this->searchTable_no_read_lock(key, index); if (found) { // rewrite value - _Table->setValue(*found, value); + _Table->setValue(found->first, value); return value; } size_t write; From a81014b052a8e6334fd673b8c833bc2ea5346e79 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 21 Jan 2025 14:47:30 -0500 Subject: [PATCH 34/39] Add weak-value hash tables --- include/clasp/core/hashTable.h | 51 +++++++++++++++++++++++++++++++-- src/analysis/clasp_gc.sif | 37 ++++++++++++++++-------- src/analysis/clasp_gc_cando.sif | 26 ++++++++++++----- src/core/hashTable.cc | 10 +++++-- 4 files changed, 100 insertions(+), 24 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index aa79f06b04..b08c311137 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -68,7 +68,9 @@ class Mapping_O : public General_O { size_t countInexact() const { return _Count; } virtual Mapping_sp realloc(size_t) const = 0; virtual gctools::KVPair get(size_t) const = 0; - virtual void setValue(size_t, T_sp) = 0; + // This accepts both the key and value as arguments for the sake of making + // weak value mappings easier - see below. + virtual void setValue(size_t, T_sp, T_sp) = 0; virtual void newEntry(size_t, T_sp, T_sp) = 0; virtual void remove(size_t) = 0; virtual Symbol_sp weakness() = 0; @@ -98,7 +100,7 @@ class StrongMapping_O final : public Mapping_O { virtual size_t count() const { return _Count; } virtual Mapping_sp realloc(size_t sz) const { return make(sz); } virtual gctools::KVPair get(size_t i) const { return _Mapping.get(i); } - virtual void setValue(size_t i, T_sp v) { _Mapping.setValue(i, v); } + virtual void setValue(size_t i, T_sp, T_sp v) { _Mapping.setValue(i, v); } virtual void newEntry(size_t i, T_sp k, T_sp v) { _Mapping.newEntry(i, k, v); _Count++; @@ -126,7 +128,7 @@ class WeakKeyMapping_O final : public Mapping_O { virtual size_t count() const { return computeCount(); } virtual Mapping_sp realloc(size_t sz) const { return make(sz); } virtual gctools::KVPair get(size_t i) const { return _Mapping.get(i); } - virtual void setValue(size_t i, T_sp v) { _Mapping.setValue(i, v); } + virtual void setValue(size_t i, T_sp, T_sp v) { _Mapping.setValue(i, v); } virtual void newEntry(size_t i, T_sp k, T_sp v) { ++_Count; _Mapping.newEntry(i, k, v); } virtual void remove(size_t i) { --_Count; _Mapping.remove(i); } virtual Symbol_sp weakness() { return kw::_sym_key; } @@ -135,6 +137,49 @@ class WeakKeyMapping_O final : public Mapping_O { } }; +FORWARD(WeakValueMapping); +class WeakValueMapping_O final : public Mapping_O { + LISP_CLASS(core, CorePkg, WeakValueMapping_O, "WeakValueMapping", Mapping_O); +public: + // need typedefs for e.g. sizeof_container + typedef gctools::EphemeronMapping::value_type value_type; +public: + WeakValueMapping_O(size_t size) : _Mapping(size) {} + static WeakValueMapping_sp make(size_t); +public: + // We use the same mapping underneath, but its keys are the table's values + // and its values are the table's keys. + gctools::EphemeronMapping _Mapping; +public: + virtual size_t size() const { return _Mapping.size(); } + virtual size_t count() const { return computeCount(); } + virtual Mapping_sp realloc(size_t sz) const { return make(sz); } + virtual gctools::KVPair get(size_t i) const { + auto p = _Mapping.get(i); + return gctools::KVPair(p.value, p.key); + } + virtual void setValue(size_t i, T_sp k, T_sp v) { + // GC note: I think we don't have to go out of our way to keep the old + // value alive here, because we're replacing the whole ephemeron anyway. + // There will be a problem from the following sequence of events: + // 1) thread A arrives here (just before the newEntry call) + // 2) the GC deletes the ephemeron + // 3) thread B does (setf gethash) on the same hash table + // and decides to use the ephemeron space at this index + // 4) thread A resumes and newEntry's, erasing thread B's work + // However our hash tables are not thread safe anyway, so anybody working + // on the same table from multiple thrads will avoid this by using + // synchronized hash tables. + _Mapping.newEntry(i, v, k); + } + virtual void newEntry(size_t i, T_sp k, T_sp v) { ++_Count; _Mapping.newEntry(i, v, k); } + virtual void remove(size_t i) { --_Count; _Mapping.remove(i); } + virtual Symbol_sp weakness() { return kw::_sym_value; } + virtual void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) override { + _Mapping.fixupInternalsForSnapshotSaveLoad(fixup); + } +}; + FORWARD(HashTable); class HashTable_O : public General_O { LISP_CLASS(core, ClPkg, HashTable_O, "HashTable", General_O); diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index 31d46bbf18..eb03cd1b4b 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -2,18 +2,19 @@ "core::SimpleMDArray_fixnum_O" "core::ComplexVector_O" "core::SimpleMDArray_int32_t_O" "core::Integer_O" "clbind::ClassRegistry_O" "mp::Process_O" "core::Record_O" - "core::LightUserData_O" "core::MDArrayT_O" "core::FunctionCell_O" - "core::DirectoryEntry_O" "llvmo::Linker_O" "comp::FunInfo_O" - "core::MDArray_float_O" "core::SourcePosInfo_O" "llvmo::BranchInst_O" - "llvmo::AllocaInst_O" "core::StandardClassCreator_O" - "core::ComplexVector_float_O" "core::HashTableCustom_O" - "comp::LexicalVarInfo_O" "core::ComplexVector_byte8_t_O" - "core::OptionalArgument" "comp::FunctionCellInfo_O" "core::HashTable_O" - "core::SimpleCoreFun_O" "core::SimpleVector_size_t_O" "llvmo::DIScope_O" - "core::FileStatus_O" "llvmo::IndirectBrInst_O" "llvmo::ConstantArray_O" - "llvmo::PHINode_O" "core::Package_O" "core::SimpleMDArrayBaseChar_O" - "llvmo::DILocation_O" "llvmo::DWARFUnit_O" "core::SimpleMDArray_O" - "core::Stream_O" "core::VMFrameDynEnv_O" "core::SymbolClassHolderPair" + "core::LightUserData_O" "core::MDArrayT_O" "core::WeakValueMapping_O" + "core::FunctionCell_O" "core::DirectoryEntry_O" "llvmo::Linker_O" + "comp::FunInfo_O" "core::MDArray_float_O" "core::SourcePosInfo_O" + "llvmo::BranchInst_O" "llvmo::AllocaInst_O" + "core::StandardClassCreator_O" "core::ComplexVector_float_O" + "core::HashTableCustom_O" "comp::LexicalVarInfo_O" + "core::ComplexVector_byte8_t_O" "core::OptionalArgument" + "comp::FunctionCellInfo_O" "core::HashTable_O" "core::SimpleCoreFun_O" + "core::SimpleVector_size_t_O" "llvmo::DIScope_O" "core::FileStatus_O" + "llvmo::IndirectBrInst_O" "llvmo::ConstantArray_O" "llvmo::PHINode_O" + "core::Package_O" "core::SimpleMDArrayBaseChar_O" "llvmo::DILocation_O" + "llvmo::DWARFUnit_O" "core::SimpleMDArray_O" "core::Stream_O" + "core::VMFrameDynEnv_O" "core::SymbolClassHolderPair" "comp::EncageFixup_O" "llvmo::MDString_O" "core::ShortFloat_O" "core::Number_O" "core::T_O" "llvmo::DICompileUnit_O" "core::BindingDynEnv_O" "core::AbstractSimpleVector_O" @@ -4791,6 +4792,18 @@ {variable-field :offset-type-cxx-identifier "SMART_PTR_OFFSET" :fixup-ctype-offset-type-key "gctools::smart_ptr" :fixup-ctype-key "gctools::KVPair" :layout-offset-field-names ("value")} +{class-kind :stamp-name "STAMPWTAG_core__WeakValueMapping_O" :stamp-key "core::WeakValueMapping_O" + :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakValueMapping_O" :layout-offset-field-names ("_Count")} +{variable-array0 :offset-base-ctype "core::WeakValueMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::Ephemeron" :offset-base-ctype "core::WeakValueMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-type "gctools::Ephemeron"} {class-kind :stamp-name "STAMPWTAG_core__RandomState_O" :stamp-key "core::RandomState_O" :parent-class "core::General_O" :lisp-class-base "core::General_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index 475f604ba2..db13448593 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -5,13 +5,13 @@ "core::SimpleMDArray_int32_t_O" "core::Integer_O" "chem::SparseLargeSquareMatrix_O" "clbind::ClassRegistry_O" "mp::Process_O" "core::Record_O" "core::LightUserData_O" - "core::MDArrayT_O" "core::FunctionCell_O" "core::DirectoryEntry_O" - "chem::Atom_O" "llvmo::Linker_O" "chem::Kmeans_O" "comp::FunInfo_O" - "chem::ZMatrix_O" "core::MDArray_float_O" "chem::KmeansPlusPlus_O" - "core::SourcePosInfo_O" "llvmo::BranchInst_O" "chem::IterateMatter_O" - "llvmo::AllocaInst_O" "chem::AtomicInfo" "chem::FFTypesDb_O" - "core::ComplexVector_float_O" "core::StandardClassCreator_O" - "chem::Alias_O" "comp::LexicalVarInfo_O" + "core::MDArrayT_O" "core::WeakValueMapping_O" "core::FunctionCell_O" + "core::DirectoryEntry_O" "chem::Atom_O" "llvmo::Linker_O" + "chem::Kmeans_O" "comp::FunInfo_O" "chem::ZMatrix_O" + "core::MDArray_float_O" "chem::KmeansPlusPlus_O" "core::SourcePosInfo_O" + "llvmo::BranchInst_O" "chem::IterateMatter_O" "llvmo::AllocaInst_O" + "chem::AtomicInfo" "chem::FFTypesDb_O" "core::ComplexVector_float_O" + "core::StandardClassCreator_O" "chem::Alias_O" "comp::LexicalVarInfo_O" "chem::MapOfMonomerNamesToAtomIndexers_O" "chem::ZMatrixInternal_O" "core::HashTableCustom_O" "adapt::SymbolSet_O" "chem::Minimizer_O" "core::ComplexVector_byte8_t_O" "core::OptionalArgument" @@ -9861,6 +9861,18 @@ :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} {variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" :fixup-type "gctools::Ephemeron"} +{class-kind :stamp-name "STAMPWTAG_core__WeakValueMapping_O" :stamp-key "core::WeakValueMapping_O" + :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" + :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakValueMapping_O" :layout-offset-field-names ("_Count")} +{variable-array0 :offset-base-ctype "core::WeakValueMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::Ephemeron" :offset-base-ctype "core::WeakValueMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-type "gctools::Ephemeron"} {class-kind :stamp-name "STAMPWTAG_core__StrongMapping_O" :stamp-key "core::StrongMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index 03ed3973b8..d2fe1242dc 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -96,6 +96,10 @@ WeakKeyMapping_sp WeakKeyMapping_O::make(size_t size) { return gctools::GC::allocate_container(false, size); } +WeakValueMapping_sp WeakValueMapping_O::make(size_t size) { + return gctools::GC::allocate_container(false, size); +} + std::atomic global_next_hash_table_id; size_t next_hash_table_id() { return global_next_hash_table_id++; } @@ -178,8 +182,10 @@ CL_DEFUN T_sp cl__make_hash_table(T_sp test, Fixnum_sp size, Number_sp rehash_si mapping = StrongMapping_O::make(isize); else if (weakness == kw::_sym_key) mapping = WeakKeyMapping_O::make(isize); + else if (weakness == kw::_sym_value) + mapping = WeakValueMapping_O::make(isize); else - SIMPLE_ERROR("Only :weakness :key (weak-key hash tables) are currently supported"); + SIMPLE_ERROR("Only :weakness :key :value (weak-key or weak-value hash tables) are currently supported"); // clamped by the constructor. double rehash_threshold = clasp_to_double(orehash_threshold); @@ -533,7 +539,7 @@ T_sp HashTable_O::setf_gethash_no_write_lock(T_sp key, T_sp value) { auto found = this->searchTable_no_read_lock(key, index); if (found) { // rewrite value - _Table->setValue(found->first, value); + _Table->setValue(found->first, key, value); return value; } size_t write; From 721ab44700ddb554eb5175d897422ec89b51c475 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 21 Jan 2025 19:43:05 -0500 Subject: [PATCH 35/39] Add weak key-and-value hash tables --- include/clasp/core/hashTable.h | 32 +++++++++++++++++++ include/clasp/gctools/gcweak.h | 49 ++++++++++++++++++++++++++++++ src/analysis/clasp_gc.sif | 39 ++++++++++++++++++++++-- src/analysis/clasp_gc_cando.sif | 54 +++++++++++++++++++++++++++------ src/core/hashTable.cc | 6 ++++ src/core/keywordPackage.cc | 1 + src/gctools/gcweak.cc | 14 +++++++++ 7 files changed, 184 insertions(+), 11 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index b08c311137..d9c4073004 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -46,6 +46,13 @@ size_t next_hash_table_id(); }; // namespace core +template <> struct gctools::GCInfo { + static bool const NeedsInitialization = false; + static bool const NeedsFinalization = false; + // Required to make it weak. + static GCInfo_policy constexpr Policy = atomic; +}; + namespace core { FORWARD(Mapping); @@ -180,6 +187,31 @@ class WeakValueMapping_O final : public Mapping_O { } }; +FORWARD(WeakKeyAndValueMapping); +class WeakKeyAndValueMapping_O final : public Mapping_O { + LISP_CLASS(core, CorePkg, WeakKeyAndValueMapping_O, "WeakKeyAndValueMapping", Mapping_O); +public: + // need typedefs for e.g. sizeof_container + typedef gctools::WeakAndMapping::value_type value_type; +public: + WeakKeyAndValueMapping_O(size_t size) : _Mapping(size) {} + static WeakKeyAndValueMapping_sp make(size_t); +public: + gctools::WeakAndMapping _Mapping; +public: + virtual size_t size() const { return _Mapping.size(); } + virtual size_t count() const { return computeCount(); } + virtual Mapping_sp realloc(size_t sz) const { return make(sz); } + virtual gctools::KVPair get(size_t i) const { return _Mapping.get(i); } + virtual void setValue(size_t i, T_sp, T_sp v) { _Mapping.setValue(i, v); } + virtual void newEntry(size_t i, T_sp k, T_sp v) { ++_Count; _Mapping.newEntry(i, k, v); } + virtual void remove(size_t i) { --_Count; _Mapping.remove(i); } + virtual Symbol_sp weakness() { return kw::_sym_key_and_value; } + virtual void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) override { + _Mapping.fixupInternalsForSnapshotSaveLoad(fixup); + } +}; + FORWARD(HashTable); class HashTable_O : public General_O { LISP_CLASS(core, ClPkg, HashTable_O, "HashTable", General_O); diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index c9bdf83973..8a71bf9e21 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -87,6 +87,7 @@ struct WeakPointer { std::optional value() const; std::optional value_no_lock() const; // used by scanner void store_no_lock(core::T_sp); // ditto. + void store(core::T_sp); void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup*); public: // has to be public for precise GC reasons even though it's not scanned? // This is a Tagged rather than a T_sp because something in gc_boot seems to @@ -223,4 +224,52 @@ struct EphemeronMapping { } }; +// For weak key-and-value tables: an entry is only alive as long as +// both the key AND the value are otherwise alive. +// Boehm only allows any given memory address to be zeroed when one object +// dies, so we can't directly zero the whole pair. But using weak pointers +// is enough. Note that this means the WeakAndMapping needs to be allocated +// with atomic policy, like WeakPointer_O. +struct WeakAnd { + WeakPointer key; + WeakPointer value; + WeakAnd(core::T_sp k, core::T_sp v) : key(k), value(v) {} + KVPair get() const { + auto k = key.value(); + auto v = value.value(); + if (k && v) return KVPair(*k, *v); + else return KVPair(deleted(), deleted()); + } + void setValue(core::T_sp v) { value.store(v); } + void reinit(core::T_sp k, core::T_sp v) { + key.store(k); value.store(v); + } + void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) { + key.fixupInternalsForSnapshotSaveLoad(fixup); + value.fixupInternalsForSnapshotSaveLoad(fixup); + } +}; + +struct WeakAndMapping { +public: + typedef GCArray_moveable vector_type; + typedef typename vector_type::value_type value_type; +private: + static const WeakAnd initKV; +public: + WeakAndMapping(size_t size) : _Data(size, initKV) {} +public: + vector_type _Data; +public: + size_t size() const { return _Data.length(); } + KVPair get(size_t i) const { return _Data[i].get(); } + void setValue(size_t i, core::T_sp v) { _Data[i].setValue(v); } + void newEntry(size_t i, core::T_sp k, core::T_sp v) { _Data[i].reinit(k, v); } + void remove(size_t i) { _Data[i].reinit(deleted(), deleted()); } + void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) { + for (size_t i = 0; i < _Data.length(); ++i) + _Data[i].fixupInternalsForSnapshotSaveLoad(fixup); + } +}; + }; // namespace gctools diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index eb03cd1b4b..d2cb2c122d 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -84,7 +84,8 @@ "comp::SpecialVarInfo_O" "core::SimpleMDArray_int16_t_O" "comp::ControlLabelFixup_O" "llvmo::StructLayout_O" "core::SimpleMDArrayT_O" "core::StrongMapping_O" "llvmo::LoadInst_O" - "llvmo::ConstantStruct_O" "core::Exposer_O" "core::DirectoryIterator_O" + "llvmo::ConstantStruct_O" "core::Exposer_O" + "core::WeakKeyAndValueMapping_O" "core::DirectoryIterator_O" "core::MDArray_byte2_t_O" "llvmo::DISubroutineType_O" "comp::LabelFixup_O" "comp::Cfunction_O" "llvmo::MetadataAsValue_O" "core::SimpleBitVector_O" "core::SimpleVector_int8_t_O" @@ -101,7 +102,7 @@ "llvmo::DIFile_O" "llvmo::LineTable_O" "llvmo::DataLayout_O" "llvmo::BasicBlock_O" "llvmo::CodeBase_O" "core::SimpleMDArray_int8_t_O" "llvmo::EngineBuilder_O" "core::ComplexVector_byte64_t_O" - "llvmo::SectionedAddress_O" "core::MDArray_byte32_t_O" + "llvmo::SectionedAddress_O" "core::MDArray_byte32_t_O" "gctools::WeakAnd" "core::Character_dummy_O" "core::PosixFileStream_O" "comp::LexRefFixup_O" "llvmo::Constant_O" "llvmo::FunctionCallee_O" "llvmo::DIBasicType_O" "llvmo::DIBuilder_O" "core::NativeVector_int_O" "llvmo::APInt_O" @@ -4776,6 +4777,24 @@ :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} {variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" :fixup-type "gctools::Ephemeron"} +{class-kind :stamp-name "STAMPWTAG_core__WeakKeyAndValueMapping_O" + :stamp-key "core::WeakKeyAndValueMapping_O" :parent-class "core::Mapping_O" + :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 + :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakKeyAndValueMapping_O" + :layout-offset-field-names ("_Count")} +{variable-array0 :offset-base-ctype "core::WeakKeyAndValueMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::WeakAnd" :offset-base-ctype "core::WeakKeyAndValueMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::WeakPointer" + :fixup-ctype-key "gctools::WeakAnd" :layout-offset-field-names ("key")} +{variable-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::WeakPointer" + :fixup-ctype-key "gctools::WeakAnd" :layout-offset-field-names ("value")} {class-kind :stamp-name "STAMPWTAG_core__StrongMapping_O" :stamp-key "core::StrongMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} @@ -6075,6 +6094,22 @@ :fixup-ctype-offset-type-key "gctools::smart_ptr" :fixup-ctype-key "core::SymbolClassHolderPair" :layout-offset-field-names ("theClassHolder")} +{container-kind :stamp-name "STAMPWTAG_gctools__GCArray_moveable_gctools__WeakAnd_" + :stamp-key "gctools::GCArray_moveable" + :parent-class "gctools::GCContainer" :lisp-class-base nil + :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} +{variable-array0 :offset-base-ctype "gctools::GCArray_moveable" + :field-names ("_Data")} +{variable-capacity :ctype "gctools::WeakAnd" + :offset-base-ctype "gctools::GCArray_moveable" + :length-field-names ("_MaybeSignedLength") + :end-field-names ("_MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::WeakPointer" + :fixup-ctype-key "gctools::WeakAnd" :layout-offset-field-names ("key")} +{variable-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::WeakPointer" + :fixup-ctype-key "gctools::WeakAnd" :layout-offset-field-names ("value")} {container-kind :stamp-name "STAMPWTAG_gctools__GCArray_moveable_signed_char_" :stamp-key "gctools::GCArray_moveable" :parent-class "gctools::GCContainer" :lisp-class-base nil diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index db13448593..c197f59319 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -145,7 +145,8 @@ "chem::Logical_O" "comp::ControlLabelFixup_O" "llvmo::StructLayout_O" "core::SimpleMDArrayT_O" "chem::ConformationExplorer_O" "core::StrongMapping_O" "chem::BondList_O" "llvmo::LoadInst_O" - "core::Exposer_O" "llvmo::ConstantStruct_O" "chem::MacroModelFile_O" + "core::Exposer_O" "llvmo::ConstantStruct_O" + "core::WeakKeyAndValueMapping_O" "chem::MacroModelFile_O" "core::MDArray_byte2_t_O" "core::DirectoryIterator_O" "chem::Angle_O" "llvmo::DISubroutineType_O" "chem::EnergyComponents_O" "comp::LabelFixup_O" "comp::Cfunction_O" "llvmo::MetadataAsValue_O" @@ -175,14 +176,15 @@ "kinematics::Joint_O" "chem::AntechamberBondToAtomTest_O" "core::MDArray_byte32_t_O" "llvmo::SectionedAddress_O" "core::Character_dummy_O" "core::PosixFileStream_O" "comp::LexRefFixup_O" - "llvmo::Constant_O" "chem::EnergyStretch_O" "llvmo::FunctionCallee_O" - "chem::ResidueOut" "core::NativeVector_int_O" "llvmo::DIBasicType_O" - "llvmo::DIBuilder_O" "llvmo::APInt_O" "llvmo::APFloat_O" - "core::SimpleMDArrayCharacter_O" "core::SimpleCharacterString_O" - "core::Symbol_O" "chem::AtomOrBondMatchNode_O" "core::Array_O" - "core::MDArray_byte4_t_O" "llvmo::Argument_O" "chem::FFItorDb_O" - "llvmo::IRBuilderBase_O" "units::Unit_O" "core::Null_O" - "chem::RingFinder_O" "chem::IterateBonds_O" "core::RequiredArgument" + "llvmo::Constant_O" "gctools::WeakAnd" "chem::EnergyStretch_O" + "llvmo::FunctionCallee_O" "chem::ResidueOut" "core::NativeVector_int_O" + "llvmo::DIBasicType_O" "llvmo::DIBuilder_O" "llvmo::APInt_O" + "llvmo::APFloat_O" "core::SimpleMDArrayCharacter_O" + "core::SimpleCharacterString_O" "core::Symbol_O" + "chem::AtomOrBondMatchNode_O" "core::Array_O" "core::MDArray_byte4_t_O" + "llvmo::Argument_O" "chem::FFItorDb_O" "llvmo::IRBuilderBase_O" + "units::Unit_O" "core::Null_O" "chem::RingFinder_O" + "chem::IterateBonds_O" "core::RequiredArgument" "core::SingleDispatchMethod_O" "chem::CDFragment_O" "comp::VarInfo_O" "core::CxxObject_O" "core::SimpleVector_long_float_O" "llvmo::ReturnInst_O" "llvmo::FunctionType_O" "clbind::DummyCreator_O" @@ -9861,6 +9863,24 @@ :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} {variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" :fixup-type "gctools::Ephemeron"} +{class-kind :stamp-name "STAMPWTAG_core__WeakKeyAndValueMapping_O" + :stamp-key "core::WeakKeyAndValueMapping_O" :parent-class "core::Mapping_O" + :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 + :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakKeyAndValueMapping_O" + :layout-offset-field-names ("_Count")} +{variable-array0 :offset-base-ctype "core::WeakKeyAndValueMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::WeakAnd" :offset-base-ctype "core::WeakKeyAndValueMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::WeakPointer" + :fixup-ctype-key "gctools::WeakAnd" :layout-offset-field-names ("key")} +{variable-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::WeakPointer" + :fixup-ctype-key "gctools::WeakAnd" :layout-offset-field-names ("value")} {class-kind :stamp-name "STAMPWTAG_core__WeakValueMapping_O" :stamp-key "core::WeakValueMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 :definition-data "IS_POLYMORPHIC"} @@ -10765,6 +10785,22 @@ :fixup-ctype-offset-type-key "gctools::smart_ptr" :fixup-ctype-key "core::SymbolClassHolderPair" :layout-offset-field-names ("theClassHolder")} +{container-kind :stamp-name "STAMPWTAG_gctools__GCArray_moveable_gctools__WeakAnd_" + :stamp-key "gctools::GCArray_moveable" + :parent-class "gctools::GCContainer" :lisp-class-base nil + :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} +{variable-array0 :offset-base-ctype "gctools::GCArray_moveable" + :field-names ("_Data")} +{variable-capacity :ctype "gctools::WeakAnd" + :offset-base-ctype "gctools::GCArray_moveable" + :length-field-names ("_MaybeSignedLength") + :end-field-names ("_MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::WeakPointer" + :fixup-ctype-key "gctools::WeakAnd" :layout-offset-field-names ("key")} +{variable-field :offset-type-cxx-identifier "WEAK_PTR_OFFSET" + :fixup-ctype-offset-type-key "gctools::WeakPointer" + :fixup-ctype-key "gctools::WeakAnd" :layout-offset-field-names ("value")} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_std__pair_gctools__smart_ptr_core__Symbol_O__gctools__smart_ptr_core__Symbol_O___" :stamp-key "gctools::GCVector_moveable,gctools::smart_ptr>>" :parent-class "gctools::GCContainer" :lisp-class-base nil diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index d2fe1242dc..a08bd91a50 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -100,6 +100,10 @@ WeakValueMapping_sp WeakValueMapping_O::make(size_t size) { return gctools::GC::allocate_container(false, size); } +WeakKeyAndValueMapping_sp WeakKeyAndValueMapping_O::make(size_t size) { + return gctools::GC::allocate_container(false, size); +} + std::atomic global_next_hash_table_id; size_t next_hash_table_id() { return global_next_hash_table_id++; } @@ -184,6 +188,8 @@ CL_DEFUN T_sp cl__make_hash_table(T_sp test, Fixnum_sp size, Number_sp rehash_si mapping = WeakKeyMapping_O::make(isize); else if (weakness == kw::_sym_value) mapping = WeakValueMapping_O::make(isize); + else if (weakness == kw::_sym_key_and_value) + mapping = WeakKeyAndValueMapping_O::make(isize); else SIMPLE_ERROR("Only :weakness :key :value (weak-key or weak-value hash tables) are currently supported"); diff --git a/src/core/keywordPackage.cc b/src/core/keywordPackage.cc index be8e618d87..a118ff49a7 100644 --- a/src/core/keywordPackage.cc +++ b/src/core/keywordPackage.cc @@ -102,6 +102,7 @@ SYMBOL_EXPORT_SC_(KeywordPkg, internal); SYMBOL_EXPORT_SC_(KeywordPkg, io); SYMBOL_EXPORT_SC_(KeywordPkg, iso_8859_1); SYMBOL_EXPORT_SC_(KeywordPkg, junkAllowed); +SYMBOL_EXPORT_SC_(KeywordPkg, key_and_value); // hash table weakness SYMBOL_EXPORT_SC_(KeywordPkg, latin_1); SYMBOL_EXPORT_SC_(KeywordPkg, lf); SYMBOL_EXPORT_SC_(KeywordPkg, line); diff --git a/src/gctools/gcweak.cc b/src/gctools/gcweak.cc index c9226f069d..19640e0f0f 100644 --- a/src/gctools/gcweak.cc +++ b/src/gctools/gcweak.cc @@ -67,6 +67,17 @@ void WeakPointer::store_no_lock(core::T_sp o) { _splattablep = o.objectp(); // links set up in fixupInternals below. } +void WeakPointer::store(core::T_sp o) { + if (o.objectp()) { // pointer, so we're actually weak + _splattablep = true; + // note: deregistered automatically if the weak pointer itself is dealloc'd + GC_general_register_disappearing_link((void**)&_value, &*o); + } else { + _splattablep = false; + GC_unregister_disappearing_link((void**)&_value); + } + _value = o.tagged_(); +} void WeakPointer::fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) { if (snapshotSaveLoad::operation(fixup) == snapshotSaveLoad::LoadOp) { @@ -90,6 +101,7 @@ WeakPointer::WeakPointer(core::T_sp o) : _value(o.tagged_()) {} std::optional WeakPointer::value() const { return core::T_sp(_value); } std::optional WeakPointer::value_no_lock() const { return value(); } void WeakPointer::store_no_lock(core::T_sp o) { _value = o.tagged_(); } +void WeakPointer::store(core::T_sp o) { store_no_lock(o); } void WeakPointer::fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup*) {} #endif @@ -182,4 +194,6 @@ const KVPair StrongMapping::initKV = {.key = core::T_sp(tag_no_key()), // static constructor ordering. const Ephemeron EphemeronMapping::initEph{no_key(), no_key()}; +const WeakAnd WeakAndMapping::initKV{no_key(), no_key()}; + } // namespace gctools From 93c735deb619ce1688b68613844e396ef9dc0219 Mon Sep 17 00:00:00 2001 From: Bike Date: Tue, 21 Jan 2025 20:29:41 -0500 Subject: [PATCH 36/39] make weak pointer _splattable field boehm-specific Since the analyzer knows about WeakPointer now, there's no point in making it generic --- include/clasp/gctools/gcweak.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index 8a71bf9e21..e99d6f3067 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -94,11 +94,9 @@ struct WeakPointer { // check for T_sps in atomic (pointerless) objects. Rather than lie harder we // can just do this and build a T_sp from it as required. Tagged _value; +#ifdef USE_BOEHM // flag needed to disambiguate fixnum 0 from splatted pointer - // not sure if other GCs need this, but i'd like to keep the structure - // consistent regardless of build parameters if possible. bool _splattablep = false; -#ifdef USE_BOEHM private: // private stuff needed to get everything done within a callback struct value_helper_s { From eb4aa81033fa6cb4b10d006a4297a69635827791 Mon Sep 17 00:00:00 2001 From: Bike Date: Wed, 22 Jan 2025 00:34:04 -0500 Subject: [PATCH 37/39] add weak key-or-value hash tables, sorta They don't and I think can't work with boehm gc, but the code's there for later. --- include/clasp/core/hashTable.h | 25 +++++++++++ include/clasp/gctools/gcweak.h | 49 ++++++++++++++++++++++ src/analysis/clasp_gc.sif | 62 +++++++++++++++++++++------ src/analysis/clasp_gc_cando.sif | 74 ++++++++++++++++++++++++--------- src/core/hashTable.cc | 6 +++ src/core/keywordPackage.cc | 1 + src/gctools/gcweak.cc | 1 + 7 files changed, 186 insertions(+), 32 deletions(-) diff --git a/include/clasp/core/hashTable.h b/include/clasp/core/hashTable.h index d9c4073004..9457b8dab7 100644 --- a/include/clasp/core/hashTable.h +++ b/include/clasp/core/hashTable.h @@ -212,6 +212,31 @@ class WeakKeyAndValueMapping_O final : public Mapping_O { } }; +FORWARD(WeakKeyOrValueMapping); +class WeakKeyOrValueMapping_O final : public Mapping_O { + LISP_CLASS(core, CorePkg, WeakKeyOrValueMapping_O, "WeakKeyOrValueMapping", Mapping_O); +public: + // need typedefs for e.g. sizeof_container + typedef gctools::WeakAndMapping::value_type value_type; +public: + WeakKeyOrValueMapping_O(size_t size) : _Mapping(size) {} + static WeakKeyOrValueMapping_sp make(size_t); +public: + gctools::DoubleEphMapping _Mapping; +public: + virtual size_t size() const { return _Mapping.size(); } + virtual size_t count() const { return computeCount(); } + virtual Mapping_sp realloc(size_t sz) const { return make(sz); } + virtual gctools::KVPair get(size_t i) const { return _Mapping.get(i); } + virtual void setValue(size_t i, T_sp, T_sp v) { _Mapping.setValue(i, v); } + virtual void newEntry(size_t i, T_sp k, T_sp v) { ++_Count; _Mapping.newEntry(i, k, v); } + virtual void remove(size_t i) { --_Count; _Mapping.remove(i); } + virtual Symbol_sp weakness() { return kw::_sym_key_or_value; } + virtual void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) override { + _Mapping.fixupInternalsForSnapshotSaveLoad(fixup); + } +}; + FORWARD(HashTable); class HashTable_O : public General_O { LISP_CLASS(core, ClPkg, HashTable_O, "HashTable", General_O); diff --git a/include/clasp/gctools/gcweak.h b/include/clasp/gctools/gcweak.h index e99d6f3067..42c704846c 100644 --- a/include/clasp/gctools/gcweak.h +++ b/include/clasp/gctools/gcweak.h @@ -270,4 +270,53 @@ struct WeakAndMapping { } }; +/* + * For weak key-or-value tables: an entry is alive as long as either the key + * or the value is alive. This is easily represented as a pair of ephemerons + * such that the key and value of one is the value and key of the other. + * But that doesn't actually work in Boehm. Boehm can't really represent + * this. However we keep this arrangement so that the static analyzer knows + * about these structures. + * On Boehm this is effectively a StrongMapping with more steps (and space). + */ +struct DoubleEphemeron { + Ephemeron kv; + Ephemeron vk; + DoubleEphemeron(core::T_sp k, core::T_sp v) : kv(k, v), vk(v, k) {} + KVPair get() const { return kv.get(); } + void setValue(core::T_sp v) { + auto r = get(); + kv.setValue(v); vk.reinit(v, r.key); + } + void reinit(core::T_sp k, core::T_sp v) { + kv.reinit(k, v); vk.reinit(v, k); + } + void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) { + kv.fixupInternalsForSnapshotSaveLoad(fixup); + vk.fixupInternalsForSnapshotSaveLoad(fixup); + } +}; + +struct DoubleEphMapping { +public: + typedef GCArray_moveable vector_type; + typedef typename vector_type::value_type value_type; +private: + static const DoubleEphemeron initEph; +public: + DoubleEphMapping(size_t size) : _Data(size, initEph) {} +public: + vector_type _Data; +public: + size_t size() const { return _Data.length(); } + KVPair get(size_t i) const { return _Data[i].get(); } + void setValue(size_t i, core::T_sp v) { _Data[i].setValue(v); } + void newEntry(size_t i, core::T_sp k, core::T_sp v) { _Data[i].reinit(k, v); } + void remove(size_t i) { _Data[i].reinit(deleted(), deleted()); } + void fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) { + for (size_t i = 0; i < _Data.length(); ++i) + _Data[i].fixupInternalsForSnapshotSaveLoad(fixup); + } +}; + }; // namespace gctools diff --git a/src/analysis/clasp_gc.sif b/src/analysis/clasp_gc.sif index d2cb2c122d..1777ca5866 100644 --- a/src/analysis/clasp_gc.sif +++ b/src/analysis/clasp_gc.sif @@ -4,8 +4,8 @@ "clbind::ClassRegistry_O" "mp::Process_O" "core::Record_O" "core::LightUserData_O" "core::MDArrayT_O" "core::WeakValueMapping_O" "core::FunctionCell_O" "core::DirectoryEntry_O" "llvmo::Linker_O" - "comp::FunInfo_O" "core::MDArray_float_O" "core::SourcePosInfo_O" - "llvmo::BranchInst_O" "llvmo::AllocaInst_O" + "comp::FunInfo_O" "gctools::DoubleEphemeron" "core::MDArray_float_O" + "core::SourcePosInfo_O" "llvmo::BranchInst_O" "llvmo::AllocaInst_O" "core::StandardClassCreator_O" "core::ComplexVector_float_O" "core::HashTableCustom_O" "comp::LexicalVarInfo_O" "core::ComplexVector_byte8_t_O" "core::OptionalArgument" @@ -144,17 +144,18 @@ "core::HashTableEqualp_O" "asttooling::PresumedLoc_O" "core::ConcatenatedStream_O" "comp::Fixup_O" "core::LexDynEnv_O" "core::FuncallableInstance_O" "clbind::detail::edge" - "core::SynonymStream_O" "core::BytecodeModule_O" "core::Ratio_O" - "core::MDArray_int2_t_O" "core::ComplexVector_byte2_t_O" - "llvmo::ExecutionEngine_O" "core::ClassRepCreator_O" - "core::MDArray_long_float_O" "core::SimpleVector_int16_t_O" - "llvmo::Attribute_O" "core::WeakKeyMapping_O" - "core::DerivableCxxObject_O" "core::SymbolToEnumConverter_O" - "llvmo::SwitchInst_O" "core::SingleDispatchGenericFunction_O" - "core::ComplexVector_int32_t_O" "core::ComplexVector_byte4_t_O" - "asttooling::SourceLocation_O" "core::LogicalPathname_O" - "llvmo::TargetSubtargetInfo_O" "core::SimpleVector_double_O" - "core::CFileStream_O" "core::SimpleMDArray_byte32_t_O" "core::Bignum_O" + "core::WeakKeyOrValueMapping_O" "core::SynonymStream_O" + "core::BytecodeModule_O" "core::Ratio_O" "core::MDArray_int2_t_O" + "core::ComplexVector_byte2_t_O" "llvmo::ExecutionEngine_O" + "core::ClassRepCreator_O" "core::MDArray_long_float_O" + "core::SimpleVector_int16_t_O" "llvmo::Attribute_O" + "core::WeakKeyMapping_O" "core::DerivableCxxObject_O" + "core::SymbolToEnumConverter_O" "llvmo::SwitchInst_O" + "core::SingleDispatchGenericFunction_O" "core::ComplexVector_int32_t_O" + "core::ComplexVector_byte4_t_O" "asttooling::SourceLocation_O" + "core::LogicalPathname_O" "llvmo::TargetSubtargetInfo_O" + "core::SimpleVector_double_O" "core::CFileStream_O" + "core::SimpleMDArray_byte32_t_O" "core::Bignum_O" "llvmo::LLVMTargetMachine_O" "core::ClassHolder_O" "core::ComplexVector_byte32_t_O" "llvmo::UnaryInstruction_O" "llvmo::GlobalValue_O" "llvmo::PointerType_O" "core::TwoWayStream_O")} @@ -4777,6 +4778,25 @@ :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} {variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" :fixup-type "gctools::Ephemeron"} +{class-kind :stamp-name "STAMPWTAG_core__WeakKeyOrValueMapping_O" + :stamp-key "core::WeakKeyOrValueMapping_O" :parent-class "core::Mapping_O" + :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 + :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakKeyOrValueMapping_O" + :layout-offset-field-names ("_Count")} +{variable-array0 :offset-base-ctype "core::WeakKeyOrValueMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::DoubleEphemeron" + :offset-base-ctype "core::WeakKeyOrValueMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-ctype-offset-type-key "gctools::Ephemeron" + :fixup-ctype-key "gctools::DoubleEphemeron" :layout-offset-field-names ("kv")} +{variable-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-ctype-offset-type-key "gctools::Ephemeron" + :fixup-ctype-key "gctools::DoubleEphemeron" :layout-offset-field-names ("vk")} {class-kind :stamp-name "STAMPWTAG_core__WeakKeyAndValueMapping_O" :stamp-key "core::WeakKeyAndValueMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 @@ -6523,6 +6543,22 @@ :fixup-ctype-key "clbind::detail::edge" :layout-offset-field-names ("target")} {variable-field :offset-type-cxx-identifier "RAW_POINTER_OFFSET" :fixup-ctype-offset-type-key nil :fixup-ctype-key "clbind::detail::edge" :layout-offset-field-names ("cast")} +{container-kind :stamp-name "STAMPWTAG_gctools__GCArray_moveable_gctools__DoubleEphemeron_" + :stamp-key "gctools::GCArray_moveable" + :parent-class "gctools::GCContainer" :lisp-class-base nil + :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} +{variable-array0 :offset-base-ctype "gctools::GCArray_moveable" + :field-names ("_Data")} +{variable-capacity :ctype "gctools::DoubleEphemeron" + :offset-base-ctype "gctools::GCArray_moveable" + :length-field-names ("_MaybeSignedLength") + :end-field-names ("_MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-ctype-offset-type-key "gctools::Ephemeron" + :fixup-ctype-key "gctools::DoubleEphemeron" :layout-offset-field-names ("kv")} +{variable-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-ctype-offset-type-key "gctools::Ephemeron" + :fixup-ctype-key "gctools::DoubleEphemeron" :layout-offset-field-names ("vk")} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_gctools__smart_ptr_core__Creator_O__" :stamp-key "gctools::GCVector_moveable>" :parent-class "gctools::GCContainer" :lisp-class-base nil diff --git a/src/analysis/clasp_gc_cando.sif b/src/analysis/clasp_gc_cando.sif index c197f59319..8211cd0f73 100644 --- a/src/analysis/clasp_gc_cando.sif +++ b/src/analysis/clasp_gc_cando.sif @@ -8,9 +8,10 @@ "core::MDArrayT_O" "core::WeakValueMapping_O" "core::FunctionCell_O" "core::DirectoryEntry_O" "chem::Atom_O" "llvmo::Linker_O" "chem::Kmeans_O" "comp::FunInfo_O" "chem::ZMatrix_O" - "core::MDArray_float_O" "chem::KmeansPlusPlus_O" "core::SourcePosInfo_O" - "llvmo::BranchInst_O" "chem::IterateMatter_O" "llvmo::AllocaInst_O" - "chem::AtomicInfo" "chem::FFTypesDb_O" "core::ComplexVector_float_O" + "gctools::DoubleEphemeron" "core::MDArray_float_O" + "chem::KmeansPlusPlus_O" "core::SourcePosInfo_O" "llvmo::BranchInst_O" + "chem::IterateMatter_O" "llvmo::AllocaInst_O" "chem::AtomicInfo" + "chem::FFTypesDb_O" "core::ComplexVector_float_O" "core::StandardClassCreator_O" "chem::Alias_O" "comp::LexicalVarInfo_O" "chem::MapOfMonomerNamesToAtomIndexers_O" "chem::ZMatrixInternal_O" "core::HashTableCustom_O" "adapt::SymbolSet_O" "chem::Minimizer_O" @@ -235,22 +236,22 @@ "asttooling::PresumedLoc_O" "core::ConcatenatedStream_O" "comp::Fixup_O" "core::LexDynEnv_O" "chem::RestrainedExoCyclicAtom_O" "chem::EnergyAtom" "kinematics::ComplexBondedJoint_O" "core::FuncallableInstance_O" - "clbind::detail::edge" "chem::NumericalFunction_O" - "core::SynonymStream_O" "core::Ratio_O" "core::BytecodeModule_O" - "core::MDArray_int2_t_O" "core::ComplexVector_byte2_t_O" - "chem::FixedNonbondRestraint" "llvmo::ExecutionEngine_O" - "core::ClassRepCreator_O" "core::MDArray_long_float_O" - "core::SimpleVector_int16_t_O" "llvmo::Attribute_O" - "core::DerivableCxxObject_O" "core::WeakKeyMapping_O" - "llvmo::SwitchInst_O" "core::SymbolToEnumConverter_O" - "chem::RestrainedPiBond_O" "chem::ConformationCollection_O" - "core::SingleDispatchGenericFunction_O" "core::ComplexVector_int32_t_O" - "chem::StepReport_O" "geom::Color_O" "chem::FFVdw_O" - "core::ComplexVector_byte4_t_O" "asttooling::SourceLocation_O" - "core::LogicalPathname_O" "llvmo::TargetSubtargetInfo_O" - "core::SimpleVector_double_O" "chem::Root_O" "core::CFileStream_O" - "core::SimpleMDArray_byte32_t_O" "core::Bignum_O" - "llvmo::LLVMTargetMachine_O" "core::ClassHolder_O" + "clbind::detail::edge" "core::WeakKeyOrValueMapping_O" + "chem::NumericalFunction_O" "core::SynonymStream_O" "core::Ratio_O" + "core::BytecodeModule_O" "core::MDArray_int2_t_O" + "core::ComplexVector_byte2_t_O" "chem::FixedNonbondRestraint" + "llvmo::ExecutionEngine_O" "core::ClassRepCreator_O" + "core::MDArray_long_float_O" "core::SimpleVector_int16_t_O" + "llvmo::Attribute_O" "core::DerivableCxxObject_O" + "core::WeakKeyMapping_O" "llvmo::SwitchInst_O" + "core::SymbolToEnumConverter_O" "chem::RestrainedPiBond_O" + "chem::ConformationCollection_O" "core::SingleDispatchGenericFunction_O" + "core::ComplexVector_int32_t_O" "chem::StepReport_O" "geom::Color_O" + "chem::FFVdw_O" "core::ComplexVector_byte4_t_O" + "asttooling::SourceLocation_O" "core::LogicalPathname_O" + "llvmo::TargetSubtargetInfo_O" "core::SimpleVector_double_O" + "chem::Root_O" "core::CFileStream_O" "core::SimpleMDArray_byte32_t_O" + "core::Bignum_O" "llvmo::LLVMTargetMachine_O" "core::ClassHolder_O" "chem::SketchFunction_O" "core::ComplexVector_byte32_t_O" "llvmo::UnaryInstruction_O" "llvmo::GlobalValue_O" "llvmo::PointerType_O" "core::TwoWayStream_O")} @@ -9863,6 +9864,25 @@ :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} {variable-field-only :offset-type-cxx-identifier "EPHEMERON_OFFSET" :fixup-type "gctools::Ephemeron"} +{class-kind :stamp-name "STAMPWTAG_core__WeakKeyOrValueMapping_O" + :stamp-key "core::WeakKeyOrValueMapping_O" :parent-class "core::Mapping_O" + :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 + :definition-data "IS_POLYMORPHIC"} +{fixed-field :offset-type-cxx-identifier "ctype_unsigned_long" :offset-ctype "unsigned long" + :offset-base-ctype "core::WeakKeyOrValueMapping_O" + :layout-offset-field-names ("_Count")} +{variable-array0 :offset-base-ctype "core::WeakKeyOrValueMapping_O" + :field-names ("_Mapping" "._Data" "._Data")} +{variable-capacity :ctype "gctools::DoubleEphemeron" + :offset-base-ctype "core::WeakKeyOrValueMapping_O" + :length-field-names ("_Mapping" "._Data" "._MaybeSignedLength") + :end-field-names ("_Mapping" "._Data" "._MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-ctype-offset-type-key "gctools::Ephemeron" + :fixup-ctype-key "gctools::DoubleEphemeron" :layout-offset-field-names ("kv")} +{variable-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-ctype-offset-type-key "gctools::Ephemeron" + :fixup-ctype-key "gctools::DoubleEphemeron" :layout-offset-field-names ("vk")} {class-kind :stamp-name "STAMPWTAG_core__WeakKeyAndValueMapping_O" :stamp-key "core::WeakKeyAndValueMapping_O" :parent-class "core::Mapping_O" :lisp-class-base "core::Mapping_O" :root-class "core::T_O" :stamp-wtag 3 @@ -12340,6 +12360,22 @@ :length-field-names ("_Capacity") :end-field-names ("_End")} {variable-field-only :offset-type-cxx-identifier "SMART_PTR_OFFSET" :fixup-type "gctools::smart_ptr"} +{container-kind :stamp-name "STAMPWTAG_gctools__GCArray_moveable_gctools__DoubleEphemeron_" + :stamp-key "gctools::GCArray_moveable" + :parent-class "gctools::GCContainer" :lisp-class-base nil + :root-class "gctools::GCContainer" :stamp-wtag 3 :definition-data "0"} +{variable-array0 :offset-base-ctype "gctools::GCArray_moveable" + :field-names ("_Data")} +{variable-capacity :ctype "gctools::DoubleEphemeron" + :offset-base-ctype "gctools::GCArray_moveable" + :length-field-names ("_MaybeSignedLength") + :end-field-names ("_MaybeSignedLength")} +{variable-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-ctype-offset-type-key "gctools::Ephemeron" + :fixup-ctype-key "gctools::DoubleEphemeron" :layout-offset-field-names ("kv")} +{variable-field :offset-type-cxx-identifier "EPHEMERON_OFFSET" + :fixup-ctype-offset-type-key "gctools::Ephemeron" + :fixup-ctype-key "gctools::DoubleEphemeron" :layout-offset-field-names ("vk")} {container-kind :stamp-name "STAMPWTAG_gctools__GCVector_moveable_unsigned_int_" :stamp-key "gctools::GCVector_moveable" :parent-class "gctools::GCContainer" :lisp-class-base nil diff --git a/src/core/hashTable.cc b/src/core/hashTable.cc index a08bd91a50..5bc218568b 100644 --- a/src/core/hashTable.cc +++ b/src/core/hashTable.cc @@ -104,6 +104,10 @@ WeakKeyAndValueMapping_sp WeakKeyAndValueMapping_O::make(size_t size) { return gctools::GC::allocate_container(false, size); } +WeakKeyOrValueMapping_sp WeakKeyOrValueMapping_O::make(size_t size) { + return gctools::GC::allocate_container(false, size); +} + std::atomic global_next_hash_table_id; size_t next_hash_table_id() { return global_next_hash_table_id++; } @@ -190,6 +194,8 @@ CL_DEFUN T_sp cl__make_hash_table(T_sp test, Fixnum_sp size, Number_sp rehash_si mapping = WeakValueMapping_O::make(isize); else if (weakness == kw::_sym_key_and_value) mapping = WeakKeyAndValueMapping_O::make(isize); + else if (weakness == kw::_sym_key_or_value) + mapping = WeakKeyOrValueMapping_O::make(isize); else SIMPLE_ERROR("Only :weakness :key :value (weak-key or weak-value hash tables) are currently supported"); diff --git a/src/core/keywordPackage.cc b/src/core/keywordPackage.cc index a118ff49a7..d883ebd153 100644 --- a/src/core/keywordPackage.cc +++ b/src/core/keywordPackage.cc @@ -103,6 +103,7 @@ SYMBOL_EXPORT_SC_(KeywordPkg, io); SYMBOL_EXPORT_SC_(KeywordPkg, iso_8859_1); SYMBOL_EXPORT_SC_(KeywordPkg, junkAllowed); SYMBOL_EXPORT_SC_(KeywordPkg, key_and_value); // hash table weakness +SYMBOL_EXPORT_SC_(KeywordPkg, key_or_value); SYMBOL_EXPORT_SC_(KeywordPkg, latin_1); SYMBOL_EXPORT_SC_(KeywordPkg, lf); SYMBOL_EXPORT_SC_(KeywordPkg, line); diff --git a/src/gctools/gcweak.cc b/src/gctools/gcweak.cc index 19640e0f0f..0864273b93 100644 --- a/src/gctools/gcweak.cc +++ b/src/gctools/gcweak.cc @@ -195,5 +195,6 @@ const KVPair StrongMapping::initKV = {.key = core::T_sp(tag_no_key()), const Ephemeron EphemeronMapping::initEph{no_key(), no_key()}; const WeakAnd WeakAndMapping::initKV{no_key(), no_key()}; +const DoubleEphemeron DoubleEphMapping::initEph{no_key(), no_key()}; } // namespace gctools From f4221a0346ffc82f40f39c3811cb573aead469cb Mon Sep 17 00:00:00 2001 From: Bike Date: Wed, 22 Jan 2025 09:46:28 -0500 Subject: [PATCH 38/39] add tests for weak hash tables most importantly, test that they actually are weak. I don't think they were before my rewrite. --- src/lisp/regression-tests/hash-tables0.lisp | 99 ++++++++++++++++----- 1 file changed, 75 insertions(+), 24 deletions(-) diff --git a/src/lisp/regression-tests/hash-tables0.lisp b/src/lisp/regression-tests/hash-tables0.lisp index 478d1f04eb..4ff1f64d25 100644 --- a/src/lisp/regression-tests/hash-tables0.lisp +++ b/src/lisp/regression-tests/hash-tables0.lisp @@ -77,41 +77,92 @@ (test-expect-error hash-table-rehash-THRESHOLD-nil (HASH-TABLE-REHASH-THRESHOLD nil) :type type-error) (test-expect-error hash-table-test-nil (HASH-TABLE-TEST nil) :type type-error) -;;weak tables: weakness :key -(test hash-table-count-weak-key - (hash-table-count (make-hash-table :test #'eq :weakness :key)) - (0)) +;; weak tables +(defun hash-table-basics (table) + (values (hash-table-p table) + (hash-table-size table) + (hash-table-count table) + (typep (hash-table-rehash-size table) '(real 1)) + (typep (hash-table-rehash-threshold table) '(real 0 1)) + (hash-table-test table) + (ext:hash-table-weakness table) + (multiple-value-list (gethash :key table)))) + +(test hash-table-weak-key.basic + (hash-table-basics (make-hash-table :size 128 :weakness :key)) + (t 128 0 t t eql :key (nil nil))) +(test hash-table-weak-value.basic + (hash-table-basics (make-hash-table :size 128 :weakness :value)) + (t 128 0 t t eql :value (nil nil))) +(test hash-table-weak-key-and-value.basic + (hash-table-basics (make-hash-table :size 128 :weakness :key-and-value)) + (t 128 0 t t eql :key-and-value (nil nil))) +(test hash-table-weak-key-or-value.basic + (hash-table-basics (make-hash-table :size 128 :weakness :key-or-value)) + (t 128 0 t t eql :key-or-value (nil nil))) + (test hash-table-count-2-weak-key - (let ((table (make-hash-table :test #'eq :weakness :key))) + (let ((table (make-hash-table :weakness :key))) (setf (gethash :key table) 23) (setf (gethash :key1 table) 22) (setf (gethash :key table) 25) (hash-table-count table)) (2)) -(test hash-table-size-weak-key - (hash-table-size (make-hash-table :size 128 :test #'eq :weakness :key)) - (128)) -(test-true hash-table-rehash-size-weak-key (HASH-TABLE-REHASH-SIZE (make-hash-table :test #'eq :weakness :key))) -(test-true hash-table-rehash-THRESHOLD-weak-key (HASH-TABLE-REHASH-THRESHOLD (make-hash-table :test #'eq :weakness :key))) -(test-true hash-table-test-weak-key (HASH-TABLE-TEST (make-hash-table :test #'eq :weakness :key))) -(test-true gethash-weak-key (let ((table (make-hash-table :test #'eq :weakness :key))) - (gethash :key table) - t)) (test setf-gethash-weak-key - (let ((table (make-hash-table :test #'eq :weakness :key))) + (let ((table (make-hash-table :weakness :key))) (setf (gethash :key table) 23) (values (gethash :key table))) (23)) -(test-true clrhash-weak-key (clrhash (make-hash-table :test #'eq :weakness :key))) -(test-true maphash-weak-key (progn - (maphash #'(lambda(a b) - (declare (ignore a b))) - (make-hash-table :test #'eq :weakness :key)) - t)) -(test-true remhash-weak-key (progn - (remhash :key (make-hash-table :test #'eq :weakness :key)) - t)) + +(test clrhash-weak-key + (let ((table (make-hash-table :weakness :key))) + (values (hash-table-p (clrhash table)) + (hash-table-count table))) + (t 0)) +(test-nil maphash-weak-key (maphash (lambda (a b) + (declare (ignore a b))) + (make-hash-table :weakness :key))) +(test-nil remhash-weak-key (remhash :key (make-hash-table :weakness :key))) + +;;; These tests are pretty strict - they want the garbage to actually be +;;; collected by that garbage-collect call, which may not be the case if we +;;; ever get a more relaxed collector (generational or something) +(test weak-key-weakness + (let ((table (make-hash-table :weakness :key))) + (setf (gethash (list 37) table) :value + (gethash :key table) (list nil) + (gethash :key2 table) (list nil)) + (gctools:garbage-collect) + (hash-table-count table)) + (2)) +(test weak-value-weakness + (let ((table (make-hash-table :weakness :value))) + (setf (gethash :key table) (list 37) + (gethash (list nil) table) :value + (gethash (list 18) table) :value) + (gctools:garbage-collect) + (hash-table-count table)) + (2)) +(test weak-key-and-value-weakness + (let ((table (make-hash-table :weakness :key-and-value))) + (setf (gethash (list nil) table) :value + (gethash :key table) (list nil) + (gethash (list nil) table) (list nil) + (gethash :key table) :value) + (gctools:garbage-collect) + (hash-table-count table)) + (1)) +#-use-boehm ; on boehm key-or-value tables are effectively strong. +(test weak-key-or-value-weakness + (let ((table (make-hash-table :weakness :key-or))) + (setf (gethash (list nil) table) :value + (gethash :key table) (list nil) + (gethash (list nil) table) (list nil) + (gethash :key table) :value) + (gctools:garbage-collect) + (hash-table-count table)) + (3)) (test equalp-hash-table-1 (let ((key-1 #\a) From e6a83c3f5d32143d4392654f9053b2067e14317f Mon Sep 17 00:00:00 2001 From: Bike Date: Wed, 22 Jan 2025 11:20:29 -0500 Subject: [PATCH 39/39] update release notes --- RELEASE_NOTES.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 84ae3410b0..b89312a408 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,13 @@ +# Version 2.8.0 (LLVM15-19) Pending + +## Added +* Weak-value and weak-key-and-value hash tables, as well as an interface + for weak-key-or-value tables, although at present they are actually + strong tables in practice. + +## Fixed +* Weak pointers and weak hash tables survive snapshot save/load. + # Version 2.7.0 (LLVM15-19) 2025-01-21 ## Added