کد ریسه‌ای

در علوم رایانه، کد ریسه‌ای (انگلیسی: Threaded Code) به روش برنامه‌نویسی اطلاق می‌شود که در آن، تمامی کد، یا حداقل اکثریت آن، از فراخوانی رویه‌ها تشکیل شده است. در حالت کلی این روش از برنامه‌نویسی در کامپایلر‌هایی یافت می‌شود که یا خروجی کامپایل آنها به صورت کد ریسه‌ای باشد و یا آنکه پیاده‌سازی کد خود کامپایلر به صورت ریسه‌ای صورت گرفته باشد.
یکی از مهم‌ترین بده‌بستان‌ها در علوم و مهندسی کامپیوتر، مسئله تقابل زمان و حافظه می‌باشد. در این روش سعی بر آن است تا چگالی و حجم کد اشغال شده در ازای افزایش زمان اجرای آن، کاهش پیدا کند. در برخی مواقع این کاهش حجم کد منجر به آن می‌شود که کل کد در حافظه نهان پردازنده قرار گیرد و در این صورت، استفاده از کد ریسه‌ای و کاهش حجم کد منجر به کاهش زمان اجرای آن می‌شود.
از کد ریسه‌ای در طراحی کامپایلر برخی زبان‌های برنامه‌نویسی از جمله Forth و همچنین برخی از پیاده‌سازی‌های بیسیک و کوبول استفاده می‌شود.
تاریخچه و معرفی
رایانه‌های اولیه حافظه به نسبت بسیار کمی داشتند که بعضا در حد چند کیلوبایت می‌بود و در نتیجه معضل اساسی، یافتن روشی برای کم حجم‌تر کردن کد بود تا بتواند در حافظه ذخیره گردد. از طرف دیگر سرعت رایانه‌ها بسیار کم بود و زمان اجرای کد ماشین بسیار سریعتر از تفسیر عادی کد بود. در اینجا بود که نوشتن توابع و زیرروال‌ها فراگیر شد و به برنامه‌نویسان امکان این را می‌داد که ضمن کاستن از حجم کد، اجرای برنامه‌ها را از طریق کد ماشین تسریع بخشند. چارلز مور روش ریسه‌ای غیرمستقیم را در سال ۱۹۷۰ ابداع کرد ولی جیمز بل در سال ۱۹۷۳ نخستین مقاله مرتبط با این روش را به چاپ رسانید. اصلی‌ترین کاربرد این روش در تولید و پیاده‌سازی مفسرهای ماشین مجازی می‌باشد.
عملکرد
در این بخش عملکرد کد ریسه‌ای را به صورت کلی و به همراه مثال توضیح می‌دهیم. فرض کنید کدی داریم که شامل سه دستورالعمل ماشین مجازی B ،A و C باشد. می‌توانیم برای اجرای این سه دستورالعمل، توابع سطح ماشینی به نام‌های Br ،Ar و Cr را تعریف کنیم و با استفاده از آنها کد مقابل را تولید کنیم.
call Ar
call Br
call Cr
حال با حذف تابع call کد را بازنویسی می‌کنیم.
Ar
Br
Cr
کد جدید در واقع دنباله‌ای از آدرس‌های کدی می‌باشد که دستورالعمل‌های ماشین را نشان می‌دهند. در نتیجه برای اجرای این تکه کد، نمی‌توانیم به ابتدای آن پرش کنیم. همچنین باید با استفاده از اشاره‌گری در یک ثبات، جدا از ثبات‌های PC و RA، به دستورالعمل فعلی اشاره کنیم. برای این منظور از ثبات اشاره‌گر دستورالعمل (IP) استفاده می‌کنیم. فرض می‌کنیم که IP به کلمه‌ای از دنباله‌ی کدها که دقیقا بعد از کلمه دستورالعمل فعلی قرار دارد اشاره می‌کند. حال کافی است تا تنها کلمه را بارگیری کرده و با افزایش مقدار آن به اندازه یک کلمه، به رویه‌ای که بدان اشاره می‌کند پرش کنیم. کد مقابل نحوه این عملیات را در زبان اسمبلی MIPS نشان می‌دهد.
lw $2,0($4) #get next instruction, $4=inst.ptr.
addu $4,$4,4 #advance instruction pointer
j $2 #execute next instruction
nop #branch delay slot
به متد بالا NEXT نیز گفته می‌شود. این روش اولین بار در مقاله‌ای توسط بل ارائه شد.
مدل‌های ریسیدن
در اینجا به تبیین برخی از مدل‌های کد ریسه‌ای می‌پردازیم.
ریسیدن مستقیم
آدرس‌های موجود در ریسه همان آدرس‌های زبان ماشین می‌باشند. این مدل در عین سادگی می‌تواند سربارهایی نیز داشته باشد زیرا از آنجایی که تنها از آدرس‌های ماشین در آن استفاده شده است، برای ورودی دادن پارامترها، باید آنها را به صورت غیرمستقیم از حافظه بارگیری کرد. خروجی این مدل حجمی در حدود یک هشتم تا یک چهارم کد کامپایل شده دارد.
ریسیدن غیرمستقیم
در این مدل از اشاره‌گرهایی استفاده می‌شود که به مکان‌هایی اشاره می‌کنند که آن مکان‌ها خود به کد ماشین اشاره می‌کنند. ممکن است بعد از اشاره‌گر غیرمستقیم تعدادی عملوند که به جای ریسه در بلوک غیرمستقیم ذخیره شده‌اند، نیز قرار داشته باشد. کدهای تولید شده توسط این روش معمولا کم حجم‌تر از کدهای تولید شده توسط روش ریسیدن مستقیم می‌باشند اما غالبا کندتر نیز می‌باشند.
ریسیدن زیرروالی
در این مدل توالی‌ای از دستورالعمل‌های call در زبان ماشین استفاده می‌شود. کامپایلرهای اولیه برای زبان‌هایی همچون فورترن و کوبول از این مدل استفاده می‌کردند. خروجی این مدل و دو مدل ارائه شده در بالا، حجمی در حدود یک هشتم تا یک چهارم کد کامپایل شده دارد.
ریسیدن نشانه‌ای
در این مدل لیستی از نمایه‌های ۸ یا ۱۲ بیتی به جدولی از اشاره‌گرها استفاده می‌شود. این روش معمولا فشرده شده می‌باشد و حجم کد تولیدی آن چیزی حدود ۵۰ تا ۷۵ درصد کد تولید شده توسط مدل‌های دیگر می‌باشد.
ویژگی‌های مشترک
به صورت معمول در یک ماشین مجازی ریسه‌ای چهار ثبات وجود دارند که عبارتند از:
ip یا همان instruction pointer که همان اشاره‌گر به دستورالعمل می‌باشد.
w یا work.
rp یا return pointer.
sp یا stack pointer که برای ارسال پارامترها بین کلمات استفاده می‌شود.