目前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]