`
RednaxelaFX
  • 浏览: 3016031 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

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

    博客分类:
  • DLR
阅读更多
先在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[System.Object] #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[System.Object] #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[Microsoft.Func`4[Microsoft.Scripting.Actions.CallSite,System.Int32,System.Int32,System.Object]] $site
                                ) {
                                    ((.var $site) = (CallSite`1)Microsoft.Scripting.Actions.CallSite`1[Microsoft.Func`4[Microsoft.Scripting.Actions.CallSite,System.Int32,System.Int32,System.Object]].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.1
IL_0001:  ldarg.2
IL_0002:  call       Microsoft.Scripting.Runtime.CodeContext CreateTopLevelCodeContext(Microsoft.Scripting.Runtime.Scope, Microsoft.Scripting.Runtime.LanguageContext)/Microsoft.Scripting.Runtime.RuntimeHelpers
IL_0007:  stloc.2
IL_0008:  ldloc.2
IL_0009:  ldarg.0
IL_000a:  ldfld      !"指定的转换无效。"!
IL_000f:  ldc.i4.0
IL_0010:  ldelem.ref
IL_0011:  ldc.i4.0
IL_0012:  call       Void ModuleStarted(Microsoft.Scripting.Runtime.CodeContext, System.Object, IronPython.Compiler.PythonLanguageFeatures)/IronPython.Runtime.Operations.PythonOps
IL_0017:  ldc.i4.0
IL_0018:  stloc.0
IL_0019:  ldc.i4.0
IL_001a:  stloc.1
IL_001b:  ldc.i4.1
IL_001c:  stloc.0
IL_001d:  ldloc.2
IL_001e:  ldarg.0
IL_001f:  ldfld      !"指定的转换无效。"!
IL_0024:  ldc.i4.1
IL_0025:  ldelem.ref
IL_0026:  castclass  Microsoft.Scripting.Actions.CallSite`1[Microsoft.Func`4[Microsoft.Scripting.Actions.CallSite,System.Int32,System.Int32,System.Object]]
IL_002b:  dup
IL_002c:  stloc.3
IL_002d:  ldfld      !"指定的转换无效。"!
IL_0032:  ldloc.3
IL_0033:  ldc.i4.1
IL_0034:  ldc.i4.2
IL_0035:  callvirt   System.Object Invoke(Microsoft.Scripting.Actions.CallSite, Int32, Int32)/Microsoft.Func`4[Microsoft.Scripting.Actions.CallSite,System.Int32,System.Int32,System.Object]
IL_003a:  call       Void PrintExpressionValue(Microsoft.Scripting.Runtime.CodeContext, System.Object)/IronPython.Runtime.Operations.PythonOps
IL_003f:  leave      IL_006c
IL_0044:  ldloc.1
IL_0045:  ldc.i4.0
IL_0046:  ceq
IL_0048:  brfalse    IL_0063
IL_004d:  ldloc.2
IL_004e:  call       System.Reflection.MethodBase GetCurrentMethod()/System.Reflection.MethodBase
IL_0053:  ldstr      "<module>"
IL_0058:  ldstr      "<stdin>"
IL_005d:  ldloc.0
IL_005e:  call       Void UpdateStackTrace(Microsoft.Scripting.Runtime.CodeContext, System.Reflection.MethodBase, System.String, System.String, Int32)/Microsoft.Scripting.Runtime.ExceptionHelpers
IL_0063:  ldc.i4.1
IL_0064:  stloc.1
IL_0065:  rethrow
IL_0067:  leave      IL_006c
IL_006c:  ldnull
IL_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 楼 cajon 2008-10-07  
难得有篇短一点的。收藏先,回头有机会看看这里的实现。

相关推荐

Global site tag (gtag.js) - Google Analytics