diff --git a/src/core/IronPython/Compiler/Ast/PythonNameBinder.cs b/src/core/IronPython/Compiler/Ast/PythonNameBinder.cs index 29b137607..fea56e306 100644 --- a/src/core/IronPython/Compiler/Ast/PythonNameBinder.cs +++ b/src/core/IronPython/Compiler/Ast/PythonNameBinder.cs @@ -565,7 +565,8 @@ public override bool Walk(RaiseStatement node) { // ForEachStatement public override bool Walk(ForStatement node) { node.Parent = _currentScope; - if (_currentScope is FunctionDefinition) { + // generators are invoked for each item so the adaptive compiler picks up the hot ones + if (_currentScope is FunctionDefinition { IsGenerator: false }) { _currentScope.ShouldInterpret = false; } diff --git a/src/core/IronPython/Compiler/LazyCode.cs b/src/core/IronPython/Compiler/LazyCode.cs index 97634c3b3..f0649a52a 100644 --- a/src/core/IronPython/Compiler/LazyCode.cs +++ b/src/core/IronPython/Compiler/LazyCode.cs @@ -4,16 +4,17 @@ using System.Linq.Expressions; +using Microsoft.Scripting.Interpreter; using Microsoft.Scripting.Runtime; namespace IronPython.Compiler { /// /// Represents code which can be lazily compiled. - /// - /// The code is created in an AST which provides the Expression of T and + /// + /// The code is created in an AST which provides the Expression of T and /// whether or not the code should be interpreted. For non-pre compiled /// scenarios the code will not be compiled until the 1st time it is run. - /// + /// /// For pre-compiled scenarios the code is IExpressionSerializable and will /// turn into a normal pre-compiled method. /// @@ -44,7 +45,16 @@ public T EnsureDelegate() { private T Compile() { if (_shouldInterpret) { - return (T)(object)Microsoft.Scripting.Generation.CompilerHelpers.LightCompile(Code, _compilationThreshold); + var result = (System.Delegate)(object)Microsoft.Scripting.Generation.CompilerHelpers.LightCompile(Code, _compilationThreshold); + + // If the adaptive compiler decides to compile this code, we + // want to store the new compiled target. This saves us from going + // through the interpreter stub every call. + if (result.Target is LightLambda lightLambda) { + lightLambda.Compile += (_, e) => Delegate = (T)(object)e.Compiled; + } + + return (T)(object)result; } return Code.Compile();