Garbage collection of DARRAY and CLASS objects.
While we're at it, provide a stub class_new runtime.
This commit is contained in:
parent
b6eb86d696
commit
a186e5ad31
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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} },
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue