[Ironruby-core] Interpreter, backtrace, and call site caching

Shri Borde Shri.Borde at microsoft.com
Tue Dec 30 17:27:46 EST 2008


For backtraces to work correctly in interpreter mode, it is required that the interpreter guard every call to C# code with a try-catch, so that the catch block has a chance to stash away the backtrace if an exception is thrown. This is done in Interpreter.InvokeMethod, and the catch block gives the language a chance to save the backtrace by calling LanguageContext.InterpretExceptionThrow.

However, with call-site caching enabled in interpreter mode, Interpreter.InterpretMetaAction can directl invoke the compiled delegate instead of calling Interpreter.InvokeMethod. This breaks the backtrace.

        private static object InterpretMetaAction(InterpreterState state, DynamicMetaObjectBinder action, DynamicExpression node, object[] argValues) {
...

            callSiteInfo.Counter++;
            if (callSiteInfo.Counter > SiteCompileThreshold) {
                if (callSiteInfo.CallSite == null) {
                    SetCallSite(callSiteInfo, node);
                }
                return callSiteInfo.CallerTarget(callSiteInfo.CallSite, argValues);
            }

...
            var result = Interpret(state, binding.Expression);
            return result;
        }

Is this a known issue? The interpreter stack trace in the unoptimized case is shown below. The fix could be for the interpreter to maintain a separate cache of compiled rules which have a try-catch generated for all MethodCallExpression nodes so as to match the unoptimized code behavior.

Thanks,
Shri


                Microsoft.Scripting.dll!Microsoft.Scripting.Utils.ReflectedCaller.Invoke(object[] args = {object[0x00000001]}) Line 46 + 0x19 bytes C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.InvokeMethod(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Reflection.MethodInfo method = {System.Reflection.RuntimeMethodInfo}, object instance = null, object[] parameters = {object[0x00000001]}) Line 135 + 0xb bytes            C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.InterpretMethodCallExpression(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Linq.Expressions.Expression expr = {System.Linq.Expressions.MethodCallExpressionN}) Line 251 + 0x30 bytes           C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.Interpret(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Linq.Expressions.Expression expr = {System.Linq.Expressions.MethodCallExpressionN}) Line 38 + 0xb bytes               C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.InterpretAndCheckFlow(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Linq.Expressions.Expression node = {System.Linq.Expressions.MethodCallExpressionN}, out object result = null) Line 76 + 0x11 bytes             C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.InterpretBlockExpression(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Linq.Expressions.Expression expr = {System.Linq.Expressions.Block2}) Line 1256 + 0xf bytes                C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.Interpret(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Linq.Expressions.Expression expr = {System.Linq.Expressions.Block2}) Line 79 + 0xb bytes   C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.InterpretAndCheckYield(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Linq.Expressions.Expression target = {System.Linq.Expressions.Block2}, out object res = true) Line 86 + 0x11 bytes     C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.InterpretConditionalExpression(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Linq.Expressions.Expression expr = {System.Linq.Expressions.FullConditionalExpression}) Line 113 + 0x22 bytes        C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.Interpret(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Linq.Expressions.Expression expr = {System.Linq.Expressions.FullConditionalExpression}) Line 40 + 0xb bytes            C#
                 Microsoft.Scripting.dll!Microsoft.Scripting.Interpretation.Interpreter.InterpretMetaAction(Microsoft.Scripting.Interpretation.InterpreterState state = {Microsoft.Scripting.Interpretation.InterpreterState}, System.Dynamic.DynamicMetaObjectBinder action = {IronRuby.Runtime.Calls.RubyCallAction}, System.Linq.Expressions.DynamicExpression node = {System.Linq.Expressions.DynamicExpression2}, object[] argValues = {object[0x00000002]}) Line 810 + 0x2a bytes           C#

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/ironruby-core/attachments/20081230/53c351a0/attachment.html>


More information about the Ironruby-core mailing list