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);
ret();
assignL(dst, src);
// test of copy label
{
Label sss(dst);
{
Label ttt;
ttt = src;
}
}
}
};
for (int i = 0; i < 2; i++) {
@ -823,4 +831,4 @@ CYBOZU_TEST_AUTO(doubleDefine)
}
}
} code;
}
}

View File

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