Design: استمرار

تم إنشاؤها على ٧ يناير ٢٠١٩  ·  38تعليقات  ·  مصدر: WebAssembly/design

قد تكون بعض الطرق لحفظ حالة تنفيذ WebAssembly واستعادتها لاحقًا مفيدة من أجل حظر واجهات برمجة التطبيقات (API) إلى الأنظمة الأساسية التي تكون واجهات برمجة التطبيقات المكافئة لها غير متزامنة ، وخاصة الويب نفسه ، والذي يعتمد بشكل كبير على واجهات برمجة التطبيقات غير المتزامنة. فقط شكل محدود للغاية من الاستمرارية سيكون ضروريًا لفتح مجموعة واسعة من الاحتمالات.

يؤدي البحث عن "استمرار" في أداة تعقب المشكلات إلى rossberg التي https://github.com/WebAssembly/design/issues/ 796 # issuecomment -403487395 ، https://github.com/WebAssembly/design/issues/919#issuecomment -349038338 ، https://github.com/WebAssembly/design/issues/1171#issuecomment -355967209. يبدو أنه لا يوجد أي ذكر للميزة على موقع الويب ، ولا توجد مشكلة مخصصة في هذا المستودع ، لذلك أود أن أسأل - ما هي الحالة هنا؟

التعليق الأكثر فائدة

كمتابعة لبعض تعليقاتي أعلاه ، من المحتمل أن أقوم بالربط مع عرضي التقديمي من اجتماع فبراير 2020 ، مع عرض أفكار لإضافة معالجات تبديل المكدس / coroutines / الاستمرارية / التأثير إلى Wasm .

ال 38 كومينتر

أعتقد أنه سيتم تنفيذ هذه الميزات كامتداد (تعميم) لدعم معالجة الاستثناءات ، بحيث يكون الانتهاء على الأرجح حيث يكون التركيز الحالي.

أوافق على أنه سيكون من الجيد الحصول على المزيد من خارطة الطريق لما سيأتي بعد ذلك ، نعم.

كان هناك بعض الوصف لهذا هنا ، على الرغم من تغيير اقتراح معالجة الاستثناءات منذ ذلك الحين ، لذلك ربما لم يعد مناسبًا بعد الآن. ربماrossberg وaheejin يمكن أن توفر مزيد من المعلومات.

يعمل بعض الأشخاص بيننا حاليًا على تصميم تجريبي يعمم اقتراح الاستثناء الحالي مع الاستئناف ، مما ينتج عنه معالجات التأثير المكافئة ، والتي هي شكل منظم وقابل للطباعة من الاستمرارية المحددة. لدينا دلالات أساسية ولكن من السابق لأوانه تقديم اقتراح. ستكون الخطوات التالية هي وضع نماذج أولية لها في المترجم المرجعي وتجربة التصميم وربما بعض المنتجين (كمنتج جانبي ، سيؤدي ذلك إلى تنفيذ مرجعي وبوكيل مواصفات لاقتراح الاستثناء).

ولكن بغض النظر عن تفاصيل التصميم ، فإن الآلية الأساسية لإنشاء مجموعات تنفيذ متعددة وإدارتها والتبديل بينها لا تتم إضافتها بسهولة إلى الأجهزة الافتراضية الموجودة ، على أقل تقدير. ستكون هذه هي العقبة الأكبر بكثير. هناك بعض الاهتمام على سبيل المثال بفريق V8 ، لكنني أتوقع أن تنفيذه وتقييم قابلية الأداء سيستغرق وقتًا طويلاً.

لقد طال هذا التعليق بعض الشيء ، لكن احمل معي ، أعدك أنه مفيد تمامًا:

أنا أعمل حاليًا على تطبيق بديل لـ Erlang يعتمد على التجميع المسبق بدلاً من تفسير الرموز الثنائية ؛ الهدف الأساسي هو WebAssembly ، ولكن سيتم دعم الأهداف الأخرى في النهاية لدعم الاستخدام كمترجم شفرة أصلي عام للغات BEAM. لتنفيذ اللغة والمترجم ، يجب تلبية بعض المتطلبات الأساسية:

  • مكالمات الذيل المناسبة ، نظرًا لاستخدام العودية بكثرة في اللغة ، لا توجد وسيلة أخرى للتعبير عن التكرار
  • عائدات غير محلية رخيصة ، يستخدم Erlang throw بشكل شائع لتبسيط الكود الذي يحتاج إلى الخروج مبكرًا ، أو للسماح بإرجاع قيمة من أعماق مكدس المكالمات ؛ إنه ليس شيئًا يستخدم للاستثناءات فقط
  • جدولة استباقية زائفة (يتم تنفيذها كجدولة تعاونية في وقت التشغيل ، ولكنها تبدو وقائية من كود Erlang) ، والتي تُستخدم لتنفيذ الخيوط الخضراء (تسمى العمليات في Erlang)
  • جمع القمامة لكل عملية ؛ مهم للأداء ، خاصة لتجنب توقف العالم عن التجميع. في كثير من الحالات ، تموت عمليات Erlang قبل أن يتم تنفيذ GC لتلك العملية ، مما يعني أن مساحات كبيرة من الذاكرة لا تحتاج أبدًا إلى المسح الضوئي على الإطلاق.

لبناء مترجم في وقت مبكر يلبي هذه المتطلبات ، اخترت استخدام أسلوب تمرير المتابعة كما هو موضح في تشيني في MTA والذي يوفر حلاً يلبي كل مطلب بأناقة. باختصار ، إليك وصفًا لكيفية عمله وكيف يحل مشاكلي كمنفذ للغة:

  • يتم تحويل البرنامج إلى نموذج CPS. في شكل CPS ، وفي هذه النكهة على وجه الخصوص ، تكون كل مكالمة في موضع الذيل ، ويتلقى المستدعي عودة واستمرارًا للهروب (ما يسمى استمرار "البرميل المزدوج") بالإضافة إلى أي حجج.
  • نظرًا لعدم عودة أي استدعاء ، ستنفجر المكدس في النهاية ، ولكن الحيلة المستخدمة في _Cheney على MTA_ هي أن نقطة الإدخال تأخذ عنوان مؤشر المكدس ، وتستخدمه للتحقق بشكل دوري (عادةً كل استدعاء دالة) لتحديد ما إذا كان المكدس على وشك نفاد المساحة. عند حدوث ذلك ، يتم نقل القيم الحية على المكدس إلى الكومة ، جنبًا إلى جنب مع الاستمرار الحالي ، ويتم استخدام longjmp للقفز مرة أخرى إلى نقطة الدخول (التي تعمل بمثابة ترامبولين). يؤدي هذا إلى إعادة تعيين المكدس بشكل فعال إلى المربع الأول ، مع القليل جدًا من النفقات العامة.
  • تمنحنا القفزة أيضًا فرصة لأداء جمع القمامة ، والجدولة ، وكنتيجة لإعادة ضبط المكدس ، يضمن أن المكالمات الخلفية لا تنفخ المكدس أبدًا. يمكن إضافة نقاط عائد إضافية أعلى من الحالة الحالية لمؤشر المكدس ، مثل حساب التخفيض (كيف يحدد Erlang وقت استباق مؤشر الترابط الأخضر) ، أو تحديد ما إذا كانت هناك حاجة إلى مجموعة قمامة رئيسية.
  • يعني استخدام الاستمرارية أننا نحصل بسهولة على عوائد غير محلية رخيصة
  • يعني استخدام الاستمرارية أنه من السهل تعليق خيط أخضر واستئناف خيط آخر

لا يتطلب أي مما وصفته أعلاه فعليًا دعمًا صريحًا للاستمرار من الجهاز - فهو يتطلب فقط بعض الوسائل التي يمكن من خلالها التحقق من حجم المكدس (والذي لدينا بالفعل حلول لهذا اليوم ، إذا كان اختراقًا بسيطًا) وشيء مثل setjmp / longjmp للسماح بإعادة لف المكدس بثمن بخس.

من البحث الذي أجريته حتى الآن ، فإن استخدام setjmp / longjmp في WebAssembly عبر استثناءات JS يأتي بعقوبة أداء كبيرة ، وهو في الأساس مجرد لوحة توافق. هذا يجعل أي لغة تستخدم تشيني في أسلوب التجميع بنمط MTA بطيئة بلا داع. من الأمثلة المعروفة إلى حد ما على مثل هذه اللغة مشروع Chicken Scheme ، وأعتقد أن Chez Scheme يستخدم أيضًا نفس الحيلة ، إن لم يكن نفس الحيلة.

أحد البدائل هو استخدام الترامبولين - على سبيل المثال بدلاً من longjmp عندما تكون المكدس على وشك النفخ أو عند الحاجة إلى نقطة عائد ، يقوم المترجم بإنشاء رمز يعود إلى الترامبولين في كل مرة يحتاج فيها المرء لاستدعاء الاستمرارية التالية. المشكلة بالطبع هي أنها تتطلب عودة + استدعاء دالة إضافية لكل متابعة تسمى ؛ ومع ذلك ، أظن أن هذا أفضل اليوم في WebAssembly مقابل الاختراق الحالي setjmp / longjmp . يمكن للمرء أيضًا استخدام return صريحًا لفك المكدس ، لكنني أظن أنه أبطأ من الحل setjmp / longjmp .

كل هذا لأقوله ، أعتقد أن هناك حاجة إلى شيء ما لجعل تطبيق اللغات ذات المتطلبات المماثلة ممكنًا وفعالًا. ربما يعني ذلك نوعًا من دعم الاستمرار الأصلي ، أو ربما يعني شيئًا أقل قوة ، مثل دعم النمط setjmp الذي وصفته بشكل أفضل. أريد أن أوضح أن هذه ليست مجرد مشكلة خاصة بتطبيقي - فمجموعة اللغات التي لديها أو قد تحتوي على هذه المتطلبات بها بعض الأعضاء غير التافهين ، على سبيل المثال Haskell ، أي تنفيذ للمخطط المطابق للمعايير ، و Erlang (و BEAM) بشكل عام) ، وأي لغة تعتمد على دعم الاتصال الذيل المناسب ، وليس فقط الإصدار المحدود الذي أصبح ممكنًا بفضل اصطلاح استدعاء fastcc.

rossberg هل هناك مكان يمكنني فيه مراجعة الرسم التقريبي لما تعمل عليه مع اقتراح الاستثناء + الاستئناف؟ أرغب في البحث ومعرفة ما إذا كان يحمل حلاً بالنسبة لي أم لا. إذا كان الأمر كذلك ، ويمكنني تقديم أي مساعدة ، يسعدني أن أحاول تقديم المساعدة أيضًا لمواصلة المضي قدمًا.

إذا كان لديك أي أسئلة (أو حتى اقتراحات!) حول ما سبق ، فأخبرني بالتأكيد!

bitwalker ما هو غير واضح بالنسبة لي من الخيارات التي تصفها:

  • يعني استخدام longjmp أنك تستخدم مكدس wasm الفعلي (الذي ليس تحت سيطرتك) ، مما يعني أنه ليس لديك طريقة لتحديد مقدار ما تستخدمه ومتى توشك على نفاد مساحة المكدس ، حاليا؟
  • إذا استخدمت بدلاً من ذلك "حزمة الظل" في الذاكرة الخطية لتخزين إطارات المكدس ، فيمكنك إعادة تعيينها دون استخدام longjmp ، بافتراض أنك لا تستخدم وظائف wasm لتنفيذ الوظائف في لغتك ، ولكن بدلاً من ذلك كل الجثث تعيش داخل مبنى ضخم من أجل (؛ ؛) تبديل (..). قد يكون هذا أبطأ لأسباب أخرى (من الصعب القيام بالتخصيص؟) ، ولكن على الأقل لا يتطلب أي مساعدة من wasm.
  • استخدام الترامبولين (مع كومة wasm) من شأنه أن يمنع الاستخدامات التي يجب أن يبقى فيها إطار المكدس ، مثل الخيوط الخضراء؟

جانبا .. "Cheney on the MTA" هو حقا أنيق .. يكاد يكون مثل جامع النسخ ، ولكن على عكس GC الكاملة ، فإن قائمة الإطارات المكدسة تافهة للنسخ. أحب أيضًا أن بيكر كان يقدم تلك الورقة بنفس الشكل من نفس عنوان url لمدة> 20 عامًا :)

aardappel بالتأكيد ، دعني أوضح :)

يعني استخدام longjmp أنك تستخدم مكدس wasm الفعلي (الذي ليس تحت سيطرتك) ، مما يعني أنه ليس لديك طريقة لتحديد مقدار ما تستخدمه ومتى توشك على نفاد مساحة المكدس ، حاليا؟

هذا صحيح على أنظمة أساسية أكثر من WebAssembly فقط ، ولكن الحيلة هي أنك تحدد أولاً حجمًا تعسفيًا أقصى للمكدس (على سبيل المثال ، أصغر حجم لجميع الأنظمة الأساسية التي تدعمها إذا كنت لا ترغب في الترجمة المشروط باستخدام ثوابت مختلفة) ، و ثم أول شيء يتم القيام به عند الإدخال هو أخذ عنوان شيء ما على المكدس (لذلك ليس من الناحية الفنية مؤشر المكدس ، ولكن في الأساس يمكن استخدامه كمؤشر واحد) ، أو الحصول على مؤشر المكدس نفسه. نظرًا لحجمك الأقصى ، ومؤشر المكدس (تقريبي أو لا) ، ومعرفة ما إذا كان المكدس ينمو لأعلى أو لأسفل على هدف معين ، يمكنك التحقق من مقدار المخزن المؤقت لديك بين الحد الأقصى الذي حددته وعنوان المكدس الذي تملكه .

إذا استخدمت بدلاً من ذلك "حزمة الظل" في الذاكرة الخطية لتخزين إطارات المكدس ، فيمكنك إعادة تعيينها دون استخدام longjmp ، بافتراض أنك لا تستخدم وظائف wasm لتنفيذ الوظائف في لغتك ، ولكن بدلاً من ذلك كل الجثث تعيش داخل مبنى ضخم من أجل (؛ ؛) تبديل (..). قد يكون هذا أبطأ لأسباب أخرى (من الصعب القيام بالتخصيص؟) ، ولكن على الأقل لا يتطلب أي مساعدة من wasm.

لقد حددت إلى حد كبير مشكلة رئيسية واحدة هنا - إنها تدمر القدرة على تحسين تخصيص التسجيل ، والتي قد لا تكون مشكلة مع WebAssembly (؟) ، نظرًا لدلالات آلة المكدس ، ولكنه بالتأكيد شيء سأتجنبه ما لم يكن لدي خيار آخر . المشكلة الأكبر هي أنها تمنع مجموعة كاملة من التحسينات في الواجهة الخلفية للمجمع (أنا أستخدم LLVM ، لكنني سمعت أن المشكلة هي نفسها مع تطبيقات الترجمة المختلفة للغة C).

استخدام الترامبولين (مع كومة wasm) من شأنه أن يمنع الاستخدامات التي يجب أن يبقى فيها إطار المكدس ، مثل الخيوط الخضراء؟

قد يساعد في فهم كيفية سير التنفيذ عند الجدولة. لذلك افترض أن لدينا بعض العمليات (اقرأ: مؤشر ترابط Erlang green) قيد التنفيذ ، وعند الدخول إلى الوظيفة الحالية ، وبعد التحقق مما إذا كان المكدس بحاجة إلى إعادة تعيين ، وما إذا كان مطلوب GC الرئيسي ، يتحقق من عدد التخفيضات (بشكل أساسي تقدير تقريبي لمقدار العمل الذي أنجزته منذ آخر عائد) ويرى أنه يحتاج إلى التنازل عن المجدول لأنه سيتجاوز حصته:

  1. فروع التحكم إلى ما أسميه "نقطة العائد" ، حيث يتم إنشاء استمرار يشير إلى الوظيفة الحالية ، ويشير إلى العودة الحالية واستمرارية الهروب ، بالإضافة إلى أي حجج أخرى.

    • تمثل جميع هذه الحجج قيمًا حية في المكدس "الحقيقي" - في نموذج CPS ، أي شيء ليس وسيطة للدالة الحالية ميت أو في الكومة.

  2. يتم نقل أي من القيم الحية الموجودة في المكدس إلى الكومة (في حالتنا ، كل عملية لها كومة خاصة بها ، لذلك يتم نقل القيم هناك).
  3. يتم تخزين الاستمرارية المُنشأة في بنية العملية (كل عملية / خيط أخضر له هيكل يحتوي على جميع بيانات التعريف الرئيسية الخاصة به ، مثل المؤشر إلى كومة الكومة ، وعدد التخفيضات ، وما إلى ذلك.
  4. يتم تنفيذ قفزة ، والتي تعيد التحكم إلى المجدول.
  5. يسحب المجدول العملية التالية ليتم جدولتها من قائمة انتظار التشغيل ، ويحصل على استمرار هذه العملية ، ويستدعيها بالوسيطات المخزنة في تلك المتابعة.

لذلك مع أخذ ذلك في الاعتبار ، فإن استخدام الترامبولين لا يمنع هذا التدفق ، بل يفرض فقط تكلفة باهظة - بدلاً من القدرة على استدعاء استمرار (في الحقيقة مجرد مؤشر وظيفي في هذه المرحلة) ، باستخدام الحجج الموجودة بالفعل على المكدس ؛ يجب إنشاء استمرار ، ونقل القيم الحية إلى الكومة ، قبل العودة إلى الترامبولين. يكون القيام بذلك لكل مكالمة أبطأ بكثير من إنشاء استمرار فقط عند حدوث الجدولة أو GC أو إعادة تعيين المكدس.

جانبا .. "Cheney on the MTA" هو حقا أنيق .. يكاد يكون مثل جامع النسخ ، ولكن على عكس GC الكاملة ، فإن قائمة الإطارات المكدسة تافهة للنسخ. أحب أيضًا أن بيكر كان يقدم تلك الورقة بنفس الشكل من نفس عنوان url لمدة> 20 عامًا :)

أعتقد أن استخدام المكدس كجيل شاب هو ضربة رائعة. ويتحسن! نظرًا لأننا في نموذج CPS ، فأنت لست بحاجة إلى نسخ إطارات المكدس ، فالقيم الحية الوحيدة التي يجب نسخها _يجب_ أن تكون في أو يشار إليها بواسطة الحجج للوظيفة الحالية ، وأي شيء لا يمكن الوصول إليه من هذه الوسائط ميت ، وجمعها بشكل فعال عن طريق القفزة :)

قبل أن ألتقي بالورقة ، يحزنني أن أقول إنني لم أكن على دراية بعمله ، لكن بيكر رائع ، وأنا معجب كبير ، خاصة أنه كما تقول ، يستمر في استضافة جميع أوراقه بعد كل هذه السنوات ، لم يتغير في الأساس!

أريد أن أشير أيضًا إلى أنه على الرغم من وجود بعض التقاطع هنا مع اقتراح استدعاء الذيل ، أشعر أن وجهة نظري تتعلق أكثر بالدفاع عن دعم الاستمرارية كاستراتيجية تنفيذ لغة ، بطريقة أو بأخرى. تعد مكالمات الذيل المناسبة في الأساس أمرًا مهمًا بالطبع ، ولكن الدرس الرئيسي وراء _Cheney على MTA_ هو أن نقص الدعم المحلي للمكالمات الخلفية يمكن حله والبقاء فعالًا نسبيًا ، مع الأخذ في الاعتبار الأدوات المناسبة.

والأهم من ذلك ، أن اقتراح استدعاء الذيل الحالي معيب في رأيي ، لأنه يصف بشكل أساسي الترامبولين (يجب على المرء أن يتحمل تكلفة عودة + مكالمة). تتمثل إحدى الفوائد الرئيسية للمكالمات الخلفية في أنها فعالة ، وتعادل بشكل أساسي نظام الانتقال المحلي. بدون ذلك ، لست متأكدًا من الفائدة التي توفرها تعليمات استدعاء الذيل في المواصفات ، بخلاف المترجم الذي لا يحتاج إلى إنشاء الترامبولين الخاص به. ربما سيكون من الممكن لآلات WebAssembly تحسين هذه التعليمات إلى مكالمات ذيل "حقيقية" ، لكنني لم أر أي مناقشة حتى هذه النقطة ، وهي مناقشة مهمة.

لست متأكدًا من الحل الصحيح ، لكنني أعتقد أن أحد المؤشرات الرئيسية حول ما إذا كان WebAssembly يحتوي على العناصر الأولية الصحيحة هو ما إذا كان يمكن تجميع البرامج الوظيفية إلى كود أم لا ، وهو في الأساس أداء مثل نظرائه الإلزامي (باستثناء المشكلات الأخرى ، مثل كبيانات غير قابلة للتغيير) ، والتي تتلخص في دعم مكالمات الذيل بكفاءة ، بطريقة أو بأخرى.

اقتراح استدعاء الذيل الحالي معيب في رأيي ، لأنه يصف بشكل أساسي الترامبولين (يجب على المرء أن يتحمل تكلفة عودة + مكالمة).

bitwalker ، أخشى أنني لا أتابع. لماذا تعتقد أنه يجب أن يكون هناك ترامبولين؟ هذا بالتأكيد من المفترض أن يكون مكالمة ذيل عادية.

إعادة قابلة للاستئناف معالجات الاستثناءات / الأثر: هناك بعض الخروج من تاريخ المثال الرسومات هنا . بخلاف ذلك ، لدينا حاليًا فقط صياغة لدلالات رسمية ، دون أي تفسير نصي قابل للاستخدام في الكتابة. ربما يجب أن نكتب شيئًا ما في النهاية ، لكن لم يكن هناك الكثير من النشاط.

أخشى أنني لا أتبع. لماذا تعتقد أنه يجب أن يكون هناك ترامبولين؟ هذا بالتأكيد من المفترض أن يكون مكالمة ذيل عادية.

أعتذر إذا أساءت التفسير! كنت أشير إلى هذا القسم ، حيث يقال إن دلالات التنفيذ تتصرف مثل return متبوعًا بـ call . يبدو أنها طريقة محيرة لشرحها ، خاصة بسبب اتصال الترامبولين. لقد رأيت دائمًا مكالمات الذيل كشيء أقرب إلى القفز وكان هذا انطباعي عن كيفية نظر الآخرين إليها أيضًا. في حين أن النقطة الرئيسية لاستدعاءات الذيل هي تجنب تجاوز المكدس عن طريق إعادة استخدام إطارات المكدس ، إلا أنني أفهم أن الخاصية الرئيسية الأخرى للمكالمات الخلفية هي أنها تتجنب الكثير من خلط المكدس الذي يحدث مع عودة + استدعاء أو حتى مجرد مكالمة؛ أكثر في حالة الاستدعاءات العودية الذاتية ، ولكن بشكل أكثر عمومية في حالة استدعاءات الدوال ذات الوسيطات في نفس الموضع ، حيث يمكن للمترجم تجنب تحريك الأشياء. أعتقد أنني كنت أتوقع فقط أن أرى ذلك منقوصًا في الاقتراح. أنا لا أخبرك بأي شيء لا تعرفه بالفعل عن مكالمات الذيل ، أنا فقط أحاول أن أشرح لماذا فسرت الاقتراح بالطريقة التي فعلت بها :)

بخلاف ذلك ، لدينا حاليًا فقط صياغة لدلالات رسمية ، دون أي تفسير نصي قابل للاستخدام في الكتابة. ربما يجب أن نكتب شيئًا ما في النهاية ، لكن لم يكن هناك الكثير من النشاط.

شكرا على الرابط! يبدو لي أنه يمكن استخدام هذا على الأرجح للتعبير عن نوع تدفق التحكم الذي أستخدمه setjmp / longjmp لـ (كما هو موضح أعلاه ، على سبيل المثال _Cheney على MTA_) ، بافتراض أن " يؤدي استئناف "التحكم في مكالمة خارجية إلى إرجاع مكدس الاستدعاءات إلى تلك النقطة. هل هذا هو الحال؟

في كلتا الحالتين ، هل هناك أي شيء يمكنني القيام به للمساعدة؟ هل المشكلة تتعلق بتنفيذ مرجعي ، هل لا تزال هناك أسئلة مفتوحة تحتاج إلى بحث / مناقشة ، أم أنها تحتاج فقط إلى شخص ما لإنجازها خلال العملية؟

حسنًا ، نظرًا لأن المتصل والمستدعي يمكن أن يكون لهما قوائم معلمات مختلفة تمامًا ، لا يمكن للمكالمات الخلفية تجنب خلط الوسيطة بشكل عام ، حتى لو حدث ذلك في السجلات. بالطبع ، من المتوقع أن تقلل المحركات من ذلك في الحالات التي تتطابق فيها ، لكن هذا لا يمكن ملاحظته من الناحية الدلالية. لا يوجد شيء غير عادي هنا ، هذه هي الطريقة التي تعمل بها عادة.

بدأت Danielhillerstrom في اختراق تصميم معالج التأثير التجريبي في المترجم المرجعي كخطوة أولى ، لكنني أشك في إمكانية موازاة ذلك كثيرًا. ستكون الخطوة التالية هي التجارب الأولية لاستهدافها ، وهنا يمكن استخدام كل المساعدة التي يمكننا الحصول عليها ، إذا كان الناس يحاولون التلاعب بها ، والمساعدة في تكرار التصميم ، ربما عن طريق كتابة الواجهة الخلفية لمجمع تجريبي تستهدفه. لكن الجزء الأصعب حتى الآن ، إذا وصلنا إلى هناك ، سيكون التنفيذ الفعال للمكدسات / الاستمرارات المتعددة (بغض النظر عن تفاصيل التصميم الملموسة) في محرك الإنتاج ، والذي سيكون صعبًا للغاية ، نظرًا للتعقيد التام لـ JS / Wasm الحالي أجهزة افتراضية.

حسنًا ، نظرًا لأن المتصل والمستدعي يمكن أن يكون لهما قوائم معلمات مختلفة تمامًا ، لا يمكن للمكالمات الخلفية تجنب خلط الوسيطة بشكل عام ، حتى لو حدث ذلك في السجلات

مشكلتي الرئيسية مع هذا الخط:

ومن ثم يقومون بفك مكدس المعامل مثل return يفعل

يبدو هذا كثيرًا وكأنه يتطلب أداء نفس العمل الذي تؤديه عودة + مكالمة ، حتى لو لم يكن التنفيذ عبارة عن ترامبولين بشكل صارم. السبب في اعتقادي أن التمييز مهم هو أن الميزة الرئيسية للمكالمات الخلفية هي أنها لا تتحمل نفقات أكثر من المكالمة العادية ، في الواقع أقل ، نظرًا لعدم تخصيص إطار مكدس. ولكن إذا كانت مكالمات الذيل تقوم فعليًا بضعف العمل الذي تقوم به المكالمة العادية ، فهذا ثمن باهظ يجب دفعه مقابل اللغات التي لا تكون فيها مكالمات الذيل مجرد تحسين.

لا أقول بالضرورة أن الاقتراح يتطلب تطبيقات للقيام بذلك بهذه الطريقة ، لكن الطريقة التي صيغ بها ليست مثالية. لا تؤدي مكالمات الذيل إلى "فك" المكدس حقًا ، بل تقوم بالكتابة فوق إطار المكدس الخاص بهم ، والذي أعتقد أنه يشبه فك المكدس ، ولكنه ليس نفس الشيء. لم أكن أقصد إخراج المحادثة عن مسارها هنا ، لكنني أعتقد أن المواصفات يجب أن تكون صريحة بشأن هذه الاختلافات ، ما لم تكن النية هي تجنب طلب إجراء مكالمات خلفية كمكالمات ذيل مناسبة.

بدأت Danielhillerstrom في اختراق تصميم معالج التأثير التجريبي في المترجم المرجعي كخطوة أولى

رائع ، هل هذا العمل متاح للجميع حاليًا أم لا يزال يتم اختراقه معًا؟

ستكون الخطوة التالية هي التجارب الأولية لاستهدافها ، وهنا يمكن استخدام كل المساعدة التي يمكننا الحصول عليها ، إذا كان الناس يحاولون التلاعب بها ، والمساعدة في تكرار التصميم ، ربما عن طريق كتابة الواجهة الخلفية لمجمع تجريبي تستهدفه.

بمجرد أن يصبح متاحًا للعب به ، حتى إذا تطلب الأمر بعض العمل لإعداده من طرفي ، فسأكون منفتحًا على كتابة خلفية WebAssembly المنفصلة للمترجم الخاص بي ، بدلاً من استخدام LLVM ، أو ربما حتى عن طريق تخصيص LLVM ببعض جديدة الجوهر + التخفيض المرتبط. يعد WebAssembly هدفًا مهمًا بالنسبة لي ، لذا كل ما يمكنني فعله للمساعدة.

لكن الجزء الأصعب حتى الآن ، إذا وصلنا إلى هناك ، سيكون التنفيذ الفعال للمكدسات / الاستمرارات المتعددة (بغض النظر عن تفاصيل التصميم الملموسة) في محرك الإنتاج ، والذي سيكون صعبًا للغاية ، نظرًا للتعقيد التام لـ JS / Wasm الحالي أجهزة افتراضية.

نعم ، أستطيع أن أتخيل. ومع ذلك ، أعتقد أن جميع المحركات الرئيسية لديها دوافع قوية لجعلها تعمل ، إذا كان WebAssembly هو الأساس الذي يعد به. هل علق المهندسون على تلك المحركات على هذا حتى الآن؟ هل هو نوع الشيء الذي يمكن تنفيذه وهو مجرد مسألة وقت ، أم أنه غير متوافق بشكل أساسي مع كيفية عمل هذه المحركات اليوم؟ لدي منظور ضئيل حول كيفية تنفيذ هذه المحركات حاليًا ، ولكن وجود فكرة عن القيود التي تعمل في ظلها سيكون سياق مفيدًا يجب التأكد منه.

مشكلتي الرئيسية مع هذا الخط:

ومن ثم يقومون بفك مكدس المعامل مثل return يفعل

آه ، لا تخلط بين لغة الآلة المجردة والتنفيذ. يشير هذا إلى مكدس المعامل داخل الوظيفة الحالية ، والذي هو مجرد فكرة عن الآلة المجردة للمواصفات ولا يتم تجسيدها فعليًا في المحركات الحقيقية. يشير هذا بشكل أساسي إلى أنه يتم إسقاط المعاملات غير المستخدمة عند استدعاء الذيل. يتم التعامل مع هذا كله في وقت الترجمة.

ومع ذلك ، لا يوجد سبب للاعتقاد بأن مكالمات الذيل أسرع من المكالمات العادية بشكل عام . هذا سوء فهم. الغرض منها هو تقليص المساحة وليس الوقت! يمكن أن تكون أكثر تكلفة إلى حد ما في بعض الحالات.

(تعليمات استدعاء الذيل في بعض المحركات التجارية التي تظل بدون اسم مشهورة بكونها أبطأ بما يصل إلى 100 مرة - أنا واثق من أننا سنعمل بشكل أفضل. :))

هل علق المهندسون على تلك المحركات على هذا حتى الآن؟

بالطبع. يرى الجميع الحاجة إلى شكل من أشكال تبديل المكدس. هذا لا يعني أن الجميع ليسوا خائفين ...

آه ، لا تخلط بين لغة الآلة المجردة والتنفيذ. يشير هذا إلى مكدس المعامل داخل الوظيفة الحالية ، والذي هو مجرد فكرة عن الآلة المجردة للمواصفات ولا يتم تجسيدها فعليًا في المحركات الحقيقية.

نعتذر عن ضياع ذلك! وهذا يوضح بالفعل سبب صياغتها بهذه الطريقة. شكرا لصبرك :)

تضمين التغريدة

لكن الحيلة هي أن تحدد أولاً حجمًا تعسفيًا للمكدس الأقصى (على سبيل المثال ، أصغر حجم لجميع الأنظمة الأساسية التي تدعمها إذا كنت لا تريد التجميع المشروط باستخدام ثوابت مختلفة) ، ثم أول شيء يتم القيام به عند الإدخال هو خذ عنوان شيء ما على المكدس

إلا أنه لا يمكنك أخذ عنوان أي شيء على wasm stack ، حسب التصميم. في اللحظة التي تأخذ فيها عنوان متغير محلي (في LLVM أو على سبيل المثال C ++) ، يغير كود wasm المنبعث من المتغير المحلي من wasm المحلي إلى شيء ما في مكدس الظل. لذلك لا يمكنك قياس كومة الوسم بهذه الطريقة. وقد قلت بالفعل أنك لن تكون سعيدًا بوجود كل شيء في مكدس الظل.

لا يزال بإمكانك محاكاة هذا .. يمكنك لكل دالة wasm حساب الحجم الإجمالي لجميع السكان المحليين + args + max temps بشكل ثابت ، واستخدام ذلك كتقريب متحفظ لحجم المكدس المستخدم ، ثم تنفيذ تنظيف المكدس (باستخدام longjmp أو الاستثناءات) بمجرد تجاوزها لبعض الحدود المتحفظة ، فإنك تقدر كمية جيدة من مكدس wasm لاستخدامه في أي محرك. لكن wasm لا يحدد مكدس min / max الذي يجب أن يوفره التطبيق ، لذلك هذا مشكوك فيه للغاية. يمكنك حتى محاولة اكتشاف ما يوفره التطبيق من خلال نفاد مساحة المكدس عن قصد لمجموعة متنوعة من الوظائف العودية ، وحساب عدد المكالمات ، والتقاط الفخ ، وتقدير مساحة مكدس معتدلة مرتبطة بذلك ؛)

مرة أخرى ، أعتقد أنك أفضل حالًا مع مكدس الظل ، بشكل عام :)

بصراحة ، يجب السماح لوحدة wasm بالتلميح على الأقل إلى مقدار مساحة المكدس التي تريد أن يوفرها المحرك ، لأنه بدون مثل هذا الشيء ، لن تتمكن أبدًا من استخدام خوارزميات متكررة (التي تعالج بيانات المستخدم ، على سبيل المثال محلل ) في wasm ، _إذا كان من الممكن أن يكون المكدس صغيرًا بشكل تعسفي_. أو قد تحتاج الخلفيات دائمًا إلى إجبار الخوارزميات العودية على استخدام مكدس الظل. من شأنه أن يجعل أي معنىrossbergtitzerbinji؟

لذلك مع أخذ ذلك في الاعتبار ، فإن استخدام الترامبولين لا يمنع هذا التدفق ، بل يفرض فقط تكلفة باهظة - بدلاً من القدرة على استدعاء استمرار (في الحقيقة مجرد مؤشر وظيفي في هذه المرحلة) ، باستخدام الحجج الموجودة بالفعل على المكدس ؛ يجب إنشاء استمرار ، ونقل القيم الحية إلى الكومة ، قبل العودة إلى الترامبولين. يكون القيام بذلك لكل مكالمة أبطأ بكثير من إنشاء استمرار فقط عند حدوث الجدولة أو GC أو إعادة تعيين المكدس.

آه حسنًا ، كنت أتخيل أنك تقصد الترامبولين لكل مكالمة / مكالمة ، لكنك تقصد أنها تستخدم بشكل مثالي فقط لتحقيق العائد وعندما تنفد مساحة المكدس؟

قبل أن ألتقي بالورقة ، يحزنني أن أقول إنني لم أكن على دراية بعمله ، لكن بيكر رائع ، وأنا معجب كبير ، خاصة أنه كما تقول ، يستمر في استضافة جميع أوراقه بعد كل هذه السنوات ، لم يتغير في الأساس!

نعم ، هناك الكثير من الأفكار "الإبداعية" التي لا تزال ذات صلة!

aardappel :

يجب السماح لوحدة wasm بالتلميح على الأقل إلى مقدار مساحة المكدس التي تريد أن يوفرها المحرك

سيكون من الجيد تقديم طريقة ما لتكوين حجم المكدس ، لكنني أرى مشكلتين في الاقتراحات الملموسة:

  1. المكدس عبارة عن وحدة متقاطعة ، لذا فإن التلميح لكل وحدة ليس له معنى حقًا.
  2. لا يوجد مقياس واضح يمكن من خلاله تحديد مساحة المكدس ، لأن استخدام المكدس هو نتاج مجموعة كاملة من المتغيرات.

لست متأكدا من كيفية معالجة هذا. سيكون من الأجمل إذا كان VM قادرًا فقط على تنمية المكدس. ثم يتم تقييد مساحة المكدس فقط بمساحة الكومة.

تضمين التغريدة
1) نقطة جيدة ، هذه مشكلة. لا يزال من المفيد أن تكون قادرًا على تحديده لغالبية الحالات ، حيث تحدد الوحدة "الثقيلة" (التي تعتمد على العودية) التي تم تشغيلها كوحدة أول / وحدة رئيسية مثل هذا الحد ، وأي وحدات مساعدة / فرعية لا ر لديها أي متطلبات خاصة. أو إذا كان تغيير حجم المكدس أمرًا سهلاً ، فقد يكون الحد الأقصى لجميع الوحدات المعنية .. على الرغم من أنني أعتقد أنه سيكون هناك محركات لا يمكن تغيير حجمها إذا كانت تستخدم مكدس العملية مباشرةً في المضيف ، لذا فهي كلها موضع نقاش.

2) نعم ، يعتمد الأمر بشكل كبير على التنفيذ ، ولكن هذا هو الحال بالفعل إذا كتبت برنامجًا أصليًا. إذا كنت أعلم أن Linux سيعطيني 8 ميجابايت ، فأنا أراقب وظيفتي العودية لتقدير مدى العمق الذي يمكنني الوصول إليه وما إذا كان ذلك معقولاً بالنسبة لبيانات الحالة الأسوأ التي أعتقد أنني سأعالجها .. قبل أن أقرر تحويلها إلى خوارزمية متكررة أم لا. هذا بالفعل علم غير دقيق للغاية. لا أفهم لماذا سيكون هذا مختلفًا كثيرًا عن wasm. ستمنحني القدرة على قول "أتوقع أن يكون هناك ما يصل إلى 1 ميجابايت من المكدس" ضمانات أفضل بكثير من الاضطرار إلى كتابة الكود الخاص بي على افتراض أن بعض المحركات ستقصرني على 16 كيلوبايت من المكدس (وبالتالي يتعين علي إزالة أي تكرار من الكود الخاص بي). نفس الشيء بالنسبة لحالة استخدام

إلا أنه لا يمكنك أخذ عنوان أي شيء على wasm stack ، حسب التصميم. في اللحظة التي تأخذ فيها عنوان متغير محلي (في LLVM أو على سبيل المثال C ++) ، يغير كود wasm المنبعث من المتغير المحلي من wasm المحلي إلى شيء ما في مكدس الظل. لذلك لا يمكنك قياس كومة الوسم بهذه الطريقة. وقد قلت بالفعل أنك لن تكون سعيدًا بوجود كل شيء في مكدس الظل.

حسنًا ، ربما هناك حاجة إلى مثال لتوضيح ما أعنيه. ما يلي هو تطبيق C تافه يستخدم العودية لزيادة عداد حتى حد تعسفي. يستخدم الترامبولين ، ولكن فقط عندما تنفجر المكدس ، ويحدد وقت العودة إلى الترامبولين عن طريق التحقق من مقدار مساحة المكدس التي يعتقد أنها بقيت:

#include <emscripten.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>

#define STACK_BUFFER 16384

// Checks whether the stack is overflowing
static bool stack_check(void);

// The address of the top of the stack when we first saw it
// This approximates a pointer to the bottom of the stack, but
// may not necessarily _be_ the exact bottom. This is set by
// the entry point of the application
static void *stack_initial = NULL;
// Pointer to the end of the stack
static uintptr_t stack_max = (uintptr_t)NULL;
// The current stack pointer
static uintptr_t stack_ptr_val = (uintptr_t)NULL;
// The amount of stack remaining
static ptrdiff_t stack_left = 0;

// Maximum stack size of 248k
// This limit is arbitrary, but is what works for me under Node.js when compiled with emscripten
static size_t stack_limit = 1024 * 248 * 1;

static bool stack_check(void) {
  // Get the address of the top of the stack
  stack_ptr_val = (uintptr_t)__builtin_frame_address(0); // could also use alloca(0)

  // The check fails if we have no stack remaining
  // Subtraction is used because the stack grows downwards
  return (stack_ptr_val - stack_max - STACK_BUFFER) <= 0;
}

#define MAX_DEPTH 50000

static int depth;
static int trampoline;

int a(int val);
int b(int val);

int a(int val) {
    // Perform stack check and only recurse if we have stack
    if (stack_check()) {
        trampoline = 1;
        return val;
    } else {
        depth += 1;
        return b(val); 
    }
}

int b(int val) {
    int val2;
    if (depth < MAX_DEPTH) {
        // Keeping recursing, but again only if we have stack
        val2 = val + 1;
        if (stack_check()) {
            trampoline = 1;
            return val2;
        }
        return a(val2);
    } else {
        return val;
    }
}

int main() {
    stack_initial = __builtin_frame_address(0); // could also use alloca(0)
    stack_max = (uintptr_t)stack_initial - stack_limit;

    double ts1, ts2 = 0;
    ts1 = emscripten_get_now();

    depth = 0;
    trampoline = 0;

    int val = 0;

    while (true) {
        val = a(val);
        // This flag helps us distinguish between a return to reset the stack vs
        // a return because we're done. Not how you'd probably do this generally,
        // but this is just to demonstrate the basic mechanism
        if (trampoline == 1) {
            trampoline = 0;
            continue;
        }
        break;
    }
    ts2 = emscripten_get_now();

    printf("executed in %fms\n", ts2-ts1);

    return 0;
}

لترى بنفسك ، قم بتشغيل emcc -s WASM=1 demo.c -o demo.js وتشغيل مع node demo.js . يبدو أن تثبيت العقدة المحلية الخاص بي يحتوي على حجم مكدس أقصى يبلغ 984 كيلو بايت ، ولكن كما ترون ، كان علي تعيين الحد الأقصى لحجم المكدس في العرض التوضيحي الخاص بي إلى 248 كيلو بايت ، حيث سيؤدي أي حجم أعلى إلى تجاوز سعة مكدس ، وللأسف لا يظهر لتكون وسيلة للوصول إلى الحد الدقيق للمكدس ، يجب على المرء أن يخمن أو يضبط ثابتًا.

من فضلك اغفر الشفرة الفظيعة ، لكنني رسمتها على عجل. يجب أن تكون الفكرة الأساسية واضحة وآمل - إذا اختار المرء أن يرتد مرة أخرى إلى الترامبولين فقط عندما ينفد المكدس ، فهذا _ ممكن في WebAssembly اليوم ، وإن كان مع بعض القيود. حتى الآن في التنميط المتنوع لسيناريوهات مماثلة ، هو في الأساس رابط بين النهج أعلاه والترامبولين العادي فقط ، لكنني أظن أن السيناريوهات الأكثر واقعية ستظهر أنه كلما قل عدد مرات العودة إلى الترامبولين ، كان ذلك أفضل. مع وجود مثل هذا المكدس الصغير للعمل معه ، فإن الفائدة صغيرة جدًا لسوء الحظ - أتوقع أن أعمل مع كومة لا تقل عن 2 ميجابايت ، إن لم يكن أكثر ، 248 كيلو أمر سخيف. بالنسبة إلى setjmp / longjmp ، فإنه لا يقترب بسبب كيفية تنفيذ ذلك اليوم.

كما قال rossberg ، لا أعتقد أن حجم المكدس لكل وحدة منطقي ، يجب أن يكون قابلاً للتكوين عالميًا ، وهذا هو الحال اليوم بشكل أساسي باستثناء أنك تقوم بتكوين حجم المكدس العام للمحرك نفسه. بقدر ما أشعر بالقلق ، قد يعني هذا أيضًا أنه غير قابل للتكوين على الإطلاق ، وهذا جيد - الحجم الفعلي ليس هو المشكلة الأساسية ، على الرغم من أن الوضع الحالي ليس مثاليًا. إن السماح للمكدس بالنمو بشكل تعسفي من خلال النمو في الكومة يبدو كخيار قابل للتطبيق أيضًا ، ولكنه ربما ليس مثاليًا لأنه ليس حقًا ما يتوقعه أي شخص. أفضل أن أرى حجم مكدس أكثر تسامحًا (كما قلت أعلاه ، على الأقل 2 ميجابايت).

من منظور المواصفات ، لا أعتقد أنه يمكن للمرء _طلب_ حجم مكدس معين ، لكني أعتقد أنه يمكن إضافة أو توضيح بعض الأشياء:

  • توصية بخصوص الحد الأدنى لحجم المكدس. من المحتمل أن تحتاج بعض الأنظمة الأساسية شديدة التقييد إلى خفض حجمها ، ولكن إذا كانت هناك توصية بشيء مثل 2 ميغا بايت ، فيمكن أن تستفيد تلك الأنظمة الأساسية التي ليس لديها قيود من مساحة تكديس أكبر للعمل بها ، ولكن المواصفات ليست _ تعيّن_ a الحد الأدنى
  • الأهم من ذلك هو طريقة للحصول على حد المكدس الحالي كما ينطبق على رمز WebAssembly الذي يتم تنفيذه (على سبيل المثال ، ستكون قيمة getrlimit(RLIMIT_STACK, ..) حدًا مفيدًا للترميز البرمجي إلى WebAssembly). يوفر هذا تطبيقات اللغة مع الوسائل للتعامل مع مجموعات مختلفة الحجم دون الحاجة إلى إضافة مجموعة من الثوابت الشرطية لكل محرك ، أو ما هو أسوأ من ذلك ، ثابت واحد منخفض للغاية لأدنى قاسم مشترك.

بالنسبة لمشروعي الخاص ، سأقوم بمزيد من التنميط ، ولكن بناءً على ما أراه ، سأستخدم على الأرجح ترامبولين بسيطًا عند استهداف WebAssembly ، حتى setjmp / longjmp أو يصبح شيء مثل الاستثناءات القابلة للاستئناف قابلة للتطبيق ؛ مكالمات الذيل تحل حالة الاستخدام الخاصة بي ؛ أو تصبح أحجام المكدس في المحركات الرئيسية كبيرة بدرجة كافية بحيث يمكن استخدام تشيني على MTA. الأدوات الموجودة تحت تصرفي ليست كافية لجعلها تعمل بشكل جيد اليوم.

يجب أن أوضح أيضًا ، لقد جمعت المثال أعلاه بـ emcc ، ولكن تم تكوينه لاستخدام تثبيت LLVM الخاص بي (المثال المستخدم في هذا العرض التوضيحي هو LLVM master ، لذلك 9 ، وتم إنشاؤه خلال الأيام القليلة الماضية - لا توجد تغييرات من جهتي) ، لذلك يتم تجميعها باستخدام LLVM backend ، _not_ asm.js - فقط في حالة توقع حدوث فرق.

تضمين التغريدة
هل أنت متأكد من أن الكود أعلاه يفعل ما تعتقد أنه يفعله؟ سيعيد Afaik ، __builtin_frame_addressalloca ) عناوين على مكدس الظل ، بينما يحدث التكرار الخاص بك على مكدس wasm ، لذلك يجب أن تكون هذه قيم غير مرتبطة. نظرًا لأنك لا تخزن أي شيء فعليًا على حزمة الظل في هذا الكود ، فقد لا يتزايد حتى ، لذلك قد يعود __builtin_frame_address .. نفس القيمة في كل مرة؟

aardappel لقد printf . قمت أيضًا بإجراء التجربة مع تمكين التحقق من المكدس وبدونه. بدون ذلك ، لا تصل الشفرة إلى ما يقرب من 50 كيلو بايت (قيمة MAX_DEPTH) ، وتجهض ، وهو أمر متوقع بالطبع. مع تمكينه ، يصل البرنامج إلى 50 كيلو بينما يضرب فقط الترامبولين ~ 6 مرات ، ويكمل بنجاح. إذا قمت بتغيير الحد الأقصى لمساحة المكدس إلى كمية أكبر من 248 كيلو ، لنفترض 256 كيلو ، فإن المكدس يفيض ، مما يشير إلى أن الكود يعود إلى الترامبولين بشكل صحيح عندما نصل إلى حد المكدس المحدد. القيمة الناتجة عن __builtin_frame_address (والتي تم تخفيضها إلى @llvm.frameaddress مضمنة) تصبح أصغر بالمبلغ الصحيح في كل مرة يتم فيها إجراء فحص مكدس (بناءً على تقدير تقريبي من النظر إلى التخصيصات في LLVM IR) ، لذلك يبدو أنه ينتج القيمة التي كنت أتوقعها.

لقد جربت تنفيذًا باستخدام getrlimit(2) ، لكن القيمة التي تم إرجاعها من خلال ذلك مفصولة بوضوح عن المكدس (مكدس الظل الذي ذكرته) ، وقد يشير إلى المكدس الحقيقي - لست متأكدًا ، لكنه ليس كذلك 'ر مفيد لفحص المكدس. لذلك هناك بعض الأدوات التي لا يمكن استخدامها.

bitwalker أعتقد أن هذا قد يكون بسبب قيامك -O3 . يؤدي ذلك إلى تحسين الحلقة وجميع استدعاءات الوظائف تمامًا. إذا أضفت مكالمة وهمية ، فإنها تحول الأمر برمته إلى حلقة. https://webassembly.studio/؟f=0aj0cn61ob8

binji نعم ، أقوم

النقطة في المثال ليست ما إذا كان المترجم يمكنه تحسين هذه الحالة الواحدة إلى شكل غير متكرر ، ولكن هذا في الأساس _يمكن_ التحقق من مساحة المكدس المتاحة والعمل عليها لتنفيذ _Cheney على MTA_.

bitwalker ، كما قال aardappel ، القيمة التي تنتجها __builtin_frame_address هي لمكدس الظل. حتى إذا تغيرت القيمة ، فهذا لا يعني شيئًا عن الغرفة المتبقية في مكدس مكالمات النظام الفعلي ، وهو ما يهمك. لا توجد طريقة لقياس أو ملاحظة ذلك من داخل واسم.

تستغل التعليمات البرمجية الخاصة بك السلوك غير المحدد في C. يحدث للعمل على الأجهزة الشائعة ، ولكن ليس على Wasm.

تستغل التعليمات البرمجية الخاصة بك السلوك غير المحدد في C. يحدث للعمل على الأجهزة الشائعة ، ولكن ليس على Wasm.

فقط للتوضيح ، أقوم بتشغيل هذا الرمز في محرك WebAssembly ، على وجه التحديد الإصدار 8 ، وليس التحويل إلى x86_64.

أعلم أنني أنظر إلى مكدس الظل في المثال ، ولكن هذا لأنني أفترض أن التخصيصات التي أجريها على المكدس (في رمز WebAssembly) يتم تخصيصها في مكدس الظل ، بما في ذلك إطارات المكدس للوظائف التي يتم استدعاؤها في هذا الرمز . بعبارة أخرى ، مكدس النظام ليس شيئًا أحتاج حتى أن أكون على دراية به عند كتابة WebAssembly ؛ مكدس الظل هو المكدس "الحقيقي" في هذا السياق.

إذا لم يكن الأمر كذلك ، إذن نعم ، فأنت محق في أن المثال يعمل عن طريق الصدفة السعيدة - ولكن يبدو أن هذا يعني أنه لا توجد وسيلة للمترجم لمنع إنشاء رمز يمكن أن يتجاوز مكدس النظام ، وهو ما يبدو مثل مشكلة كبيرة بالنسبة لي. هل هذا هو الحال فعلا؟

تستخدم وظائف Wasm مكدس النظام مثل معظم التعليمات البرمجية الأخرى. يقوم المحرك بتنفيذ أدوات حماية المكدس ، ولكن بخلاف ذلك ، فإنه يستخدم مكدس النظام مثل أي مترجم ووقت تشغيل آخر. ونعم ، يمكن أن تفيض ، ولكن يتم اكتشاف مثل هذه الفيضانات. مكدس الظل هو شيء تم تقديمه بواسطة مترجم C ، وهو يحتوي فقط على السكان المحليين الذين يحتاجون إلى أن يكونوا في الذاكرة يمكن معالجتهم من C. ومن الواضح أن المحرك لا يمكنه تخزين عناوين الإرجاع أو المؤشرات الداخلية الأخرى هناك دون خلق مشاكل أمنية كبيرة.

ونعم ، يمكن أن تفيض ، ولكن يتم اكتشاف مثل هذه الفيضانات.

المشكلة التي أواجهها هي أن هذا التمييز ليس مفيدًا إذا كان تطبيق المترجم الذي يستهدف Wasm غير قادر على تنفيذ أي فحوصات لوقت التشغيل لمنع تجاوز المكدس ، أو التعافي من تجاوز وشيك ، كما هو ممكن في الأهداف الأخرى. ليس من الواضح لماذا من غير المرغوب فيه إتاحة ، على الأقل على أساس القراءة فقط ، مؤشر مكدس النظام الحالي ، بالإضافة إلى الحد الأقصى لحجم المكدس ، من أجل القيام بذلك. من الواضح أن وضع كل شيء على مكدس الظل لا يكفي لضمان أي شيء ، كما اقترح سابقًا ، لذا فإن خيارات اللغات الوظيفية هنا تبدو مروعة حقًا ، بصراحة.

يبدو أن نموذج C الخاص بي قد عكر المياه بدلاً من المساعدة في التوضيح ، لذلك أعتذر إذا كانت مشكلة أكثر مما تستحق. أنا لا أستخدم لغة C ولا أقوم بتوليدها ، لقد اخترتها لإبقاء المثال بسيطًا. ومع ذلك ، فإن المترجم الخاص بي يستخدم LLVM ، وسيستخدم العناصر الجوهرية التي يوفرها لـ Wasm ، والتي تعتمد بشكل طبيعي على الميزات المحددة في المواصفات. ولكن يبدو أنه لا توجد طريقة مدعومة لتطبيق اللغة على أساس _Cheney على MTA_ ، مثل لغتي ، لاستهداف Wasm دون إعادة هيكلة كبيرة ، والتي أظن أنها في معظم الحالات مجرد بداية.

لذا فإن السؤال الأهم بالنسبة لي هو: ما هو الطريق إلى الأمام لهذه اللغات / التطبيقات؟ وبالمثل ، ما الذي يمكن أن تفعله المواصفات لدعمها؟ اعتقدت أن أكبر قطعة مفقودة كانت الافتقار إلى دعم الاتصال الذيل الأصلي ، ولكن يبدو أن الخيارات النموذجية للعمل غير متوفرة بشكل أساسي ، أو غير عملية بسبب النفقات العامة. الاستثناء الوحيد هو استخدام الترامبولين البسيط - وإذا لم تبدأ من نقطة الصفر ، فإن إعادة تصميم التنفيذ الخاص بك حول ذلك أمر غير تافه في أحسن الأحوال.

مؤشر مكدس النظام هو عنوان جهاز فعلي. من الواضح أنه من غير الوارد كشف ذلك لرمز غير موثوق به على نظام أساسي حساس للأمان مثل الويب ، حتى لو كان للقراءة فقط ولا يمكن الوصول إليه.

من حيث المبدأ ، يمكن أن يوفر Wasm وسائل أكثر تجريدًا للاستعلام عن أحجام المكدس ومعالجتها. لكن تفاصيل كيفية توفير مثل هذه الآلية ليست واضحة ، انظر أعلاه. خاصة لأنهم سيقدمون درجة كبيرة من اللاحتمية الملحوظة. هناك طريق مرغوب فيه أكثر وهو أن يكون لديك آليات لزيادة المداخن في المحركات نفسها بدلاً من اختراق كل برنامج حولها.

بمجرد أن يصبح اقتراح استدعاء الذيل متاحًا ، يجب أن تكون المشكلة بسيطة بشكل معقول من الناحية العملية ، على الرغم من ذلك. ما تبقى هو قيود صارمة إلى حد ما على الموارد وحقيقة أن البرامج يمكن أن تموت بشكل غير متوقع عند تفجيرها ، ولكن هذا كان دائمًا حقيقة الويب. أعتقد أنه من المبالغة أن نقول إن هذا ممنوع ، ومن المؤكد أن واسم لا يزيد الأمر سوءًا.

مؤشر مكدس النظام هو عنوان جهاز فعلي. من الواضح أنه من غير الوارد كشف ذلك لرمز غير موثوق به على نظام أساسي حساس للأمان مثل الويب ، حتى لو كان للقراءة فقط ولا يمكن الوصول إليه.

أنا مهتم بمعرفة المزيد عن الثغرة (الثغرات) المحددة التي يمثلها هذا ، لكنني لا أزعم أن عناوين الأجهزة الحقيقية ضرورية. ما لم أفقد شيئًا ما ، يجب أن يكون عنوان مؤشر المكدس الذي يمكن الوصول إليه إلى كود Wasm فقط وكيلًا مفيدًا للموضع النسبي في مكدس النظام الذي يتم تنفيذ الكود فيه (على سبيل المثال ، يبدو أنه عنوان بين 0 و n ) ، ويمكن أن يكون الحد أصغر بشكل تعسفي من حجم مكدس النظام الحقيقي. يمنحك هذا ميزة القدرة على الاستعلام عن المكدس دون الكشف عن عناوين حقيقية خارج المحرك نفسه.

خاصة لأنهم سيقدمون درجة كبيرة من اللاحتمية الملحوظة.

هل يمكنك توضيح ما تعنيه بهذا؟ أنا أتحدث بشكل خاص عن القدرة على الاستعلام عن حجم المكدس ، ولا أعتقد أن التلاعب به هو هدف. من المؤكد أنه من المقبول بالنسبة للمحركات المختلفة أن يكون لها أحجام مكدس مختلفة ، لذا فإن تعريض هذا الحجم لن يؤدي إلى مزيد من اللاحتمية أكثر مما هو موجود بالفعل بشكل أساسي.

هناك طريق مرغوب فيه أكثر وهو أن يكون لديك آليات لزيادة المداخن في المحركات نفسها بدلاً من اختراق كل برنامج حولها.

يتعامل هذا مع مشكلة واحدة (المكدس صغير جدًا وبالتالي من السهل جدًا تجاوزه) ، ولكنه عرضي للمشكلة التي أحاول إثارتها.

بمجرد أن يصبح اقتراح استدعاء الذيل متاحًا ، يجب أن تكون المشكلة بسيطة بشكل معقول من الناحية العملية ، على الرغم من ذلك.

أوافق ، بالنسبة لبعض المجموعات الفرعية من اللغات على أي حال ، ولكن هذا الاقتراح لا يزال يبدو في وقت مبكر من دورته ، وسيأتي في الوقت المناسب. في غضون ذلك ، يعد الافتقار إليها ونقص الحلول البديلة مشكلة كبيرة بالنسبة للغات التي تتطلبها. لا يحتوي اقتراح استدعاء الذيل نفسه على حل للغات التي تستخدم المكدس للتخصيصات وجمع البيانات المهملة عن طريق القفز ، ولكن من المحتمل أن توفر فكرة الاستثناءات القابلة للاستئناف حلاً لذلك - ولكن هذا لا يتم العمل به بشكل نشط بقدر ما أنا أدرك أنه ممكن من الناحية النظرية بمجرد قبول اقتراح الاستثناءات.

ما تبقى هو قيود صارمة إلى حد ما على الموارد وحقيقة أن البرامج يمكن أن تموت بشكل غير متوقع عند تفجيرها ، ولكن هذا كان دائمًا حقيقة الويب. أعتقد أنه من المبالغة أن نقول إن هذا ممنوع ، ومن المؤكد أن واسم لا يزيد الأمر سوءًا.

القيود نفسها ليست مانعة ، وليست هي المشكلة الحقيقية. توجد قيود الموارد والمخاطر المرتبطة بها خارج الويب أيضًا ، ولكن هناك أدوات للتعامل معها هناك - في سياق حدود المكدس ، يمتلك المرء setjmp / longjmp ، يتحقق من المكدس والقمامة التجميع عن طريق القفز / العودة عندما يكون على وشك تجاوز السعة ، أو باستخدام الترامبولين. بشكل أساسي ، يمكن للمرء أن يضمن أنه إذا كنت على وشك تجاوز الحد ، فيمكن التعامل معه بأمان (أو السماح فقط بتجاوز الحد والإجهاض / الذعر). المشكلة مع Wasm التي أحاول إيجاد حل لها ، هي أن هذه الأدوات (باستثناء الترامبولين) تمت إزالتها (إما كليًا أو عمليًا كما هو الحال مع SJLJ) ، وليس لها بديل. بالنسبة للغات التي يستند تنفيذها بالكامل إلى تلك الأدوات ، فإن الافتقار إليها يعد بالتأكيد مشكلة رئيسية. أنا لا أقول على الإطلاق أن Wasm معيب بشكل أساسي أو شيء من هذا القبيل ، لكنني أعتقد أن هناك شيئًا مفقودًا في المواصفات هنا ، على وجه التحديد ، يتم تنفيذ بعض وسائل فهم القيود الحالية تحت (مثل حجم المكدس) وأين تكون نسبيًا تلك القيود (على سبيل المثال ، شيء يشبه العنوان الذي يمنحك فكرة عن موضعك بالنسبة إلى الحجم الأقصى للمكدس).

إذا كنت قد أسأت فهم شيء ما بشكل أساسي أو فاتني شيء ما ، فأنا بالتأكيد أتطلع إلى تعلم ذلك وإصلاحه. يبدو أن هذا شيء تم تجاهله ، بناءً على قراءة المواصفات والبحث في مختلف القضايا / المقترحات في المؤسسة. إذا كانت لديك روابط لمناقشات أخرى ذات صلة هنا ، فعليك بالتأكيد توجيهي إليها حتى أتمكن من تجنب إعادة صياغة أي شيء تمت مناقشته بالفعل ، أو على الأقل التأكد من أنني أحضر شيئًا جديدًا إلى الطاولة.

bitwalker :

خاصة لأنهم سيقدمون درجة كبيرة من اللاحتمية الملحوظة.

هل يمكنك توضيح ما تعنيه بهذا؟ أنا أتحدث بشكل خاص عن القدرة على الاستعلام عن حجم المكدس ، ولا أعتقد أن التلاعب به هو هدف. من المؤكد أنه من المقبول بالنسبة للمحركات المختلفة أن يكون لها أحجام مكدس مختلفة ، لذا فإن تعريض هذا الحجم لن يؤدي إلى مزيد من اللاحتمية أكثر مما هو موجود بالفعل بشكل أساسي.

حاليًا ، لا يمكن لـ Wasm code مراقبة تجاوزات المكدس ، لأنه سيتم إحباطها. لا يمكن أن تعتمد نتيجتها على حجم المكدس ، فقط النجاح مقابل الفشل. هذا يختلف تمامًا عن القدرة على النجاح بالنتيجة A أو بالنتيجة B اعتمادًا على المكدس.

بمجرد أن يصبح اقتراح استدعاء الذيل متاحًا ، يجب أن تكون المشكلة بسيطة بشكل معقول من الناحية العملية ، على الرغم من ذلك.

أوافق ، بالنسبة لبعض المجموعات الفرعية من اللغات على أي حال ، ولكن هذا الاقتراح لا يزال يبدو في وقت مبكر من دورته ، وسيأتي في الوقت المناسب.

الاقتراح في المرحلة 3 ، لذا سيكون متاحًا قريبًا نسبيًا. من غير المرجح أن يتم بدء اقتراح مختلف تمامًا من البداية بشكل أسرع.

المشكلة مع Wasm التي أحاول إيجاد حل لها ، هي أن هذه الأدوات (باستثناء الترامبولين) تمت إزالتها (إما كليًا أو عمليًا كما هو الحال مع SJLJ) ، وليس لها بديل.

كانت وجهة نظري أن هذه الأدوات لم تكن متوفرة على الويب مطلقًا ، لذلك ربما لا ينبغي أن يكون مفاجئًا إذا لم تكن متوفرة في Wasm أيضًا.

كانت وجهة نظري أن هذه الأدوات لم تكن متوفرة على الويب مطلقًا ، لذلك ربما لا ينبغي أن يكون مفاجئًا إذا لم تكن متوفرة في Wasm أيضًا.

بالتأكيد ، ولكن الآن بعد أن فتح Wasm إمكانية هذه الأدوات ، ألا يجب أن تسعى المواصفات جاهدة لتحديدها ومعالجتها؟

لذا فإن السؤال الأهم بالنسبة لي هو: ما هو الطريق إلى الأمام لهذه اللغات / التطبيقات؟

في الوقت الحالي ، استخدم مكدس الظل ، تمامًا مثل ما يفعله كود C في بنية غير محسّنة ، وكما ذكرت في ردي الأول.

لا يجب أن يكون ذلك بطيئًا بشكل كارثي ، فلا يزال بإمكانك تحميل المتغيرات إلى السكان المحليين في الداخل كوظيفة واحدة ، والحصول على بعض فوائد استخدام التسجيل. أيضًا لديك الآن معالجة مكدس رخيصة للغاية نظرًا لأنك تتحكم في كل ذلك.

كما يقول rossberg ، في حين أنه من الممكن نظريًا ، لا أرى أنه من المحتمل أن يوفر wasm وصولًا كافيًا إلى مكدس wasm بحيث يمكنك تنفيذ كل هذه الوظائف هناك.

عدد اللغات التي تنحرف في نموذج التنفيذ عن نموذج C لا حصر له ، ومن غير المحتمل أن ندعمها جميعًا بشكل مباشر. في الواقع ، نحن لا ندعم C بشكل مباشر :) ستساعد مكالمات الذيل والاستثناءات القابلة للاستئناف البعض ، لكن "تدوير إطارات المكدس الخاصة بك" سيظل خيارًا شائعًا أتوقعه.

الاقتراح في المرحلة 3 ، لذا سيكون متاحًا قريبًا نسبيًا. من غير المرجح أن يتم بدء اقتراح مختلف تمامًا من البداية بشكل أسرع.

هذه أخبار رائعة! لم أر كثيرًا من الحركة ، ولا يزال من غير الواضح بالنسبة لي ما إذا كان الاقتراح الفعلي يحتوي على مكالمات ذيل مناسبة أو شيء أكثر تقييدًا. لكن المكالمات الخلفية ليست سوى جزء من المشكلة ؛ إدارة الذاكرة هي الجانب الرئيسي الآخر من هذا.

التخصيص على المكدس عندما يكون ذلك ممكنًا هو الأفضل دائمًا ، لأنه في معظم الأنظمة ، يكون المكدس مساحة من الذاكرة يتم تحسين الوصول إليها بالنسبة إلى الذاكرة الرئيسية. في الحالات التي لا تعمل فيها ، فهي تعمل مثل أي ذاكرة أخرى. يتبع ذلك أنه إذا كان المكدس مجانيًا في الغالب ، لأن جميع الوظائف في برنامجك هي مكالمات ذيلية ، وبالتالي لا تستهلك مساحة مكدس ، فأنت تريد استخدام مساحة المكدس المجانية هذه للتخصيصات المؤقتة. للقيام بذلك ، تحتاج إلى معرفة ما إذا كان التخصيص سينجح أو يفشل ، عن طريق التحقق من كمية المكدس المتبقية. علاوة على ذلك ، يبسط مثل هذا النموذج عملية جمع القمامة بشكل كبير ، حيث يمكن بسهولة جمع القمامة في مساحة المكدس إما عن طريق العودة إلى الترامبولين ، أو عن طريق التلاعب بمؤشر المكدس. النهج الذي تستخدمه ليس له أي أهمية هنا ، ما يهم هو أنه يمكنك معرفة متى يجب أن يحدث GC.

بصفتك منفذًا للغة ، لا تريد أيضًا أن يكون لديك طريقتان مختلفتان تمامًا لإدارة الذاكرة بناءً على ما إذا كنت تستهدف WebAssembly أم لا. عدم تحسين المكدس لا يمثل خسارة كبيرة ، ولكن الاضطرار إلى _تجنب_ المكدس على نظام أساسي واحد يعني أنه يتعين عليك تغيير كل من كود التخصيص وتطبيقات جمع البيانات المهملة بشكل كبير. يعد هذا عبئًا كبيرًا على المجمعين الذين يمثل WebAssembly هدفًا واحدًا فقط ممكنًا له. في المواقف التي لا يمكن تجنبها ، عليك فقط تناول هذه التكلفة أو تجنب دعم النظام الأساسي ؛ ولكن هذا ينطبق فقط على WebAssembly إذا لم ينجح أي اقتراح لإجراء هذا التغيير.

كانت وجهة نظري أن هذه الأدوات لم تكن متوفرة على الويب مطلقًا ، لذلك ربما لا ينبغي أن يكون مفاجئًا إذا لم تكن متوفرة في Wasm أيضًا.

لست مندهشًا من عدم توفرها - تمامًا الآن - ، لكنني مندهش ومحبط لسماع هذا النوع من الإجابات ، خاصة منك ، والتي يبدو أنها تقول ذلك لأن شيئًا ما لم يكن متاحًا على الويب تاريخيًا ، لا يستحق النظر. يشهد WebAssembly بالفعل استخدامه خارج الويب ، وقد تم ذكر حالات الاستخدام هذه في المواصفات / المواد الخاصة بـ WebAssembly نفسه! ناهيك عن أن WebAssembly يقوم بالفعل بإحضار أدوات لم تكن متوفرة من قبل إلى الجدول ؛ مكالمات الذيل واحدة منهم فقط.

لا شيء عن الويب (الذي أعلم به) يضع قيودًا بشكل أساسي على القدرة على الاستعلام عن معلومات حول مساحة المكدس - هذه مجرد تفاصيل تنفيذية لكيفية عمل المحركات اليوم ، ولم تكن هناك حاجة إليها مطلقًا في JS ، فلماذا تكون موجودة ؟ إذا أراد مطورو المحرك إتاحته لـ WebAssembly ، يمكنهم ذلك ، لكنني أشك في أنهم يميلون إلى القيام بذلك دون دافع. أنا أدافع بهدف محاولة شرح سبب ضرورة ذلك. لتحقيق هذه الغاية ، أعمل أيضًا على التواصل مع مجموعة متنوعة من مهندسي مترجم اللغة الوظيفية لجمع المزيد من حالات الاستخدام والتعليقات ، والتي آمل أن أشاركها هنا قريبًا.

من أكثر الأشياء إلهامًا حول WebAssembly أنه لديه القدرة على تمكين الكثير مما لم يكن ممكنًا في السابق على الويب ، أو كان ممكنًا ولكن بجهد كبير وتكلفة كبيرة. أتفق بشكل عام مع الرأي القائل بأن WebAssembly يدور حول الويب أولاً وقبل كل شيء ، ولكن ما لم تكن هناك مشكلة أساسية في بعض المقترحات ، لست متأكدًا من أننا يجب أن نغلق الباب أمام الأفكار لمجرد أنها ليست موجودة بالفعل في شكل. بعد كل شيء ، أليس هذا هو الغرض من عملية الاقتراح هنا؟

في الوقت الحالي ، استخدم مكدس الظل ، تمامًا مثل ما يفعله كود C في بنية غير محسّنة ، وكما ذكرت في ردي الأول.

هذا ليس خيارًا قابلاً للتطبيق ، كما أشير سابقًا ، لأنه لا توجد مراسلات مباشرة بين مكدس الظل ومكدس النظام ؛ هذا يعني أن منع الفيضانات ، وهي النقطة ، ليس مضمونًا. الضمان ضروري لاستدعاءات الذيل ، وكذلك لتقرير وقت إجراء التخصيصات على المكدس مقابل الكومة و / أو المشغل GC.

لا يجب أن يكون ذلك بطيئًا بشكل كارثي ، فلا يزال بإمكانك تحميل المتغيرات إلى السكان المحليين في الداخل كوظيفة واحدة ، والحصول على بعض فوائد استخدام التسجيل. أيضًا لديك الآن معالجة مكدس رخيصة للغاية نظرًا لأنك تتحكم في كل ذلك.

كيف تقترح أن أقوم بتنفيذ مكدس الخاص بي؟ يعني التجميع إلى الكود الأصلي استخدام المكدس الأصلي ، وهذا يعني في هذه الحالة مكدس ظل Wasm ، والذي _لا نملك_ التحكم الكامل فيه. يعد تجميع برنامج في إرسال حلقة / تبديل عملاقة حلاً مروعًا ، لعدد من الأسباب. البديل الوحيد الحالي هو الترامبولين لكل مكالمة ، ولكن كما ذكرنا سابقًا ، بالإضافة إلى تكلفة الأداء ، فإنه لا يزال يتجاهل أي لغة ترغب في أداء GC باستخدام _Cheney على جامع MTA style_ Genational ، أو استخدام المكدس للتخصيصات.

عدد اللغات التي تنحرف في نموذج التنفيذ عن نموذج C لا حصر له ، ومن غير المحتمل أن ندعمها جميعًا بشكل مباشر. في الحقيقة نحن لا ندعم C بشكل كامل :)

مما رأيته ، فإن كل لغة وظيفية تقريبًا (Haskell ، Lisp ، ML ، Prolog) لها مترجم / تنفيذ واحد على الأقل يولد لغة C ، والنماذج التي تمثلها تلك اللغات تغطي بشكل أساسي المساحة الكاملة للغات البرمجة الوظيفية. Erlang ، على سبيل المثال ، تشبه إلى حد بعيد ML في تمثيلها الأساسي. تختلف كل هذه اللغات اختلافًا كبيرًا عن C من الناحية الدلالية ، ولكن مع ذلك يمكن ترجمتها جميعًا إلى شيء يمكن أن يتناسب مع نموذج C. لا أعتقد أننا نتحدث عن مشكلة دعم كل تفاصيل التنفيذ الممكنة ، ولكن وجود أساسيات للاستعلام عن استخدام المكدس هو مصدر قلق شامل يؤثر على جميع أنواع اللغات ، بما في ذلك C.

ستساعد مكالمات الذيل والاستثناءات القابلة للاستئناف البعض ، ولكن "تدوير إطارات المكدس الخاصة بك" سيظل خيارًا شائعًا أتوقعه.

هل لديك مثال لمترجم لغة يستهدف Wasm ، ويقوم بتدوير إطارات المكدس الخاصة به ، وليست لغة مفسرة؟ أنت تقول إنه شائع ، لكنني لا أراه ، لكن ربما أنا فقط أبحث في الأماكن الخطأ. أظن أن هذه مشكلة أيضًا لـ FFI ، لكني لا أعرف ما يكفي عن التنفيذ المقترح لأقوله.

ربما ينبغي أن أقوم بفتح إصدار جديد خصيصًا للأولويات المكدسة التي أعتقد أنها ضرورية؟ لم يعد هذا الموضوع _ حقًا_ متعلقًا بالاستمرارات على وجه التحديد ، ولا يتعلق أيضًا باستدعاءات الذيل. قد يساعدك الضغط على زر إعادة الضبط ، إذا جاز التعبير.

تضمين التغريدة

ربما ينبغي أن أقوم بفتح إصدار جديد خصيصًا للأولويات المكدسة التي أعتقد أنها ضرورية؟

لتحقيق هذه الغاية ، أعمل أيضًا على التواصل مع مجموعة متنوعة من مهندسي مترجم اللغة الوظيفية لجمع المزيد من حالات الاستخدام والتعليقات ، والتي آمل أن أشاركها هنا قريبًا.

في هذه المرحلة ، نعم ، أعتقد أنه يجب عليك فتح قضية منفصلة.

أعتقد أنه يجب عليك أيضًا إعداد قائمة بأساسيات المكدس التي تطلبها بالضبط. أعلم أنه بصرف النظر عن الميزات مثل المكالمات الخلفية و SJLJ المضمنة التي تم التخطيط لها بالفعل ، فأنت تريد أن تكون قادرًا على التنبؤ بالوقت الذي قد يتجاوز فيه مكدس المكالمات الداخلية مسبقًا. هل هذا كل ما تحتاجه؟

في هذه المرحلة ، نعم ، أعتقد أنه يجب عليك فتح قضية منفصلة.

سوف تفعل

... ترغب في أن تكون قادرًا على التنبؤ بموعد تجاوز مكدس المكالمات الداخلية مسبقًا. هل هذا كل ما تحتاجه؟

حسنًا ، أفكر في عكس الأوليات بشكل أو بآخر التي قد يستخدمها المرء في مكان آخر:

  • حد حجم المكدس ، يمكن أن يكون هذا أصغر بشكل تعسفي من حد حجم المكدس _real_ ، ولكنه سيحقق هدف توفير حد أعلى لمقدار المكدس المتاح.
  • موضع المكدس ، هذا ليس مؤشرًا ، بل هو موضع متعلق بحد المكدس. يوفر هذا طريقة لتقييم مقدار المكدس المتبقي.

ولكن يمكن طيها في "مساحة مكدس متبقية" بدائية واحدة ، والتي لا توفر لك حدًا أو موضعًا ، إذا كان ذلك مفضلاً. نظرًا لأن بعض الأشياء تعيش في Wasm shadow stack ، والبعض الآخر على المكدس المضيف ، يجب على المرء أن يأخذ في الاعتبار كلاً من العناصر بدلاً من واحد فقط عند اتخاذ القرارات ، وبقدر ما يتعلق الأمر بمكدس المضيف ، أعتقد أنه من الضروري حقًا فقط تعرف على مقدار المساحة المتبقية.

باستخدام هذه ، يمكن للمترجم إنشاء رمز من شأنه التحقق من المكدس المتبقي ، وتحديد ما إذا كانت مجموعة القمامة / الترامبولين مطلوبة أم لا ، ثم إجراء تخصيصات المكدس التي يحتاجها ، وإجراء أي حساب محلي ، ثم المتابعة عن طريق استدعاء استمرار (بشكل عام آخر call ، ولكن يمكن أن تكون قفزة محلية في بعض الحالات) ، والتي في حالة المكالمة ، ستدخل الوظيفة الجديدة وتتحقق مرة أخرى من المكدس المتبقي وتقرر كيفية المتابعة. جزء مهم من هذا التدفق هو القدرة على معرفة أين سيتم تخصيص الأشياء ، بحيث يتم التحقق من الحد الصحيح. لست واضحًا بنسبة 100٪ بشأن كل ما قد ينتهي به المطاف في حزمة المضيف ، لذلك سأحاول ومتابعة ذلك اليوم قبل فتح مشكلة جديدة.

كانت وجهة نظري أن هذه الأدوات لم تكن متوفرة على الويب مطلقًا ، لذلك ربما لا ينبغي أن يكون مفاجئًا إذا لم تكن متوفرة في Wasm أيضًا.

بالنظر إلى أن لغة مثل لغة pyret @ shriram تنبثق من نظرة عميقة إلى الإخفاقات ونقاط النجاح الخاصة بأهم اللغات الموجودة (بما في ذلك جافا سكريبت) ، فإن تعليقه يحمل وزنًا https://github.com/WebAssembly/design/issues/ 919 # إصدار -348000242. Javascript عبارة عن شريط منخفض ، والنقطة الرئيسية التي تم الحصول عليها من أجلها هي أنها موجودة في كل مكان بسبب المشاركة في نشر المحتوى عبر أنظمة شبكة من نقطة إلى نقطة. تنشأ احتكارات نشر البيانات كسلوك ناشئ لنشر البيانات عبر نظام اتصال من نقطة إلى نقطة. ركبت لغة تم تصميمها في 10 أيام على ذيول المعطف لعقدة tcp / ip الثقيلة المخصصة لخدمة الإعلانات ، وهي ليست خاصة ولم تصل إلى وضعها الحالي من خلال مزاياها. لدينا فرصة لتصحيح الأخطاء ولا نطلب الكثير من الأطر لإعادة تنفيذ الاستمرارية النصفية. التكلفة الإجمالية للملكية (TCO) هي خطوة رائعة في الاتجاه الصحيح.

تسمح عمليات الاستمرارية بلغات البرمجة الوظيفية المتزامنة المناسبة والتي تحتوي على مفاعلات تبث البيانات إلى نقاط متعددة (وليس فقط خوادم GAFAM!). خاصة عندما تصبح البيانات قابلة للعنونة بشكل مباشر ولا نحتاج إلى الحصول على بيانات مفهرسة عن طريق معالجة عقد Google. يفيد google أن يكون لديها بيئة تنفيذ مترابطة واحدة حيث تعمل بشكل جيد على تحويل الإعلانات إلى أسفل أنبوب عميل / خادم IP. الاستمرارية المناسبة تعطينا خيارات أفضل. يمكن أن يكون المتصفح أكثر بكثير من مجرد آلة تقديم الإعلانات المعطلة عمداً كما هو الحال اليوم.

بعد قليل على هذه المحادثة ، التي لم أكن أعرف أنها تحدث ، ولكن bitwalker قد تجد أنه من المفيد إلقاء نظرة (ربما ليس بعد الآن!) على موقع Stopify [الموقع: https://www.stopify.org ] ، [مقالة: https://cs.brown.edu/~sk/Publications/Papers/Published/bnpkg-stopify/ ] ، [repo: https://github.com/plasma-umass/Stopify ].

يقدم مترجم JS-> JS عام الذي ينفذ تحويلات مماثلة ويتضمن تحسينات لتوفير الاستمرارية. يوضح كيف يمكن إثراء العديد من لغات JS-transpiled تلقائيًا باستخدام هذه التحولات.

بينما ما زلت أرغب في رؤية دعم محلي أفضل (انظر أرقام أدائنا) ، تقدم Stopify مسارًا جيدًا (انظر أرقام أدائنا) من واقع اليوم إلى هذا الحلم. على وجه الخصوص ، فإنه يأخذ الكثير من الفوضى من نظام وقت التشغيل ، ويفصل بين مخاوف اللغة الأساسية والمخاوف المتعلقة بالاستمرارية.

CCarjunguhajpolitzrachitnigam

كمتابعة لبعض تعليقاتي أعلاه ، من المحتمل أن أقوم بالربط مع عرضي التقديمي من اجتماع فبراير 2020 ، مع عرض أفكار لإضافة معالجات تبديل المكدس / coroutines / الاستمرارية / التأثير إلى Wasm .

إغلاق لصالح # 1359

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

aaabbbcccddd00001111 picture aaabbbcccddd00001111  ·  3تعليقات

spidoche picture spidoche  ·  4تعليقات

cretz picture cretz  ·  5تعليقات

JimmyVV picture JimmyVV  ·  4تعليقات

mfateev picture mfateev  ·  5تعليقات