//
//<止まらないalignの再現コード> for 3.51
//
// 1)最初に先頭が偶然8KBにアライメントが合っていたとします
// +----------------+----------------+----------------+----------------+
// | ADDRESS |0x2000(top_) |0x3000 |0x4000 |
// +----------------+----------------+----------------+----------------+
// | DATA | < | |
// +----------------+----------------+----------------+----------------+
//
// 2)1バイト書き込んでからalign(8192)を呼び出します。
// +----------------+----------------+----------------+----------------+
// | ADDRESS |0x2000(top_) |0x3000 |0x4000 |
// +----------------+----------------+----------------+----------------+
// | DATA |* | | |
// +----------------+----------------+----------------+----------------+
//
// 3)4096バイト目の書き込み時にgrowかおこり、
// 今度は先頭が4KBにアライメントが合ったとします。(8KBには合ってない)
// +----------------+----------------+----------------+----------------+
// | ADDRESS |0x5000(top_) |0x6000 |0x7000 |
// +----------------+----------------+----------------+----------------+
// | DATA |****************| < |
// +----------------+----------------+----------------+----------------+
//
// 4)すると書き込もうとしている位置は8KBにアライメントが
// 合っているにもかかわらず1バイト書き込んでしまいます。(db内でgrow直後に書き込んでいるため)
// +----------------+----------------+----------------+----------------+
// | ADDRESS |0x5000(top_) |0x6000 |0x7000 |
// +----------------+----------------+----------------+----------------+
// | DATA |****************|* < |
// +----------------+----------------+----------------+----------------+
//
// 5)8196バイト目にgrowがおこり、先頭が偶然8KBにアライメントが合ったとします。
// +----------------+----------------+----------------+----------------+
// | ADDRESS |0x8000(top_) |0x9000 |0xA000 |
// +----------------+----------------+----------------+----------------+
// | DATA |****************|****************| <
// +----------------+----------------+----------------+----------------+
//
// 6)すると書き込もうとしている位置は8KBにアライメントが
// 合っているにもかかわらず1バイト書き込んでしまいます。
// +----------------+----------------+----------------+----------------+
// | ADDRESS |0x8000(top_) |0x9000 |0xA000 |
// +----------------+----------------+----------------+----------------+
// | DATA |****************|****************|* <
// +----------------+----------------+----------------+----------------+
// (以降繰り返し)
//
//
//<対処法>
//
// CodeArrayのメンバ変数にtop_align_を用意する
// private:
// size_t top_align_;
//
// CodeArrayのコンストラクタでtop_align_をALIGN_PAGE_SIZEで初期化する
// , top_align_( ALIGN_PAGE_SIZE)
//
// growMemory内の2行を以下の様に変更
// uint8 *newAllocPtr = reinterpret_cast<uint8*>(alloc_->alloc(newSize + top_align_));
// uint8 *newTop = getAlignedAddress(newAllocPtr, top_align_);
//
// CodeArray内にアライメントの要求を行う関数を用意しalign()の先頭で呼び出す。
// protected:
// void request_align( size_t align) // 名前は適当です
// {
// if(align < 1 || (align & (align - 1))) throw ERR_BAD_ALIGN;
// if(isAutoGrow() && align > top_align_) {
// // ザイズを変えずにアライメントだけ変更する
// top_align_ = align;
// uint8 *newAllocPtr = reinterpret_cast<uint8*>(alloc_->alloc(maxSize_ + top_align_));
// if (newAllocPtr == 0) throw ERR_CANT_ALLOC;
// uint8 *newTop = getAlignedAddress(newAllocPtr, top_align_);
// for (size_t i = 0; i < size_; i++) newTop[i] = top_[i];
// alloc_->free(allocPtr_);
// allocPtr_ = newAllocPtr;
// top_ = newTop;
// }
// }
//
// コレで大丈夫だと思います。
// この関数は継承先から呼び出し可能であると嬉しいです。
// Nバイトnop等、分割できないバイト列でもアライメントしてみたいので。
//
#include <stdint.h>
#include <iostream>
#include <iomanip>
#include <xbyak/xbyak.h>
namespace {
//----------------
// 例外クラス
//
class InfiniteAllocateException {};
//----------------
// 8KB/4KBアライメントのメモリを交互に返すアロケータ
//
class Alloc8K4K : public Xbyak::Allocator {
int alloc_count_;
static int const max_alloc = 15;
public:
Alloc8K4K() : alloc_count_( 0) {}
Xbyak::uint8 *alloc( size_t size) {
if( alloc_count_ > max_alloc) throw InfiniteAllocateException();
intptr_t nap, ap;
if( alloc_count_ % 2) {
// 4K
nap = reinterpret_cast< intptr_t>(new Xbyak::uint8[size + sizeof(intptr_t) + 4096 + 8192 -1]);
ap = ((nap + sizeof(intptr_t) + 8192 - 1) & ~(8192-1)) + 4096;
} else {
// 8K
nap = reinterpret_cast< intptr_t>( new Xbyak::uint8[size + sizeof(intptr_t) + 8192 -1]);
ap = (nap + sizeof(intptr_t) + 8192 - 1) & ~(8192-1);
}
*reinterpret_cast< intptr_t*>(ap - sizeof(intptr_t)) = nap; // 保管
++alloc_count_;
std::cout << std::right << std::dec;
std::cout << "alloc(" << std::setw(2) << alloc_count_ << ")";
std::cout << std::hex;
std::cout << std::setw(16) << ap;
std::cout << std::left << std::dec;
std::cout << " size = " << std::setw(16) << size;
std::cout << std::endl;
return reinterpret_cast< Xbyak::uint8*>( ap);
}
void free( Xbyak::uint8*p) {
Xbyak::uint8 *nap = reinterpret_cast< Xbyak::uint8*>( *reinterpret_cast< intptr_t*>(reinterpret_cast< intptr_t>(p) - sizeof(intptr_t)));
delete[] nap;
}
};
//----------------
// テストコード
//
class TestCode1 : Xbyak::CodeGenerator {
public:
TestCode1( Xbyak::Allocator *alc) : CodeGenerator( 4096, Xbyak::AutoGrow, alc) {
nop();
align( 8192);
std::cout << std::left << std::dec;
std::cout << "getSize()=" << getSize() << std::endl;
}
};
} // namespace
//----------------
// main
//
using namespace std;
int main() {
Alloc8K4K alc;
try {
TestCode1 *t1 = new TestCode1(&alc);
delete t1;
} catch( InfiniteAllocateException) {
cout << "Stop : Detect infinite allocation." << endl;
} catch( bad_alloc) {
cout << "Stop : Allocate error." << endl;
} catch( ...) {
cout << "Stop : Unknown error." << endl;
}
{
cout << "\nwait." << endl;
int x; cin >> x;
}
}