use reference counter of label

This commit is contained in:
MITSUNARI Shigeo 2014-03-19 17:51:55 +09:00
parent 72cdfb80be
commit 502f65aaee
2 changed files with 56 additions and 2 deletions

View File

@ -777,6 +777,14 @@ CYBOZU_TEST_AUTO(testAssign)
jne(dst, T_NEAR); jne(dst, T_NEAR);
ret(); ret();
assignL(dst, src); assignL(dst, src);
// test of copy label
{
Label sss(dst);
{
Label ttt;
ttt = src;
}
}
} }
}; };
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -823,4 +831,4 @@ CYBOZU_TEST_AUTO(doubleDefine)
} }
} }
} code; } code;
} }

View File

@ -147,6 +147,7 @@ enum {
ERR_BAD_VSIB_ADDRESSING, ERR_BAD_VSIB_ADDRESSING,
ERR_CANT_CONVERT, ERR_CANT_CONVERT,
ERR_LABEL_ISNOT_SET_BY_L, ERR_LABEL_ISNOT_SET_BY_L,
ERR_LABEL_IS_ALREADY_SET_BY_L,
ERR_INTERNAL ERR_INTERNAL
}; };
@ -194,6 +195,7 @@ public:
"bad vsib addressing", "bad vsib addressing",
"can't convert", "can't convert",
"label is not set by L()", "label is not set by L()",
"label is already set by L()",
"internal error", "internal error",
}; };
assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl)); assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl));
@ -884,11 +886,17 @@ struct JmpLabel {
inner::LabelMode mode; inner::LabelMode mode;
}; };
class LabelManager;
class Label { class Label {
mutable LabelManager *mgr;
mutable int id; mutable int id;
friend class LabelManager; friend class LabelManager;
public: public:
Label() : id(0) {} Label() : mgr(0), id(0) {}
Label(const Label& rhs);
Label& operator=(const Label& rhs);
~Label();
int getId() const { return id; } int getId() const { return id; }
// backward compatibility // backward compatibility
@ -925,8 +933,10 @@ class LabelManager {
// for Label class // for Label class
typedef XBYAK_STD_UNORDERED_MAP<int, size_t> DefinedList2; typedef XBYAK_STD_UNORDERED_MAP<int, size_t> DefinedList2;
typedef XBYAK_STD_UNORDERED_MULTIMAP<int, const JmpLabel> UndefinedList2; typedef XBYAK_STD_UNORDERED_MULTIMAP<int, const JmpLabel> UndefinedList2;
typedef XBYAK_STD_UNORDERED_MAP<int, int> RefCount;
DefinedList2 definedList2_; DefinedList2 definedList2_;
UndefinedList2 undefinedList2_; UndefinedList2 undefinedList2_;
RefCount refCount_;
/* /*
@@ --> @@.<num> @@ --> @@.<num>
@ -991,6 +1001,19 @@ class LabelManager {
*offset = i->second; *offset = i->second;
return true; return true;
} }
friend class Label;
void incRefCount(int id) { refCount_[id]++; }
void decRefCount(int id)
{
RefCount::iterator i = refCount_.find(id);
if (i == refCount_.end()) return;
if (i->second == 1) {
refCount_.erase(i);
definedList2_.erase(id);
} else {
--i->second;
}
}
public: public:
LabelManager() LabelManager()
: base_(0) : base_(0)
@ -1036,12 +1059,16 @@ public:
void define2(const Label& label) void define2(const Label& label)
{ {
define_inner(definedList2_, undefinedList2_, getId(label), base_->getSize()); define_inner(definedList2_, undefinedList2_, getId(label), base_->getSize());
refCount_[label.id] = 1;
label.mgr = this;
} }
void assign(Label& dst, const Label& src) void assign(Label& dst, const Label& src)
{ {
DefinedList2::const_iterator i = definedList2_.find(src.id); DefinedList2::const_iterator i = definedList2_.find(src.id);
if (i == definedList2_.end()) throw Error(ERR_LABEL_ISNOT_SET_BY_L); if (i == definedList2_.end()) throw Error(ERR_LABEL_ISNOT_SET_BY_L);
define_inner(definedList2_, undefinedList2_, dst.id, i->second); define_inner(definedList2_, undefinedList2_, dst.id, i->second);
refCount_[dst.id] = 1;
dst.mgr = this;
} }
bool getOffset(size_t *offset, const std::string& label) const bool getOffset(size_t *offset, const std::string& label) const
{ {
@ -1079,6 +1106,25 @@ public:
} }
}; };
inline Label::Label(const Label& rhs)
{
id = rhs.id;
mgr = rhs.mgr;
if (mgr) mgr->incRefCount(id);
}
inline Label& Label::operator=(const Label& rhs)
{
if (id) throw Error(ERR_LABEL_IS_ALREADY_SET_BY_L);
id = rhs.id;
mgr = rhs.mgr;
if (mgr) mgr->incRefCount(id);
return *this;
}
inline Label::~Label()
{
if (id && mgr) mgr->decRefCount(id);
}
class CodeGenerator : public CodeArray { class CodeGenerator : public CodeArray {
public: public:
enum LabelType { enum LabelType {