diff options
author | MITSUNARI Shigeo <[email protected]> | 2014-03-19 17:51:55 +0900 |
---|---|---|
committer | MITSUNARI Shigeo <[email protected]> | 2014-03-19 17:51:55 +0900 |
commit | 502f65aaeed053cd5edc354bd92498887c75dc99 (patch) | |
tree | d84dbe56e97a2f182e0b8334e965b3e190b028e8 | |
parent | 72cdfb80be64eabc3d0ec3992c8b55cb28032641 (diff) | |
download | xbyak-502f65aaeed053cd5edc354bd92498887c75dc99.tar.gz xbyak-502f65aaeed053cd5edc354bd92498887c75dc99.zip |
use reference counter of label
-rw-r--r-- | test/jmp.cpp | 10 | ||||
-rw-r--r-- | xbyak/xbyak.h | 48 |
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 { |