aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <[email protected]>2014-03-19 17:51:55 +0900
committerMITSUNARI Shigeo <[email protected]>2014-03-19 17:51:55 +0900
commit502f65aaeed053cd5edc354bd92498887c75dc99 (patch)
treed84dbe56e97a2f182e0b8334e965b3e190b028e8
parent72cdfb80be64eabc3d0ec3992c8b55cb28032641 (diff)
downloadxbyak-502f65aaeed053cd5edc354bd92498887c75dc99.tar.gz
xbyak-502f65aaeed053cd5edc354bd92498887c75dc99.zip
use reference counter of label
-rw-r--r--test/jmp.cpp10
-rw-r--r--xbyak/xbyak.h48
2 files changed, 56 insertions, 2 deletions
diff --git a/test/jmp.cpp b/test/jmp.cpp
index a77f2ed..9263944 100644
--- a/test/jmp.cpp
+++ b/test/jmp.cpp
@@ -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;
-} \ No newline at end of file
+}
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
index d128cf9..bdf8097 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -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 {