Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/core/IronPython/Runtime/FunctionCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,8 @@ private Delegate CompileLambda(LightLambdaExpression code, EventHandler<LightLam
return result;
}

return code.Compile();
// LightLambdaExpression.Compile() would light-compile it with the default DLR threshold, so compile the reduced lambda instead
return ((LambdaExpression)code.Reduce()).Compile();
}

private Delegate CompileLambda(LambdaExpression code, EventHandler<LightLambdaCompileEventArgs> handler) {
Expand Down
4 changes: 4 additions & 0 deletions tests/IronPython.Tests/Cases/IronPythonCasesManifest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ IsolationLevel=PROCESS # to avoid having a long list of object subtypes
RunCondition=NOT $(IS_MONO) AND NOT $(IS_OSX)
Reason=Memory allocation on Mono may not match MS.NET

[IronPython.test_noadaptivecompilation]
IsolationLevel=PROCESS
Arguments=-X NoAdaptiveCompilation "$(TEST_FILE)" # the test is skipped without the option

[IronPython.test_number]
Timeout=300000 # 5 minute timeout - slow on macOS

Expand Down
58 changes: 58 additions & 0 deletions tests/suite/test_noadaptivecompilation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Licensed to the .NET Foundation under one or more agreements.
# The .NET Foundation licenses this file to you under the Apache 2.0 License.
# See the LICENSE file in the project root for more information.

"""
Test that functions are compiled up front with -X:NoAdaptiveCompilation.
"""

import unittest

from iptest import IronPythonTestCase, is_cli, run_test

if is_cli:
import clr
from System.Reflection import BindingFlags

def is_interpreted(func):
"""Returns whether the function, which must have been called at least once, runs in the interpreter."""
field = clr.GetClrType(type(func.__code__)).GetField('_normalDelegate', BindingFlags.NonPublic | BindingFlags.Instance)
delegate = field.GetValue(func.__code__)
return delegate.Target.GetType().Name == 'LightLambda'

no_adaptive_compilation = clr.GetCurrentRuntime().GetLanguageByName('python').Options.NoAdaptiveCompilation
else:
no_adaptive_compilation = False

def no_loop(n):
return n

def with_for(n):
for i in range(n):
pass

def with_while(n):
i = 0
while i < n:
i += 1

def generator(n):
for i in range(n):
yield i

@unittest.skipUnless(no_adaptive_compilation, 'requires -X NoAdaptiveCompilation')
class NoAdaptiveCompilationTest(IronPythonTestCase):
def test_functions(self):
def nested(n):
return n

class C:
def method(self, n):
return n

calls = [(no_loop, 1), (with_for, 1), (with_while, 1), (generator, 1), (nested, 1), (lambda n: n, 1), (C.method, C(), 1)]
for func, *args in calls:
func(*args) # for a generator, this runs the function that creates the generator object
self.assertFalse(is_interpreted(func), func.__name__)

run_test(__name__)
Loading