forked from IronLanguages/ironpython3
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRuntimeScriptCode.cs
More file actions
133 lines (112 loc) · 5.05 KB
/
RuntimeScriptCode.cs
File metadata and controls
133 lines (112 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#if FEATURE_CORE_DLR
using MSAst = System.Linq.Expressions;
#else
using MSAst = Microsoft.Scripting.Ast;
#endif
using System;
using System.Diagnostics;
using System.Threading;
using Microsoft.Scripting;
using Microsoft.Scripting.Generation;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
using IronPython.Compiler.Ast;
using IronPython.Runtime;
using IronPython.Runtime.Operations;
namespace IronPython.Compiler {
/// <summary>
/// Represents a script code which can be consumed at runtime as-is. This code has
/// no external dependencies and is closed over its scope.
/// </summary>
class RuntimeScriptCode : RunnableScriptCode {
private readonly CodeContext/*!*/ _optimizedContext;
private Func<FunctionCode, object> _optimizedTarget;
private ScriptCode _unoptimizedCode;
public RuntimeScriptCode(PythonAst/*!*/ ast, CodeContext/*!*/ codeContext)
: base(ast) {
Debug.Assert(codeContext.GlobalScope.GetExtension(codeContext.LanguageContext.ContextId) != null);
Debug.Assert(ast.Type == typeof(MSAst.Expression<Func<FunctionCode, object>>));
_optimizedContext = codeContext;
}
public override object Run() {
return InvokeTarget(CreateScope());
}
public override object Run(Scope scope) {
return InvokeTarget(scope);
}
public override FunctionCode GetFunctionCode(bool register) {
EnsureCompiled();
return EnsureFunctionCode(_optimizedTarget, false, register);
}
private object InvokeTarget(Scope scope) {
if (scope == _optimizedContext.GlobalScope && !_optimizedContext.LanguageContext.EnableTracing) {
EnsureCompiled();
Exception e = PythonOps.SaveCurrentException();
var funcCode = EnsureFunctionCode(_optimizedTarget, false, true);
PushFrame(_optimizedContext, funcCode);
try {
if (Ast.CompilerContext.SourceUnit.Kind == SourceCodeKind.Expression) {
return OptimizedEvalWrapper(funcCode);
}
return _optimizedTarget(funcCode);
} finally {
PythonOps.RestoreCurrentException(e);
PopFrame();
}
}
// if we're running against a different scope or we need tracing then re-compile the code.
if (_unoptimizedCode == null) {
// TODO: Copy instead of mutate
((PythonCompilerOptions)Ast.CompilerContext.Options).Optimized = false;
Interlocked.CompareExchange(
ref _unoptimizedCode,
Ast.MakeLookupCode().ToScriptCode(),
null
);
}
// This is a brand new ScriptCode which also handles all appropriate ScriptCode
// things such as pushing a function code or updating the stack trace for
// exec/eval code. Therefore we don't need to do any of that here.
return _unoptimizedCode.Run(scope);
}
private object OptimizedEvalWrapper(FunctionCode funcCode) {
try {
return _optimizedTarget(funcCode);
} catch (Exception e) {
PythonOps.UpdateStackTrace(e, _optimizedContext, Code, 0);
throw;
}
}
public override Scope/*!*/ CreateScope() {
return _optimizedContext.GlobalScope;
}
private void EnsureCompiled() {
if (_optimizedTarget == null) {
Interlocked.CompareExchange(ref _optimizedTarget, Compile(), null);
}
}
private Func<FunctionCode, object>/*!*/ Compile() {
var pco = (PythonCompilerOptions)Ast.CompilerContext.Options;
var pc = (PythonContext)SourceUnit.LanguageContext;
if (pc.ShouldInterpret(pco, SourceUnit)) {
return ((Microsoft.Scripting.Ast.LightExpression<Func<FunctionCode, object>>)Ast.GetLambda()).Compile(pc.Options.CompilationThreshold);
} else {
return ((Microsoft.Scripting.Ast.LightExpression<Func<FunctionCode, object>>)Ast.GetLambda()).ReduceToLambda().Compile(pc.EmitDebugSymbols(SourceUnit));
}
}
}
}