Hatena::ブログ(Diary)

新言語 Xtalを作る日記

2010-01-18

16byteアライメントを持つメンバを持つオブジェクトに対応 08:33  16byteアライメントを持つメンバを持つオブジェクトに対応を含むブックマーク

これまでxnew<T>で生成されたオブジェクトは16byteアライメントを持っていてもいなくても、関係なくmallocで取得したメモリに配置していました。

普通のnewも同様に、関係なく配置します。

なのでアライメントの問題はどうしようもないだろう、と思っていたのですが、

ゲームにおいては、16byteアライメントを持つことはよくありうる、といったこともあり、対応することにしました。

どうやって対応するか、この一週間悩んでやっと実装できました。


xnewで生成されたオブジェクトは、16byteアライメントを持つメンバがある場合16byteアライメントを保障します。

持たないオブジェクトに関してはこれまでどおりです。

#include <xmmintrin.h>

struct Vec128{
	__m128 a;
};

struct Spr{
	Vec128 v;
};

XTAL_BIND(Spr){
	it->def_var("v", &Spr::v);
}

void test(){
	Spr* p = new Spr();
	_mm_add_ps(p->v.a, p->v.a); // これは危険


	SmartPtr<Spr> s = xnew<Spr>();
	_mm_add_ps(s->v.a, s->v.a); // xnewで確保した場合は大丈夫
}

----

今回の実装の余波


AllocatorLibは次のようなインターフェイスと変更となりました。

class AllocatorLib{
public:
	virtual ~AllocatorLib(){}
	virtual void* malloc(std::size_t size);
	virtual void free(void* p, std::size_t size);

	virtual void* malloc_align(std::size_t size, std::size_t alignment);
	virtual void free_align(void* p, std::size_t size, std::size_t alignment);

	virtual void out_of_memory(){}
};

malloc_align, free_alignが増えています。

ただし、これらは実装しなくてもかまいません。デフォルトの実装でmallocを使って整列するメモリを返すようになっています。

memalignなど、もっと効率のよい関数がある場合にオーバーライドしてください。

--

また、RefCountingBase, Baseという基底クラスも修正しました。

仮想関数はすべてon_という接頭をつけた名前にリネームし、非仮想関数としました。

たとえばvirtual void rawmember();はvoid on_rawmember();となります。

デストラクタも非仮想とし、仮想関数を排除しました。

ただし、特別な仕組みを導入したため、それらは仮想関数と同様にオーバーライドできます。