Skip to content

Commit

Permalink
Make PG::TypeMap and derivations friendly to GC.compact
Browse files Browse the repository at this point in the history
This way the VALUE references may be relocated.

This partly reverts 7c1756f which was introduced as a simple fix for GC.compact compatbility.
  • Loading branch information
larskanis committed Aug 9, 2020
1 parent a24a64e commit 15f1e71
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 29 deletions.
2 changes: 2 additions & 0 deletions ext/pg.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ int pg_typemap_fit_to_copy_get _(( VALUE ));
VALUE pg_typemap_result_value _(( t_typemap *, VALUE, int, int ));
t_pg_coder *pg_typemap_typecast_query_param _(( t_typemap *, VALUE, int ));
VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
void pg_typemap_mark _(( t_typemap * ));
void pg_typemap_compact _(( t_typemap * ));

PGconn *pg_get_pgconn _(( VALUE ));
t_pg_connection *pg_get_connection _(( VALUE ));
Expand Down
15 changes: 14 additions & 1 deletion ext/pg_type_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,25 @@

#include "pg.h"

void
pg_typemap_mark( t_typemap *this )
{
rb_gc_mark_movable(this->default_typemap);
}

void
pg_typemap_compact( t_typemap *this )
{
this->default_typemap = rb_gc_location(this->default_typemap);
}

const rb_data_type_t pg_typemap_type = {
"PG::TypeMap",
{
(void (*)(void*))NULL,
(void (*)(void*))pg_typemap_mark,
(void (*)(void*))-1,
(size_t (*)(const void *))NULL,
pg_compact_callback(pg_typemap_compact),
},
0,
0,
Expand Down
3 changes: 2 additions & 1 deletion ext/pg_type_map_all_strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
static const rb_data_type_t pg_tmas_type = {
"PG::TypeMapAllStrings",
{
(void (*)(void*))NULL,
(void (*)(void*))pg_typemap_mark,
(void (*)(void*))-1,
(size_t (*)(const void *))NULL,
pg_compact_callback(pg_typemap_compact),
},
&pg_typemap_type,
0,
Expand Down
21 changes: 15 additions & 6 deletions ext/pg_type_map_by_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,20 @@ pg_tmbk_fit_to_query( VALUE self, VALUE params )
static void
pg_tmbk_mark( t_tmbk *this )
{
rb_gc_mark(this->typemap.default_typemap);
rb_gc_mark(this->klass_to_coder);
rb_gc_mark(this->self);
/* Clear the cache, to be safe from changes of klass VALUE by GC.compact.
* TODO: Move cache clearing to compactation callback provided by Ruby-2.7+.
*/
pg_typemap_mark(&this->typemap);
rb_gc_mark_movable(this->klass_to_coder);
}

static void
pg_tmbk_compact(void *ptr)
{
t_tmbk *this = (t_tmbk *)ptr;

pg_typemap_compact(&this->typemap);
this->klass_to_coder = rb_gc_location(this->klass_to_coder);
this->self = rb_gc_location(this->self);

/* Clear the cache, to be safe from changes of klass VALUE by GC.compact. */
memset(&this->cache_row, 0, sizeof(this->cache_row));
}

Expand All @@ -136,6 +144,7 @@ static const rb_data_type_t pg_tmbk_type = {
(void (*)(void*))pg_tmbk_mark,
(void (*)(void*))-1,
(size_t (*)(const void *))NULL,
pg_compact_callback(pg_tmbk_compact),
},
&pg_typemap_type,
0,
Expand Down
21 changes: 19 additions & 2 deletions ext/pg_type_map_by_column.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,27 @@ pg_tmbc_mark( t_tmbc *this )
/* allocated but not initialized ? */
if( this == (t_tmbc *)&pg_typemap_funcs ) return;

rb_gc_mark(this->typemap.default_typemap);
pg_typemap_mark(&this->typemap);
for( i=0; i<this->nfields; i++){
t_pg_coder *p_coder = this->convs[i].cconv;
if( p_coder )
rb_gc_mark(p_coder->coder_obj);
rb_gc_mark_movable(p_coder->coder_obj);
}
}

static void
pg_tmbc_compact( t_tmbc *this )
{
int i;

/* allocated but not initialized ? */
if( this == (t_tmbc *)&pg_typemap_funcs ) return;

pg_typemap_compact(&this->typemap);
for( i=0; i<this->nfields; i++){
t_pg_coder *p_coder = this->convs[i].cconv;
if( p_coder )
p_coder->coder_obj = rb_gc_location(p_coder->coder_obj);
}
}

Expand All @@ -200,6 +216,7 @@ static const rb_data_type_t pg_tmbc_type = {
(void (*)(void*))pg_tmbc_mark,
(void (*)(void*))pg_tmbc_free,
(size_t (*)(const void *))NULL,
pg_compact_callback(pg_tmbc_compact),
},
&pg_typemap_type,
0,
Expand Down
18 changes: 15 additions & 3 deletions ext/pg_type_map_by_mri_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,34 @@ pg_tmbmt_fit_to_query( VALUE self, VALUE params )
}

#define GC_MARK_AS_USED(type) \
rb_gc_mark( this->coders.ask_##type ); \
rb_gc_mark( this->coders.coder_obj_##type );
rb_gc_mark_movable( this->coders.ask_##type ); \
rb_gc_mark_movable( this->coders.coder_obj_##type );

static void
pg_tmbmt_mark( t_tmbmt *this )
{
rb_gc_mark(this->typemap.default_typemap);
pg_typemap_mark(&this->typemap);
FOR_EACH_MRI_TYPE( GC_MARK_AS_USED );
}

#define GC_COMPACT(type) \
this->coders.ask_##type = rb_gc_location( this->coders.ask_##type ); \
this->coders.coder_obj_##type = rb_gc_location( this->coders.coder_obj_##type );

static void
pg_tmbmt_compact( t_tmbmt *this )
{
pg_typemap_compact(&this->typemap);
FOR_EACH_MRI_TYPE( GC_COMPACT );
}

static const rb_data_type_t pg_tmbmt_type = {
"PG::TypeMapByMriType",
{
(void (*)(void*))pg_tmbmt_mark,
(void (*)(void*))-1,
(size_t (*)(const void *))NULL,
pg_compact_callback(pg_tmbmt_compact),
},
&pg_typemap_type,
0,
Expand Down
16 changes: 14 additions & 2 deletions ext/pg_type_map_by_oid.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,20 @@ pg_tmbo_mark( t_tmbo *this )
{
int i;

rb_gc_mark(this->typemap.default_typemap);
pg_typemap_mark(&this->typemap);
for( i=0; i<2; i++){
rb_gc_mark(this->format[i].oid_to_coder);
rb_gc_mark_movable(this->format[i].oid_to_coder);
}
}

static void
pg_tmbo_compact( t_tmbo *this )
{
int i;

pg_typemap_compact(&this->typemap);
for( i=0; i<2; i++){
this->format[i].oid_to_coder = rb_gc_location(this->format[i].oid_to_coder);
}
}

Expand All @@ -170,6 +181,7 @@ static const rb_data_type_t pg_tmbo_type = {
(void (*)(void*))pg_tmbo_mark,
(void (*)(void*))-1,
(size_t (*)(const void *))NULL,
pg_compact_callback(pg_tmbo_compact),
},
&pg_typemap_type,
0,
Expand Down
36 changes: 22 additions & 14 deletions ext/pg_type_map_in_ruby.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@

#include "pg.h"

static const rb_data_type_t pg_tmir_type = {
"PG::TypeMapInRuby",
{
(void (*)(void*))NULL,
(void (*)(void*))-1,
(size_t (*)(const void *))NULL,
},
&pg_typemap_type,
0,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
RUBY_TYPED_FREE_IMMEDIATELY,
#endif
};

VALUE rb_cTypeMapInRuby;
static VALUE s_id_fit_to_result;
static VALUE s_id_fit_to_query;
Expand All @@ -34,6 +20,28 @@ typedef struct {
} t_tmir;


static void
pg_tmir_compact( t_tmir *this )
{
pg_typemap_compact(&this->typemap);
this->self = rb_gc_location(this->self);
}

static const rb_data_type_t pg_tmir_type = {
"PG::TypeMapInRuby",
{
(void (*)(void*))pg_typemap_mark,
(void (*)(void*))-1,
(size_t (*)(const void *))NULL,
pg_compact_callback(pg_tmir_compact),
},
&pg_typemap_type,
0,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
RUBY_TYPED_FREE_IMMEDIATELY,
#endif
};

/*
* call-seq:
* typemap.fit_to_result( result )
Expand Down

0 comments on commit 15f1e71

Please sign in to comment.