2011-06-21 24 views
22

Yüksek düzeyde derlenmiş bir dil için bir bayt kodu yazıyoruz ve bir miktar profilleme ve optimizasyondan sonra, mevcut en büyük performans ek yükünün kullandığımız anahtar ifadesi olduğu ortaya çıktı Bayt kodu davalarına atlamak için.Etiketlerin Adresi (MSVC)

Her bir durum etiketinin adresini çekip, genellikle açtığımız yönerge kimliğinden ziyade bayt kodunun kendisinde saklamayı araştırdık. Bunu yaparsak, atlama tablosunu atlayabilir ve doğrudan o anda yürütülen komutun kodunun konumuna atlayabiliriz. Bu, GCC'de fevkalade çalışır, ancak MSVC böyle bir özelliği desteklemiyor gibi görünmektedir.

Etiketlerin adresini (ve bunlara atlamak için) almak için satır içi derlemeyi kullanmayı denedik ve satır içi montajı kullanarak MSVC iyileştiricisi tarafından tüm işlevlerden kaçınılmasına neden oluyor.

Eniyileyicinin kod üzerinde çalışmasına izin verilmesinin bir yolu var mı? Ne yazık ki, satır içi montajı etiketlerin yapıldığı yer dışındaki bir başka işleve ayıklayamayız, çünkü bir satır içi montajda bile başka bir işlev için bir etikete başvurmanın bir yolu yoktur. Herhangi bir düşünce ya da fikir? Girişiniz çok takdir edildi, teşekkürler!

+3

İşlev işaretçileri denediniz mi? –

+0

Bayt kodunda etiket adresleri yerine işlev adresleri koymaya ne dersiniz? Daha sonra her komut için bir işleviniz var. Getirme-yürütme döngüsünüz büyük etiketli işlevlerinizde değilse. –

+0

Her bir vaka için işlevler ve etiket adresleri yerine kullanılan işlev işaretçileri kullansaydım, çalışırdı.Bununla birlikte, işlev çağrısı yükü, işlev önemsiz olsa bile (hiçbir argüman, geri dönüş yok) herhangi bir performans kazancını geçersiz kılacak kadar büyük olacağını düşünüyorum. Yine de deneyeceğim ve gönderdiğiniz için teşekkürler. – Trevor

cevap

15

MSVC Bunu yapmanın tek yolu (temelde x64 için teşekkür niyetine becerir) satır içi montaj kullanmaktır:

int _tmain(int argc, _TCHAR* argv[]) 
{ 
case_1: 
    void* p; 
    __asm{ mov [p],offset case_1 } 
    printf("0x%p\n",p); 
    return 0; 
} 

böyle bir şey yapmayı planlıyorsanız, o zaman en iyi yolu yazmak olacaktır tüm yorumlayıcı, daha sonra montajcı aracılığıyla ana ikiliye bağlar (bu, LuaJIT'in yaptığıdır ve VM'nin, JIT'ed kodunu çalıştırmadığı zaman, çok hızlı bir şekilde açtığı ana sebeptir).

LuaJIT is open-source, böylece o rotayı izlerseniz ondan bazı ipuçları alabilirsiniz. Alternatif olarak, (kimin yaratıcısını geliştirmeye çalıştığınız the principle modelini geliştirdi) ileri kaynağın kaynağına bakmak isteyebilirsiniz, eğer bir MSVC yapısı varsa, nasıl başardıklarını görebilirsiniz, başka bir deyişle GCC ile (isn ') t kötü bir şey, tüm büyük platformlarda çalışır).

3

Gerçek kodları, durum etiketleri yerine işlevlere taşıyabilirsiniz. Bayt kodu daha sonra doğrudan çağrılara dönüştürülebilir. Yani Bayt kodu 1, CALL BC1'a çevrilecektir. Doğrudan aramalar oluşturduğunuzdan, işlev işaretleyicilerinin genel yüküne sahip değilsiniz. Çoğu CPU'nun boru hatları bu koşulsuz doğrudan şubeleri takip edebilir. Sonuç olarak, her bayt kodunun gerçek uygulamaları en iyi duruma getirilir ve bayt kodundan machince koduna dönüştürme önemsiz bir 1: 1 dönüşümdür. Üste | Her bir CALL, 5 bayt olduğundan (x86-32 varsayarak) biraz kod genişletme elde edersiniz, ancak büyük bir sorun olması olası değildir.