تحليل الهروب
في تحسين أداء المترجمات ، يُعد تحليل الهروب طريقة لتحديد النطاق الديناميكي للمؤشرات - أي المكان الذي يمكن الوصول فيه إلى مؤشر ما في البرنامج. وهو يرتبط بتحليل المؤشرات وتحليل الشكل .
عند تخصيص متغير (أو كائن) في روتين فرعي ، يمكن لمؤشر هذا المتغير أن ينتقل إلى مسارات تنفيذ أخرى ، أو إلى الروتينات الفرعية المستدعِية. إذا كان التطبيق يستخدم تحسين استدعاء الذيل (وهو أمر مطلوب عادةً في اللغات الوظيفية )، فقد تُعتبر الكائنات أيضًا وكأنها تنتقل إلى الروتينات الفرعية المستدعَية . إذا كانت اللغة تدعم الاستمراريات من الدرجة الأولى (كما هو الحال في لغتي Scheme و Standard ML of New Jersey )، فقد تنتقل أجزاء من مكدس الاستدعاءات أيضًا.
إذا قام روتين فرعي بتخصيص كائن وأعاد مؤشرًا إليه، فيمكن الوصول إلى هذا الكائن من أماكن غير محددة في البرنامج - أي أن المؤشر قد "تجاوز" حدود البرنامج. ويمكن للمؤشرات أيضًا أن تتجاوز حدود البرنامج إذا تم تخزينها في متغيرات عامة أو هياكل بيانات أخرى تتجاوز بدورها حدود الإجراء الحالي.
يحدد تحليل الهروب جميع الأماكن التي يمكن تخزين المؤشر فيها وما إذا كان من الممكن إثبات أن عمر المؤشر يقتصر فقط على الإجراء الحالي و/أو الخيط الحالي.
التحسينات
يمكن للمترجم استخدام نتائج تحليل الهروب كأساس للتحسينات: [ 1 ]
- تحويل تخصيصات الذاكرة الديناميكية إلى تخصيصات الذاكرة المكدسة . [ 2 ] إذا تم تخصيص كائن في روتين فرعي، ولم يتم تحرير مؤشر إلى هذا الكائن، فقد يكون هذا الكائن مرشحًا لتخصيص الذاكرة المكدسة بدلًا من تخصيص الذاكرة الديناميكية. في اللغات التي تستخدم جمع البيانات المهملة، يمكن أن يقلل هذا من عدد مرات تشغيل جامع البيانات المهملة.
- حذف التزامن . إذا تم العثور على كائن يمكن الوصول إليه من خيط واحد فقط، فيمكن إجراء العمليات على الكائن دون تزامن.
- تجزئة الكائنات أو استبدالها بقيم عددية . [ 3 ] قد يُكتشف إمكانية الوصول إلى كائن ما بطرق لا تتطلب وجوده كبنية ذاكرة تسلسلية. وهذا قد يسمح بتخزين أجزاء من الكائن (أو كله) في سجلات وحدة المعالجة المركزية بدلاً من الذاكرة.
الاعتبارات العملية
في لغات البرمجة كائنية التوجه ، تُعدّ المترجمات الديناميكية خيارًا مثاليًا لإجراء تحليل الهروب. في الترجمة الثابتة التقليدية ، قد يُعيق تجاوز الدوال إجراء تحليل الهروب، إذ يُمكن تجاوز أي دالة مُستدعاة بنسخة تسمح بتجاوز المؤشر. تستطيع المترجمات الديناميكية إجراء تحليل الهروب باستخدام المعلومات المتاحة حول التحميل الزائد، وإعادة التحليل عند تجاوز الدوال ذات الصلة بواسطة تحميل الكود الديناميكي. [ 1 ]
أدت شعبية لغة البرمجة جافا إلى جعل تحليل الهروب هدفًا ذا أهمية. فمزيج جافا من تخصيص الكائنات في الذاكرة الديناميكية فقط، والترابط المدمج، ومترجم Sun HotSpot الديناميكي، ومترجم OpenJ9 الفوري (JIT)، يُشكل منصةً مثاليةً لتحسينات تحليل الهروب (انظر: تحليل الهروب في جافا ). يُطبَّق تحليل الهروب في جافا الإصدار القياسي 6. تدعم بعض آلات جافا الافتراضية (JVMs) نوعًا أقوى من تحليل الهروب يُسمى تحليل الهروب الجزئي ، والذي يُتيح استبدال الكائن المُخصَّص بقيم عددية حتى لو هرب الكائن في بعض مسارات الدالة. [ 4 ]
مثال (جافا)
class Main { public static void main ( String [] args ) { example (); } public static void example () { Foo foo = new Foo (); //alloc Bar bar = new Bar (); //alloc bar . setFoo ( foo ); } }class Foo {}class Bar { private Foo foo ; public void setFoo ( Foo foo ) { this . foo = foo ; } }في هذا المثال، يتم إنشاء كائنين (مع تعليق باستخدام alloc)، ويُمرر أحدهما كوسيط إلى دالة في كائن آخر. setFoo()تخزن الدالة مرجعًا إلى كائن Foo المُستلم. لو كان كائن Bar موجودًا في الذاكرة الديناميكية (heap)، لكان مرجع Foo قد تم تجاوزه. ولكن في هذه الحالة، يستطيع المُصرّف، من خلال تحليل التجاوز، تحديد أن كائن Bar نفسه لا يتجاوز استدعاء الدالة example(). ونتيجةً لذلك، لا يمكن لمرجع Foo تجاوزه أيضًا، وبالتالي يستطيع المُصرّف تخصيص كلا الكائنين بأمان على المكدس (stack).
أمثلة (مخطط)
في المثال التالي، لا ينتقل المتجه p إلى g ، لذلك يمكن تخصيصه على المكدس ثم إزالته من المكدس قبل استدعاء g .
( define ( f x ) ( let (( p ( make-vector 10000 ))) ( fill-vector-with-good-stuff p ) ( g ( vector-ref p 7023 ))))لكن لو كنا قد
( define ( f x ) ( let (( p ( make-vector 10000 ))) ( fill-vector-with-good-stuff p ) ( g p )))عندئذٍ إما أن يتم تخصيص p على الكومة أو (إذا كان g معروفًا للمترجم عند تجميع f ، ويتصرف بشكل جيد) يتم تخصيصه على المكدس بطريقة تسمح له بالبقاء في مكانه عند استدعاء g .
إذا تم استخدام الاستمراريات لتنفيذ هياكل تحكم شبيهة بالاستثناءات، فغالبًا ما يمكن لتحليل الهروب اكتشاف ذلك لتجنب الحاجة إلى تخصيص استمرار فعلي ونسخ مكدس الاستدعاءات إليه. على سبيل المثال، في
يقرأ كائنات المخطط التي أدخلها المستخدم. إذا كانت جميعها أرقامًا، فإنه يُرجع قائمة تحتوي عليها جميعًا بالترتيب. إذا أدخل المستخدم كائنًا ليس رقمًا، فإنه يُرجع #f مباشرةً. ( define ( getnumlist ) ( call/cc ( lambda ( continuation ) ( define ( get-numbers ) ( let (( next-object ( read ))) ( cond (( eof-object? next-object ) ' ()) (( number? next-object ) ( cons next-object ( get-numbers ))) ( else ( continuation #f ))))) ( get-numbers ))))سيحدد تحليل الهروب أن الاستمرار الذي تم التقاطه بواسطة call/cc لا يهرب، لذلك لا حاجة لتخصيص بنية استمرار، ويمكن تنفيذ استدعاء الاستمرار عن طريق استدعاء الاستمرار عن طريق فك المكدس.
انظر أيضاً
مراجع
- 1 2 T. Kotzmann و H. Mössenböck، "تحليل الهروب في سياق التجميع الديناميكي وإلغاء التحسين"، في وقائع المؤتمر الدولي الأول ACM/USENIX حول بيئات التنفيذ الافتراضية، نيويورك، نيويورك، الولايات المتحدة الأمريكية، 2005، ص 111-120.
- ↑ بلانشيه، برونو (نوفمبر 2003). "تحليل الهروب في جافا™: النظرية والتطبيق" . معاملات ACM في لغات البرمجة والأنظمة . 25 (6): 713-775 . doi : 10.1145/945885.945886 . ISSN 0164-0925 .
- ↑ كوتزمان، توماس؛ موسنبوك، هانزبيتر (مارس 2007). "دعم وقت التشغيل لعمليات التحسين القائمة على تحليل الهروب". الندوة الدولية حول توليد الشفرة وتحسينها (CGO'07) . الصفحات 49-60 . CiteSeerX 10.1.1.394.5944 . doi : 10.1109/CGO.2007.34 . ISBN 978-0-7695-2764-2. S2CID 16011497 .
- ↑ ستادلر، لوكاس؛ وورثينجر، توماس؛ موسنبوك، هانزبيتر (2014). "تحليل الهروب الجزئي والاستبدال القياسي للغة جافا". وقائع الندوة الدولية السنوية المشتركة بين معهد مهندسي الكهرباء والإلكترونيات ورابطة مكائن الحوسبة حول توليد الشفرة وتحسينها - CGO '14 . الصفحات 165-174 . doi : 10.1145/2581122.2544157 . ISBN 9781450326704.
- تحليل البرامج الثابتة
