Optimize special cases during refcounting.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/2dab35a4 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/2dab35a4 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/2dab35a4 Branch: refs/heads/master Commit: 2dab35a40af89271a193a6b6614968c8cfad96d3 Parents: 886c347 Author: Marvin Humphrey <[email protected]> Authored: Sat Feb 7 17:06:53 2015 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Sun Feb 8 12:50:30 2015 -0800 ---------------------------------------------------------------------- compiler/src/CFCBindCore.c | 2 ++ runtime/c/src/Clownfish/Obj.c | 67 +++++++++++++++++++++++++------------ runtime/core/Clownfish/Class.c | 13 ++++++- runtime/perl/xs/XSBind.c | 47 +++++++++++++++++++------- 4 files changed, 94 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2dab35a4/compiler/src/CFCBindCore.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCBindCore.c b/compiler/src/CFCBindCore.c index 80080b5..c4d7f91 100644 --- a/compiler/src/CFCBindCore.c +++ b/compiler/src/CFCBindCore.c @@ -296,6 +296,8 @@ S_write_parcel_h(CFCBindCore *self, CFCParcel *parcel) { "#define CFISH_REFCOUNT_NN(_self) \\\n" " cfish_get_refcount(_self)\n" "\n" + "/* Flags for internal use. */\n" + "#define CFISH_fREFCOUNTSPECIAL 0x00000001\n" ; const char *cfish_defs_2 = "/* Structs for Class initialization.\n" http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2dab35a4/runtime/c/src/Clownfish/Obj.c ---------------------------------------------------------------------- diff --git a/runtime/c/src/Clownfish/Obj.c b/runtime/c/src/Clownfish/Obj.c index 222b283..3db144f 100644 --- a/runtime/c/src/Clownfish/Obj.c +++ b/runtime/c/src/Clownfish/Obj.c @@ -15,20 +15,16 @@ */ #define C_CFISH_OBJ +#define C_CFISH_CLASS #define CFISH_USE_SHORT_NAMES #include "charmony.h" #include "Clownfish/Obj.h" +#include "Clownfish/Class.h" #include "Clownfish/Err.h" #include "Clownfish/String.h" -uint32_t -cfish_get_refcount(void *vself) { - cfish_Obj *self = (cfish_Obj*)vself; - return self->refcount; -} - static CFISH_INLINE bool SI_immortal(cfish_Class *klass) { if (klass == CFISH_CLASS @@ -42,39 +38,66 @@ SI_immortal(cfish_Class *klass) { } static CFISH_INLINE bool -SI_is_string(cfish_Class *klass) { +SI_is_string_type(cfish_Class *klass) { if (klass == CFISH_STRING || klass == CFISH_STACKSTRING) { return true; } return false; } +static CFISH_INLINE bool +SI_threadsafe_but_not_immortal(cfish_Class *klass) { + if (klass == CFISH_LOCKFREEREGISTRY) { + return true; + } + return false; +} + +uint32_t +cfish_get_refcount(void *vself) { + cfish_Obj *self = (cfish_Obj*)vself; + return self->refcount; +} + Obj* cfish_inc_refcount(void *vself) { Obj *self = (Obj*)vself; + + // Handle special cases. cfish_Class *const klass = self->klass; - if (SI_immortal(klass)) { - return self; - } - else if (SI_is_string(klass) - && CFISH_Str_Is_Copy_On_IncRef((cfish_String*)self) - ) { - const char *utf8 = CFISH_Str_Get_Ptr8((cfish_String*)self); - size_t size = CFISH_Str_Get_Size((cfish_String*)self); - return (cfish_Obj*)cfish_Str_new_from_trusted_utf8(utf8, size); - } - else { - self->refcount++; - return self; + if (klass->flags & CFISH_fREFCOUNTSPECIAL) { + if (SI_is_string_type(klass)) { + // Only copy-on-incref Strings get special-cased. Ordinary + // strings fall through to the general case. + if (CFISH_Str_Is_Copy_On_IncRef((cfish_String*)self)) { + const char *utf8 = CFISH_Str_Get_Ptr8((cfish_String*)self); + size_t size = CFISH_Str_Get_Size((cfish_String*)self); + return (cfish_Obj*)cfish_Str_new_from_trusted_utf8(utf8, size); + } + } + else if (SI_immortal(klass)) { + return self; + } + else if (SI_threadsafe_but_not_immortal(klass)) { + // TODO: use atomic operation + } } + + self->refcount++; + return self; } uint32_t cfish_dec_refcount(void *vself) { cfish_Obj *self = (Obj*)vself; cfish_Class *klass = self->klass; - if (SI_immortal(klass)) { - return self->refcount; + if (klass->flags & CFISH_fREFCOUNTSPECIAL) { + if (SI_immortal(klass)) { + return self->refcount; + } + else if (SI_threadsafe_but_not_immortal(klass)) { + // TODO: use atomic operation + } } uint32_t modified_refcount = INT32_MAX; http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2dab35a4/runtime/core/Clownfish/Class.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c index b30b124..478bd6c 100644 --- a/runtime/core/Clownfish/Class.c +++ b/runtime/core/Clownfish/Class.c @@ -93,10 +93,21 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs) klass->parent = parent; klass->parcel_id = parcel_id; - klass->flags = 0; klass->obj_alloc_size = ivars_offset + spec->ivars_size; klass->class_alloc_size = class_alloc_size; + klass->flags = 0; + if (spec->klass == &CLASS + || spec->klass == &METHOD + || spec->klass == &BOOLNUM + || spec->klass == &HASHTOMBSTONE + || spec->klass == &STRING + || spec->klass == &STACKSTRING + || spec->klass == &LOCKFREEREGISTRY + ) { + klass->flags |= CFISH_fREFCOUNTSPECIAL; + } + if (parent) { // Copy parent vtable. size_t parent_vt_size = parent->class_alloc_size http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2dab35a4/runtime/perl/xs/XSBind.c ---------------------------------------------------------------------- diff --git a/runtime/perl/xs/XSBind.c b/runtime/perl/xs/XSBind.c index d624ff7..659ab35 100644 --- a/runtime/perl/xs/XSBind.c +++ b/runtime/perl/xs/XSBind.c @@ -609,13 +609,21 @@ SI_immortal(cfish_Class *klass) { } static CFISH_INLINE bool -SI_is_string(cfish_Class *klass) { +SI_is_string_type(cfish_Class *klass) { if (klass == CFISH_STRING || klass == CFISH_STACKSTRING) { return true; } return false; } +static CFISH_INLINE bool +SI_threadsafe_but_not_immortal(cfish_Class *klass) { + if (klass == CFISH_LOCKFREEREGISTRY) { + return true; + } + return false; +} + static void S_lazy_init_host_obj(cfish_Obj *self) { SV *inner_obj = newSV(0); @@ -653,16 +661,25 @@ cfish_get_refcount(void *vself) { cfish_Obj* cfish_inc_refcount(void *vself) { cfish_Obj *self = (cfish_Obj*)vself; + + // Handle special cases. cfish_Class *const klass = self->klass; - if (SI_immortal(klass)) { - return self; - } - else if (SI_is_string(klass) - && CFISH_Str_Is_Copy_On_IncRef((cfish_String*)self) - ) { - const char *utf8 = CFISH_Str_Get_Ptr8((cfish_String*)self); - size_t size = CFISH_Str_Get_Size((cfish_String*)self); - return (cfish_Obj*)cfish_Str_new_from_trusted_utf8(utf8, size); + if (klass->flags & CFISH_fREFCOUNTSPECIAL) { + if (SI_is_string_type(klass)) { + // Only copy-on-incref Strings get special-cased. Ordinary + // Strings fall through to the general case. + if (CFISH_Str_Is_Copy_On_IncRef((cfish_String*)self)) { + const char *utf8 = CFISH_Str_Get_Ptr8((cfish_String*)self); + size_t size = CFISH_Str_Get_Size((cfish_String*)self); + return (cfish_Obj*)cfish_Str_new_from_trusted_utf8(utf8, size); + } + } + else if (SI_immortal(klass)) { + return self; + } + else if (SI_threadsafe_but_not_immortal(klass)) { + // TODO: use atomic operation + } } if (self->ref.count & XSBIND_REFCOUNT_FLAG) { @@ -680,9 +697,15 @@ cfish_inc_refcount(void *vself) { uint32_t cfish_dec_refcount(void *vself) { cfish_Obj *self = (cfish_Obj*)vself; + cfish_Class *klass = self->klass; - if (SI_immortal(klass)) { - return 1; + if (klass->flags & CFISH_fREFCOUNTSPECIAL) { + if (SI_immortal(klass)) { + return 1; + } + else if (SI_threadsafe_but_not_immortal(klass)) { + // TODO: use atomic operation + } } uint32_t modified_refcount = I32_MAX;
