RednaxelaFX 发表于 2013-1-27 04:58:03

目前DLR执行一棵DLR tree的过程(针对10月3日的ChangeSet 41087)

先在Microsoft.Scripting.Actions.CallSite<T>的构造器设断点,然后开始调试。

在IronPythonConsole里,输入1+2回车,然后观察调用栈。可以看到在很多层调用之前是一个对Microsoft.Scripting.Generation.GlobalRewriter.RewriteLambda(lambda)的调用(注意到GlobalRewriter近期将会被refactor而去除掉,CodeContext也会消失掉)。在rewrite前,lambda(也就是console所执行的main,委托类型为DlrMainCallTarget)是:
//// AST: Expression`1//.lambda (<module> Microsoft.Func`1 #1)//// LAMBDA: <module>(1)//.lambda System.Object <module> ()() {    .scope <module> (      System.Int32 $lineNo      System.Boolean $lineUpdated    ) {      {            (PythonOps.ModuleStarted)(                .extension (CodeContext) ;                ,                (BinderState)IronPython.Runtime.Binding.BinderState,                (PythonLanguageFeatures)Default,            )            (.var $lineNo) = 0            (.var $lineUpdated) = (Boolean)False            .try {                {                  {                  }                  /*empty*/;                  {                        (.var $lineNo) = 1                        {                            (PythonOps.PrintExpressionValue)(                              .extension (CodeContext) ;                              ,                              .site (Object) Operation Add( // Python Add                                    1                                    2                              ),                            )                        }                  }                }            } .fault {                {                  .if (!(.var $lineUpdated) ) {(ExceptionHelpers.UpdateStackTrace)(                        .extension (CodeContext) ;                        ,                        (MethodBase.GetCurrentMethod)(),                        "<module>",                        "<stdin>",                        (.var $lineNo),                  )} .else {/*empty*/;                  }                  (.var $lineUpdated) = (Boolean)True                }            }      }    }}
rewrite后则是:
//// AST: Expression`1//.lambda (<module> Microsoft.Func`1 #1)//// LAMBDA: <module>(1)//.lambda System.Object <module> ()() {    .scope <module> (      System.Int32 $lineNo      System.Boolean $lineUpdated    ) {      {            (PythonOps.ModuleStarted)(                (.var $globalContext),                (BinderState)IronPython.Runtime.Binding.BinderState,                (PythonLanguageFeatures)Default,            )            (.var $lineNo) = 0            (.var $lineUpdated) = (Boolean)False            .try {                {                  {                  }                  /*empty*/;                  {                        (.var $lineNo) = 1                        {                            (PythonOps.PrintExpressionValue)(                              (.var $globalContext),                              .scope (                                    Microsoft.Scripting.Actions.CallSite`1] $site                              ) {                                    ((.var $site) = (CallSite`1)Microsoft.Scripting.Actions.CallSite`1].Target).(Func`4.Invoke)(                                        (.var $site),                                        1,                                        2,                                    )}                              ,                            )                        }                  }                }            } .fault {                {                  .if (!(.var $lineUpdated) ) {(ExceptionHelpers.UpdateStackTrace)(                        (.var $globalContext),                        (MethodBase.GetCurrentMethod)(),                        "<module>",                        "<stdin>",                        (.var $lineNo),                  )} .else {/*empty*/;                  }                  (.var $lineUpdated) = (Boolean)True                }            }      }    }}
Rewrite的意义在于把所有DynamicExpression重写为静态类型的节点,其中的动态行为则编译为CallSite的初始化(Expression.Constant())与调用(Expression.Call())。

编译出来的委托的类型为Func<Microsoft.Runtime.CompilerServices.Closure, Microsoft.Scripting.Runtime.Scope, Microsoft.Scripting.Runtime.LanguageContext, object>,内容是:
IL_0000:ldarg.1IL_0001:ldarg.2IL_0002:call       Microsoft.Scripting.Runtime.CodeContext CreateTopLevelCodeContext(Microsoft.Scripting.Runtime.Scope, Microsoft.Scripting.Runtime.LanguageContext)/Microsoft.Scripting.Runtime.RuntimeHelpersIL_0007:stloc.2IL_0008:ldloc.2IL_0009:ldarg.0IL_000a:ldfld      !"指定的转换无效。"!IL_000f:ldc.i4.0IL_0010:ldelem.refIL_0011:ldc.i4.0IL_0012:call       Void ModuleStarted(Microsoft.Scripting.Runtime.CodeContext, System.Object, IronPython.Compiler.PythonLanguageFeatures)/IronPython.Runtime.Operations.PythonOpsIL_0017:ldc.i4.0IL_0018:stloc.0IL_0019:ldc.i4.0IL_001a:stloc.1IL_001b:ldc.i4.1IL_001c:stloc.0IL_001d:ldloc.2IL_001e:ldarg.0IL_001f:ldfld      !"指定的转换无效。"!IL_0024:ldc.i4.1IL_0025:ldelem.refIL_0026:castclassMicrosoft.Scripting.Actions.CallSite`1]IL_002b:dupIL_002c:stloc.3IL_002d:ldfld      !"指定的转换无效。"!IL_0032:ldloc.3IL_0033:ldc.i4.1IL_0034:ldc.i4.2IL_0035:callvirt   System.Object Invoke(Microsoft.Scripting.Actions.CallSite, Int32, Int32)/Microsoft.Func`4IL_003a:call       Void PrintExpressionValue(Microsoft.Scripting.Runtime.CodeContext, System.Object)/IronPython.Runtime.Operations.PythonOpsIL_003f:leave      IL_006cIL_0044:ldloc.1IL_0045:ldc.i4.0IL_0046:ceqIL_0048:brfalse    IL_0063IL_004d:ldloc.2IL_004e:call       System.Reflection.MethodBase GetCurrentMethod()/System.Reflection.MethodBaseIL_0053:ldstr      "<module>"IL_0058:ldstr      "<stdin>"IL_005d:ldloc.0IL_005e:call       Void UpdateStackTrace(Microsoft.Scripting.Runtime.CodeContext, System.Reflection.MethodBase, System.String, System.String, Int32)/Microsoft.Scripting.Runtime.ExceptionHelpersIL_0063:ldc.i4.1IL_0064:stloc.1IL_0065:rethrowIL_0067:leave      IL_006cIL_006c:ldnullIL_006d:ret
执行这个委托,在原本的加法调用点会进入到先前生成的UpdateDelegates.Update2<Func<CalSite,int,int,object>,int,int,object>中,进而调用CallSite<T>.UpdateAndExecute()。

此时,该调用点尚未有任何调用记录,所以会生成一个新的monomorphic rule(CallSite<T>.CreateNewRule())。在这里,通过CallSiteBinder<T>.Bind()(具体来说是IronPython.Runtime.Binding.OperationBinder,{Python Add};Bind()方法来自MetaAction类)得到一个Rule<Func<CalSite,int,int,object>>:
//// AST: Rule//.scope <rule> () {    .scope (    ) {      .return (Int32Ops.Add)(            (.arg $arg0),            (.arg $arg1),      );    }}
接下来,这个Rule<T>会被加入Level 2 Cache,然后赋值给Level 0 Cache并执行,如果成功则加入Level 1 Cache并将执行结果返回;失败的话则会尝试再次创建Rule<T>,重复上述创建过程。

这样就完成了一次1+2的执行。上面省略了一些Python特定的步骤(如PythonBinder、PythonOps里许多初始化),专注于DLR一侧的运行步骤。
页: [1]
查看完整版本: 目前DLR执行一棵DLR tree的过程(针对10月3日的ChangeSet 41087)