سؤال

وأنا ألعب مع F # في beta2 VS2010، وأنا منذ جديدة لF #، أنا فقط اختار واحدة من الأمثلة الشائعة وذهبت إلى الأمام وتنفيذ وظيفة مضروب على النحو التالي:

let rec factorial n =
  if n <= 1 then 1 else n * factorial (n - 1);;

إذا كنت أبني هذا وإلقاء نظرة على الشفرة التي تم إنشاؤها في العاكس، وأحصل على المقابلة C # رمز:

public static int Factorial(int n) {
   if (n <= 1) 
      return 1;

      return n * Factorial(n - 1);
}

وحتى لو كنت تجميع C # تمثيل العاكس للو# رمز F، أتوقع أن يحصل متطابقة IL.

ولكن، إذا كنت تجميع كل من هذه القصاصات في وضع إطلاق ومقارنة IL لدت، فهي مختلفة (كانت متطابقة وظيفيا، ولكن لا يزال يختلف قليلا).

وتنفيذ C # يجمع إلى:

.method public hidebysig static int32 Factorial(int32 n) cil managed
{
   .maxstack 8
   L_0000: ldarg.0 
   L_0001: ldc.i4.1 
   L_0002: bgt.s L_0006
   L_0004: ldc.i4.1 
   L_0005: ret 
   L_0006: ldarg.0 
   L_0007: ldarg.0 
   L_0008: ldc.i4.1 
   L_0009: sub 
   L_000a: call int32 TestApp.Program::Factorial(int32)
   L_000f: mul 
   L_0010: ret 
}

و # تنفيذ F يجمع إلى:

.method public static int32 factorial(int32 n) cil managed
{
   .maxstack 5        <=== Different maxstack
   L_0000: nop        <=== nop instruction?
   L_0001: ldarg.0 
   L_0002: ldc.i4.1 
   L_0003: bgt.s L_0007
   L_0005: ldc.i4.1 
   L_0006: ret 
   L_0007: ldarg.0 
   L_0008: ldarg.0 
   L_0009: ldc.i4.1 
   L_000a: sub 
   L_000b: call int32 FSharpModule::factorial(int32)
   L_0010: mul 
   L_0011: ret 
}

والشفرة التي تم إنشاؤها مطابق باستثناء maxstack مختلفة وتعليمات NOP إضافي في # طريقة F.

وربما هذه ليست كبيرة، ولكن أنا الغريب لماذا # مترجم F سوف تضاف NOP في إنشاء إصدار.

ويمكن لأي شخص أن يفسر لماذا؟

(وأنا أدرك تماما أن # مترجم F لم تذهب من خلال نفس المستوى من اختبار العالم الحقيقي مثل C # المترجم، ولكن هذا واضح لدرجة أنني الصورة قد تم القبض عليه).

وتحرير: الأمر الترجمة على النحو التالي

C:\Program Files\Microsoft F#\v4.0\fsc.exe -o:obj\Release\FSharpLib.dll 
--debug:pdbonly --noframework --define:TRACE --optimize+ 
--target:library --warn:3 --warnaserror:76 --vserrors --utf8output --fullpaths 
--flaterrors "C:\Temp\.NETFramework,Version=v4.0.AssemblyAttributes.fs" Module1.fs 

و(التجميعات المشار إزالة الإيجاز).

هل كانت مفيدة؟

المحلول

ويرجع ذلك إلى حقيقة أن C # مترجم يجمع الأسلوب الأول مع «خفيفة» طريقة رأس هيئة الفرق maxstack، التي يتم استخدامها كلما رمز صغير، لا يوجد استثناءات ولا السكان المحليين. في هذه الحالة، لم يتم تحديد maxstack والتخلف إلى 8.

و # مترجم F يستخدم «الدهون» طريقة رأس الجسم، ويحدد maxstack ويحسب ذلك.

وأما بالنسبة للNOP، انها لأنك تجميع في وضع التصحيح. يبدأون دائما الجسم الأسلوب مع NOP. ترى من fsharp / ilxgen.ml:

// Add a nop to make way for the first sequence point. There is always such a 
// sequence point even when zapFirstSeqPointToStart=false
do if mgbuf.cenv.generateDebugSymbols  then codebuf.Add(i_nop);

إذا كنت تجميع مضروب دون رموز التصحيح، وأنا لا تحصل على نوب.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top