Garbage collection of DARRAY and CLASS objects.

While we're at it, provide a stub class_new runtime.
This commit is contained in:
Stephen Williams 2012-11-17 17:20:33 -08:00
parent b6eb86d696
commit a186e5ad31
8 changed files with 119 additions and 13 deletions

View File

@ -148,6 +148,7 @@ extern bool of_MUL_WR(vthread_t thr, vvp_code_t code);
extern bool of_MULI(vthread_t thr, vvp_code_t code); extern bool of_MULI(vthread_t thr, vvp_code_t code);
extern bool of_NAND(vthread_t thr, vvp_code_t code); extern bool of_NAND(vthread_t thr, vvp_code_t code);
extern bool of_NANDR(vthread_t thr, vvp_code_t code); extern bool of_NANDR(vthread_t thr, vvp_code_t code);
extern bool of_NEW_COBJ(vthread_t thr, vvp_code_t code);
extern bool of_NEW_DARRAY(vthread_t thr, vvp_code_t code); extern bool of_NEW_DARRAY(vthread_t thr, vvp_code_t code);
extern bool of_NOOP(vthread_t thr, vvp_code_t code); extern bool of_NOOP(vthread_t thr, vvp_code_t code);
extern bool of_NOR(vthread_t thr, vvp_code_t code); extern bool of_NOR(vthread_t thr, vvp_code_t code);

View File

@ -196,7 +196,8 @@ static const struct opcode_table_s opcode_table[] = {
{ "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%new/darray",of_NEW_DARRAY,2,{OA_BIT1, OA_STRING, OA_NONE} }, { "%new/cobj", of_NEW_COBJ, 0, {OA_NONE,OA_NONE, OA_NONE} },
{ "%new/darray",of_NEW_DARRAY,2, {OA_BIT1,OA_STRING, OA_NONE} },
{ "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },

View File

@ -26,6 +26,7 @@
# include "vpi_priv.h" # include "vpi_priv.h"
# include "statistics.h" # include "statistics.h"
# include "vvp_cleanup.h" # include "vvp_cleanup.h"
# include "vvp_object.h"
# include <cstdio> # include <cstdio>
# include <cstdlib> # include <cstdlib>
# include <cstring> # include <cstring>
@ -197,6 +198,8 @@ void set_delay_selection(const char* sel)
static void final_cleanup() static void final_cleanup()
{ {
vvp_object::cleanup();
/* /*
* We only need to cleanup the memory if we are checking with valgrind. * We only need to cleanup the memory if we are checking with valgrind.
*/ */

View File

@ -47,7 +47,7 @@ int __vpiDarrayVar::vpi_get(int code)
vvp_fun_signal_object*fun = dynamic_cast<vvp_fun_signal_object*> (get_net()->fun); vvp_fun_signal_object*fun = dynamic_cast<vvp_fun_signal_object*> (get_net()->fun);
assert(fun); assert(fun);
vvp_object_t val = fun->get_object(); vvp_object_t val = fun->get_object();
vvp_darray*aval = dynamic_cast<vvp_darray*> (val); vvp_darray*aval = val.peek<vvp_darray>();
switch (code) { switch (code) {
case vpiSize: case vpiSize:

View File

@ -167,6 +167,7 @@ struct vthread_s {
{ {
assert(stack_obj_.size() > 0); assert(stack_obj_.size() > 0);
vvp_object_t val = stack_obj_.back(); vvp_object_t val = stack_obj_.back();
stack_obj_.back().reset();
stack_obj_.pop_back(); stack_obj_.pop_back();
return val; return val;
} }
@ -2097,7 +2098,7 @@ bool of_DELETE_OBJ(vthread_t thr, vvp_code_t cp)
{ {
/* set the value into port 0 of the destination. */ /* set the value into port 0 of the destination. */
vvp_net_ptr_t ptr (cp->net, 0); vvp_net_ptr_t ptr (cp->net, 0);
vvp_send_object(ptr, 0, thr->wt_context); vvp_send_object(ptr, vvp_object_t(), thr->wt_context);
return true; return true;
} }
@ -3193,7 +3194,7 @@ bool of_LOAD_DAR(vthread_t thr, vvp_code_t cp)
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun); vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj); assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*>(obj->get_object()); vvp_darray*darray = obj->get_object().peek<vvp_darray>();
assert(darray); assert(darray);
vvp_vector4_t word; vvp_vector4_t word;
@ -3217,7 +3218,7 @@ bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t cp)
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun); vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj); assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*> (obj->get_object()); vvp_darray*darray = obj->get_object().peek<vvp_darray>();
assert(darray); assert(darray);
double word; double word;
@ -3236,7 +3237,7 @@ bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t cp)
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun); vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj); assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*> (obj->get_object()); vvp_darray*darray = obj->get_object().peek<vvp_darray>();
assert(darray); assert(darray);
string word; string word;
@ -4066,6 +4067,12 @@ bool of_NAND(vthread_t thr, vvp_code_t cp)
return cp->opcode(thr, cp); return cp->opcode(thr, cp);
} }
bool of_NEW_COBJ(vthread_t thr, vvp_code_t cp)
{
vvp_object_t tmp;
thr->push_object(tmp);
return true;
}
bool of_NEW_DARRAY(vthread_t thr, vvp_code_t cp) bool of_NEW_DARRAY(vthread_t thr, vvp_code_t cp)
{ {
@ -4659,7 +4666,7 @@ bool of_SET_DAR(vthread_t thr, vvp_code_t cp)
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun); vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj); assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*>(obj->get_object()); vvp_darray*darray = obj->get_object().peek<vvp_darray>();
assert(darray); assert(darray);
darray->set_word(adr, value); darray->set_word(adr, value);
@ -4904,7 +4911,7 @@ bool of_STORE_DAR_R(vthread_t thr, vvp_code_t cp)
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun); vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj); assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*>(obj->get_object()); vvp_darray*darray = obj->get_object().peek<vvp_darray>();
assert(darray); assert(darray);
darray->set_word(adr, value); darray->set_word(adr, value);
@ -4927,7 +4934,7 @@ bool of_STORE_DAR_STR(vthread_t thr, vvp_code_t cp)
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun); vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj); assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*>(obj->get_object()); vvp_darray*darray = obj->get_object().peek<vvp_darray>();
assert(darray); assert(darray);
darray->set_word(adr, value); darray->set_word(adr, value);
@ -5119,7 +5126,7 @@ bool of_TEST_NUL(vthread_t thr, vvp_code_t cp)
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun); vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj); assert(obj);
if (obj->get_object() == 0) if (obj->get_object().test_nil())
thr_put_bit(thr, 4, BIT4_1); thr_put_bit(thr, 4, BIT4_1);
else else
thr_put_bit(thr, 4, BIT4_0); thr_put_bit(thr, 4, BIT4_0);

View File

@ -691,7 +691,6 @@ void vvp_fun_signal_object_sa::recv_object(vvp_net_ptr_t ptr, vvp_object_t bit,
assert(ptr.port() == 0); assert(ptr.port() == 0);
if (needs_init_ || value_ != bit) { if (needs_init_ || value_ != bit) {
if (value_) delete value_;
value_ = bit; value_ = bit;
needs_init_ = false; needs_init_ = false;

View File

@ -24,8 +24,15 @@
using namespace std; using namespace std;
int vvp_object::total_active_cnt_ = 0;
void vvp_object::cleanup(void)
{
}
vvp_object::~vvp_object() vvp_object::~vvp_object()
{ {
total_active_cnt_ -= 1;
} }
vvp_darray::~vvp_darray() vvp_darray::~vvp_darray()

View File

@ -23,15 +23,103 @@
# include <string> # include <string>
# include <vector> # include <vector>
typedef class vvp_object*vvp_object_t;
class vvp_vector4_t; class vvp_vector4_t;
class vvp_object_t;
/*
* A vvp_object is a garbage collected object such as a darray or
* class object. The vvp_object class is a virtual base class and not
* generally used directly. Instead, use the vvp_object_t object as a
* smart pointer. This makes garbage collection automatic.
*/
class vvp_object { class vvp_object {
public: public:
inline vvp_object() { } inline vvp_object() { total_active_cnt_ += 1; }
virtual ~vvp_object() =0; virtual ~vvp_object() =0;
static void cleanup(void);
private:
friend class vvp_object_t;
int ref_cnt_;
static int total_active_cnt_;
}; };
class vvp_object_t {
public:
inline vvp_object_t() : ref_(0) { }
vvp_object_t(const vvp_object_t&that);
~vvp_object_t();
vvp_object_t& operator = (const vvp_object_t&that);
vvp_object_t& operator = (class vvp_object*that);
void reset(vvp_object*tgt = 0);
bool test_nil() const { return ref_ == 0; }
inline bool operator == (const vvp_object_t&that) const
{ return ref_ == that.ref_; }
inline bool operator != (const vvp_object_t&that) const
{ return ref_ != that.ref_; }
template <class T> T*peek(void) const;
private:
class vvp_object*ref_;
};
inline vvp_object_t::vvp_object_t(const vvp_object_t&that)
{
ref_ = that.ref_;
if (ref_) ref_->ref_cnt_ += 1;
}
inline vvp_object_t::~vvp_object_t()
{
reset(0);
}
/*
* This is the workhorse of the vvp_object_t class. It manages the
* pointer to the referenced object.
*/
inline void vvp_object_t::reset(class vvp_object*tgt)
{
if (tgt) tgt->ref_cnt_ += 1;
if (ref_) {
ref_->ref_cnt_ -= 1;
if (ref_->ref_cnt_ <= 0) delete ref_;
ref_ = 0;
}
ref_ = tgt;
}
inline vvp_object_t& vvp_object_t::operator = (const vvp_object_t&that)
{
if (this == &that) return *this;
reset(that.ref_);
return *this;
}
inline vvp_object_t& vvp_object_t::operator = (class vvp_object*that)
{
reset(that);
return *this;
}
/*
* This peeks at the actual pointer value in the form of a derived
* class. It uses dynamic_cast<>() to convert the pointer to the
* desired type.
*
* NOTE: The vvp_object_t object retains ownership of the pointer!
*/
template <class T> inline T*vvp_object_t::peek(void) const
{
return dynamic_cast<T*> (ref_);
}
class vvp_darray : public vvp_object { class vvp_darray : public vvp_object {
public: public: