Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

syncing to head of tfs. Changes IronRuby to version 0.3

  • Loading branch information...
commit cd988456fb3d102da84056e8e150d5376284cc8e 1 parent be5ccb7
Jim Deville jredville authored
Showing with 859 additions and 142 deletions.
  1. +1 −1  Merlin/External/Languages/IronRuby/mspec/rubyspec/core/file/expand_path_spec.rb
  2. +1 −1  Merlin/Main/Config/Signed/App.config
  3. +1 −1  Merlin/Main/Config/Unsigned/App.config
  4. +1 −1  Merlin/Main/Languages/IronPython/IronPython/Compiler/PythonGlobalVariableExpression.cs
  5. +9 −2 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/ScopeOps.cs
  6. +11 −11 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/StringOps.cs
  7. +27 −7 Merlin/Main/Languages/Ruby/IronRuby.Tests/Driver.cs
  8. +1 −1  Merlin/Main/Languages/Ruby/IronRuby.Tests/Helpers.cs
  9. +2 −2 Merlin/Main/Languages/Ruby/IronRuby.Tests/Parser/ParserTests.cs
  10. +4 −3 Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/BacktraceTests.cs
  11. +4 −4 Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/LoaderTests.cs
  12. +1 −1  Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ModuleOps.cs
  13. +3 −3 Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Protocols.cs
  14. +1 −1  Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyClass.cs
  15. +8 −0 Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyModule.cs
  16. +4 −3 Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/BlockDefinition.cs
  17. +1 −2  Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/MethodDeclaration.cs
  18. BIN  Merlin/Main/Languages/Ruby/Ruby/Ruby.Build.csproj
  19. +4 −0 Merlin/Main/Languages/Ruby/Ruby/Ruby.csproj
  20. +10 −8 Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/BlockDispatcher.cs
  21. +0 −8 Merlin/Main/Languages/Ruby/Ruby/Runtime/Loader.cs
  22. +13 −7 Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyContext.cs
  23. +15 −1 Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs
  24. +65 −0 Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyMethodDebugInfo.cs
  25. +94 −0 Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyScriptCode.cs
  26. +1 −1  Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs
  27. +2 −2 Merlin/Main/Languages/Ruby/Utils/IronRuby.Libraries.Scanner/Program.cs
  28. +22 −4 Merlin/Main/Runtime/Microsoft.Scripting/Generation/CompilerHelpers.cs
  29. +1 −1  Merlin/Main/Runtime/Microsoft.Scripting/Runtime/LanguageContext.cs
  30. +39 −11 ndp/fx/src/Core/Microsoft/Scripting/Ast/LambdaExpression.cs
  31. +2 −10 ndp/fx/src/Core/Microsoft/Scripting/Compiler/AnalyzedTree.cs
  32. +4 −4 ndp/fx/src/Core/Microsoft/Scripting/Compiler/CompilerScope.Storage.cs
  33. +56 −0 ndp/fx/src/Core/Microsoft/Scripting/Compiler/DebugInfoGenerator.cs
  34. +2 −0  ndp/fx/src/Core/Microsoft/Scripting/Compiler/ILGen.cs
  35. +2 −0  ndp/fx/src/Core/Microsoft/Scripting/Compiler/LabelInfo.cs
  36. +3 −17 ndp/fx/src/Core/Microsoft/Scripting/Compiler/LambdaCompiler.Expressions.cs
  37. +1 −1  ndp/fx/src/Core/Microsoft/Scripting/Compiler/LambdaCompiler.Lambda.cs
  38. +1 −1  ndp/fx/src/Core/Microsoft/Scripting/Compiler/LambdaCompiler.Statements.cs
  39. +21 −13 ndp/fx/src/Core/Microsoft/Scripting/Compiler/LambdaCompiler.cs
  40. +357 −0 ndp/fx/src/Core/Microsoft/Scripting/Compiler/OffsetTrackingILGenerator.cs
  41. +61 −0 ndp/fx/src/Core/Microsoft/Scripting/Compiler/SymbolDocumentGenerator.cs
  42. +3 −0  ndp/fx/src/Core/Microsoft/Scripting/Microsoft.Scripting.Core.csproj
  43. +0 −9 ndp/fx/src/Core/Microsoft/Scripting/Utils/ExceptionFactory.Generated.cs
2  Merlin/External/Languages/IronRuby/mspec/rubyspec/core/file/expand_path_spec.rb
View
@@ -40,7 +40,7 @@
end
# FIXME: do not use conditionals like this around #it blocks
- unless not home = ENV['HOME']
+ unless not home = ENV['HOME'].tr('\\', '/')
it "converts a pathname to an absolute pathname, using ~ (home) as base" do
File.expand_path('~').should == home
File.expand_path('~', '/tmp/gumby/ddd').should == home
2  Merlin/Main/Config/Signed/App.config
View
@@ -7,7 +7,7 @@
<microsoft.scripting>
<languages>
<language names="IronPython;Python;py" extensions=".py" displayName="IronPython 2.6 Alpha" type="IronPython.Runtime.PythonContext, IronPython, Version=2.6.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
- <language names="IronRuby;Ruby;rb" extensions=".rb" displayName="IronRuby 1.0 Alpha" type="IronRuby.Runtime.RubyContext, IronRuby, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+ <language names="IronRuby;Ruby;rb" extensions=".rb" displayName="IronRuby 0.3" type="IronRuby.Runtime.RubyContext, IronRuby, Version=0.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<language names="ToyScript;ts" extensions=".ts" type="ToyScript.ToyLanguageContext, ToyScript, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</languages>
2  Merlin/Main/Config/Unsigned/App.config
View
@@ -7,7 +7,7 @@
<microsoft.scripting>
<languages>
<language names="IronPython;Python;py" extensions=".py" displayName="IronPython 2.6 Alpha" type="IronPython.Runtime.PythonContext, IronPython, Version=2.6.0.1, Culture=neutral, PublicKeyToken=null" />
- <language names="IronRuby;Ruby;rb" extensions=".rb" displayName="IronRuby 1.0 Alpha" type="IronRuby.Runtime.RubyContext, IronRuby, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
+ <language names="IronRuby;Ruby;rb" extensions=".rb" displayName="IronRuby 0.3" type="IronRuby.Runtime.RubyContext, IronRuby, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null" />
<language names="ToyScript;ts" extensions=".ts" type="ToyScript.ToyLanguageContext, ToyScript, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</languages>
2  Merlin/Main/Languages/IronPython/IronPython/Compiler/PythonGlobalVariableExpression.cs
View
@@ -267,7 +267,7 @@ class LookupGlobalInstruction : Instruction {
_name = SymbolTable.StringToId(name);
_isLocal = isLocal;
}
-
+ public override int ConsumedStack { get { return 1; } }
public override int ProducedStack { get { return 1; } }
public override int Run(StackFrame frame) {
if (_isLocal) {
11 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/ScopeOps.cs
View
@@ -59,14 +59,21 @@ public static class ScopeOps {
}
}
- public static object __getattribute__(Scope/*!*/ self, string name) {
+ public static object __getattribute__(CodeContext/*!*/ context, Scope/*!*/ self, string name) {
+ switch (name) {
+ // never look in the dict for these...
+ case "__dict__": return Get__dict__(self);
+ case "__class__": return DynamicHelpers.GetPythonType(self);
+ }
+
SymbolId si = SymbolTable.StringToId(name);
object res;
if (self.TryGetName(si, out res)) {
return res;
}
- throw PythonOps.AttributeErrorForMissingAttribute("module", si);
+ // fall back to object to provide all of our other attributes (e.g. __setattr__, etc...)
+ return ObjectOps.__getattribute__(context, self, name);
}
public static void __setattr__(Scope/*!*/ self, string name, object value) {
22 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/StringOps.cs
View
@@ -179,7 +179,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return FastNew(context, @object);
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -197,7 +197,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return FastNew(context, @object);
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -206,7 +206,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return CheckAsciiString(context, ScriptingRuntimeHelpers.CharToString(@object));
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -215,7 +215,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return @object.ToString();
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -224,7 +224,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return FastNew(context, @object);
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -233,7 +233,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return @object.ToString();
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -242,7 +242,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return @object.ToString();
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -251,7 +251,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return DoubleOps.__str__(context, @object);
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -260,7 +260,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return FastNew(context, @object);
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -269,7 +269,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return SingleOps.__str__(context, @object);
} else {
- return cls.CreateInstance(context, @object);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, @object));
}
}
@@ -285,7 +285,7 @@ public static class StringOps {
if (cls == TypeCache.String) {
return decode(context, str, encoding ?? PythonContext.GetContext(context).GetDefaultEncodingName(), errors);
} else {
- return cls.CreateInstance(context, str, encoding, errors);
+ return cls.CreateInstance(context, __new__(context, TypeCache.String, str, encoding, errors));
}
}
34 Merlin/Main/Languages/Ruby/IronRuby.Tests/Driver.cs
View
@@ -59,7 +59,7 @@ public class TestRuntime {
_driver = driver;
_testName = testCase.Name;
- if (_driver.IsDebug) {
+ if (_driver.SaveToAssemblies) {
Environment.SetEnvironmentVariable("DLR_AssembliesFileName", _testName);
}
@@ -72,8 +72,7 @@ public class TestRuntime {
}
}
- // TODO: dynamic modules with symbols are not available in partial trust
- runtimeSetup.DebugMode = !driver.PartialTrust;
+ runtimeSetup.DebugMode = _driver.IsDebug;
languageSetup.Options["InterpretedMode"] = _driver.Interpret;
languageSetup.Options["Verbosity"] = 2;
languageSetup.Options["Compatibility"] = testCase.Compatibility;
@@ -94,6 +93,7 @@ public class Driver {
private TestRuntime _testRuntime;
private static bool _excludeSelectedCases;
private static bool _isDebug;
+ private static bool _saveToAssemblies;
private static bool _runTokenizerDriver;
private static bool _displayList;
private static bool _partialTrust;
@@ -116,6 +116,10 @@ public class Driver {
get { return _isDebug; }
}
+ public bool SaveToAssemblies {
+ get { return _saveToAssemblies; }
+ }
+
public bool PartialTrust {
get { return _partialTrust; }
}
@@ -132,8 +136,10 @@ public class Driver {
if (args.Contains("/help") || args.Contains("-?") || args.Contains("/?") || args.Contains("-help")) {
Console.WriteLine("Partial trust : /partial");
Console.WriteLine("Interpret : /interpret");
+ Console.WriteLine("Save to assemblies : /save");
+ Console.WriteLine("Debug Mode : /debug");
Console.WriteLine("Disable Python interop tests : /py-");
- Console.WriteLine("Run Specific Tests : [/debug] [/exclude] [test_to_run ...]");
+ Console.WriteLine("Run Specific Tests : [/exclude] [test_to_run ...]");
Console.WriteLine("List Tests : /list");
Console.WriteLine("Tokenizer baseline : /tokenizer <target-dir> <sources-file>");
Console.WriteLine("Productions dump : /tokenizer /prod <target-dir> <sources-file>");
@@ -150,6 +156,11 @@ public class Driver {
_isDebug = true;
}
+ if (args.Contains("/save")) {
+ args.Remove("/save");
+ _saveToAssemblies = true;
+ }
+
if (args.Contains("/partial")) {
args.Remove("/partial");
_partialTrust = true;
@@ -278,7 +289,7 @@ public sealed class Loader : MarshalByRefObject {
}
private static void InitializeDomain() {
- if (_isDebug) {
+ if (_saveToAssemblies) {
string _dumpDir = Path.Combine(Path.GetTempPath(), "RubyTests");
if (Directory.Exists(_dumpDir)) {
@@ -374,7 +385,11 @@ public sealed class Loader : MarshalByRefObject {
failedCases.Add(test);
Console.Error.WriteLine();
- WriteError("{0}) {1} {2} : {3}", failedCases.Count, test, frame.GetFileName(), frame.GetFileLineNumber());
+ if (_partialTrust) {
+ WriteError("{0}) {1}", failedCases.Count, test);
+ } else {
+ WriteError("{0}) {1} {2} : {3}", failedCases.Count, test, frame.GetFileName(), frame.GetFileLineNumber());
+ }
Console.Error.WriteLine(message);
}
}
@@ -397,7 +412,12 @@ public sealed class Loader : MarshalByRefObject {
Console.ForegroundColor = ConsoleColor.Gray;
} else {
Console.WriteLine();
- Console.Write("Repro: {0}", Environment.CommandLine);
+ // TODO:
+ if (!_partialTrust) {
+ Console.Write("Repro: {0}", Environment.CommandLine);
+ } else {
+ Console.Write("Repro: IronRuby.Tests.exe /partial");
+ }
if (largs.Count == 0) {
Console.Write(" {0}", String.Join(" ", failedCases.ToArray()));
}
2  Merlin/Main/Languages/Ruby/IronRuby.Tests/Helpers.cs
View
@@ -113,7 +113,7 @@ public partial class Tests {
string name = _driver.TestRuntime.TestName;
- if (_driver.IsDebug) {
+ if (_driver.SaveToAssemblies) {
string path = Path.Combine(Snippets.Shared.SnippetsDirectory, name + ".rb");
Directory.CreateDirectory(Snippets.Shared.SnippetsDirectory);
File.WriteAllText(path, code);
4 Merlin/Main/Languages/Ruby/IronRuby.Tests/Parser/ParserTests.cs
View
@@ -890,8 +890,8 @@ p __ENCODING__
const int Id = 0x12345678;
- var lambda = CallSiteTracer.Transform<DlrMainCallTarget>(ast, sourceUnit, options, Id);
- var code = new LegacyScriptCode(lambda, sourceUnit);
+ var lambda = CallSiteTracer.Transform<Func<Scope, LanguageContext, object>>(ast, sourceUnit, options, Id);
+ var code = new RubyScriptCode(lambda, sourceUnit);
var locations = new List<int>();
CallSiteTracer.Register((context, args, result, id, location) => {
7 Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/BacktraceTests.cs
View
@@ -15,10 +15,11 @@
using Microsoft.Scripting;
using System;
+
namespace IronRuby.Tests {
public partial class Tests {
private bool PreciseTraces {
- get { return !_driver.PartialTrust || _driver.Interpret; }
+ get { return Runtime.Setup.DebugMode || _driver.Interpret; }
}
public void Backtrace1() {
@@ -171,13 +172,13 @@ def foo
}, PreciseTraces ? @"
Backtrace4.rb:7:in `baz'
Backtrace4.rb:11:in `foo'
-*.cs:*:in `Bar'
+*:*:in `Bar'
Backtrace4.rb:11:in `foo'
Backtrace4.rb:14
" : @"
Backtrace4.rb:6:in `baz'
Backtrace4.rb:11:in `foo'
-:0:in `Bar'
+*:*:in `Bar'
Backtrace4.rb:10:in `foo'
Backtrace4.rb:0
", OutputFlags.Match);
8 Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/LoaderTests.cs
View
@@ -41,14 +41,14 @@ public partial class Tests {
b = Loader.TryParseAssemblyName(str, out type, out assembly);
Assert(b == false);
- str = "IronRuby.Runtime.RubyContext, IronRuby, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
+ str = "IronRuby.Runtime.RubyContext, IronRuby, Version=0.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
b = Loader.TryParseAssemblyName(str, out type, out assembly);
Assert(b == true &&
- assembly == "IronRuby, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" &&
+ assembly == "IronRuby, Version=0.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" &&
type == "IronRuby.Runtime.RubyContext"
);
- str = "IronRuby, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
+ str = "IronRuby, Version=0.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
b = Loader.TryParseAssemblyName(str, out type, out assembly);
Assert(b == true && assembly == str && type == null);
@@ -56,7 +56,7 @@ public partial class Tests {
b = Loader.TryParseAssemblyName(str, out type, out assembly);
Assert(b == true && assembly == str && type == null);
- str = "IronRuby, Version=1.0.0.0";
+ str = "IronRuby, Version=0.3.0.0";
b = Loader.TryParseAssemblyName(str, out type, out assembly);
Assert(b == true && assembly == str && type == null);
}
2  Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ModuleOps.cs
View
@@ -324,7 +324,7 @@ public static class ModuleOps {
);
}
- self.SetDefinedMethodNoEventNoLock(self.Context, methodName, info, attributesScope.Visibility);
+ self.SetDefinedMethodNoEventNoLock(self.Context, methodName, info, visibility);
}
self.Context.MethodAdded(self, methodName);
6 Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Protocols.cs
View
@@ -395,9 +395,9 @@ public static class Protocols {
return tt.Type;
}
- RubyClass rc = value as RubyClass;
- if (rc != null) {
- return rc.GetUnderlyingSystemType();
+ RubyModule module = value as RubyModule;
+ if (module != null) {
+ return module.GetUnderlyingSystemType();
}
throw RubyExceptions.InvalidValueForType(context, value, "Class");
2  Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyClass.cs
View
@@ -166,7 +166,7 @@ public sealed partial class RubyClass : RubyModule, IDuplicable {
}
#endif
- public Type/*!*/ GetUnderlyingSystemType() {
+ public override Type/*!*/ GetUnderlyingSystemType() {
if (_isSingletonClass) {
throw new InvalidOperationException("Singleton class doesn't have underlying system type.");
}
8 Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyModule.cs
View
@@ -108,6 +108,14 @@ private enum MemberTableState {
get { return _tracker != null && _tracker.Type.IsInterface; }
}
+ public virtual Type/*!*/ GetUnderlyingSystemType() {
+ if (IsInterface) {
+ return _tracker.Type;
+ } else {
+ throw new InvalidOperationException();
+ }
+ }
+
public RubyClass/*!*/ SingletonClass {
get {
Debug.Assert(_singletonClass != null);
7 Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/BlockDefinition.cs
View
@@ -173,11 +173,12 @@ public BlockDefinition(LexicalScope definedScope, CompoundLeftValue/*!*/ paramet
gen.CurrentScopeVariable,
gen.CurrentRfcVariable,
gen.CurrentSelfVariable,
- Ast.Lambda(
- BlockDispatcher.GetDelegateType(parameterCount, attributes),
+ BlockDispatcher.CreateLambda(
body,
RubyExceptionData.EncodeMethodName(gen.SourceUnit, gen.CurrentMethod.MethodName, Location),
- new ReadOnlyCollection<MSA.ParameterExpression>(parameters)
+ new ReadOnlyCollection<MSA.ParameterExpression>(parameters),
+ parameterCount,
+ attributes
),
AstUtils.Constant(parameterCount),
AstUtils.Constant(attributes)
3  Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/MethodDeclaration.cs
View
@@ -156,8 +156,7 @@ public partial class MethodDeclaration : DeclarationExpression {
}
bodyWithParamInit[parameters.Length] = body;
- return Ast.Lambda(
- RubyMethodInfo.ParamsArrayDelegateType,
+ return Ast.Lambda<Func<object, Proc, object[], object>>(
Ast.Block(
new ReadOnlyCollection<MSA.ParameterExpression>(parameters),
new ReadOnlyCollection<MSA.Expression>(bodyWithParamInit)
BIN  Merlin/Main/Languages/Ruby/Ruby/Ruby.Build.csproj
View
Binary file not shown
4 Merlin/Main/Languages/Ruby/Ruby/Ruby.csproj
View
@@ -61,6 +61,7 @@
<NoStdLib>true</NoStdLib>
<SilverlightBuild>true</SilverlightBuild>
<SilverlightSdkPath>..\..\..\Utilities\Silverlight\x86ret\</SilverlightSdkPath>
+ <NoWarn>414,219</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Silverlight Release|AnyCPU' ">
<OutputPath>..\..\..\Bin\Silverlight Release\</OutputPath>
@@ -71,6 +72,7 @@
<ErrorReport>prompt</ErrorReport>
<SilverlightBuild>true</SilverlightBuild>
<SilverlightSdkPath>..\..\..\Utilities\Silverlight\x86ret\</SilverlightSdkPath>
+ <NoWarn>414,219</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" Condition=" '$(SilverlightBuild)' != 'true' " />
@@ -309,11 +311,13 @@
<Compile Include="Builtins\RubyModule.cs" />
<Compile Include="Builtins\RubyInputProvider.cs" />
<Compile Include="Runtime\RubyGlobalScope.cs" />
+ <Compile Include="Runtime\RubyMethodDebugInfo.cs" />
<Compile Include="Runtime\RubyOps.cs" />
<Compile Include="Runtime\Calls\RubyMethodInfo.cs" />
<Compile Include="Runtime\RubyContext.cs" />
<Compile Include="Runtime\RubyOptions.cs" />
<Compile Include="Runtime\RubyScope.cs" />
+ <Compile Include="Runtime\RubyScriptCode.cs" />
<Compile Include="Runtime\RubyUtils.cs" />
<Compile Include="Runtime\RuntimeFlowControl.cs" />
<Compile Include="Runtime\RuntimeErrorSink.cs" />
18 Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/BlockDispatcher.cs
View
@@ -22,6 +22,7 @@
using System.Linq.Expressions;
using System.Reflection;
using IronRuby.Builtins;
+using System.Collections.ObjectModel;
namespace IronRuby.Runtime.Calls {
using Ast = System.Linq.Expressions.Expression;
@@ -108,18 +109,19 @@ public abstract class BlockDispatcher {
return new BlockDispatcherUnsplatN((BlockCallTargetUnsplatN)method, parameterCount, attributes);
}
- internal static Type/*!*/ GetDelegateType(int parameterCount, BlockSignatureAttributes attributes) {
+ internal static LambdaExpression/*!*/ CreateLambda(Expression body, string name, ReadOnlyCollection<ParameterExpression> parameters,
+ int parameterCount, BlockSignatureAttributes attributes) {
if ((attributes & BlockSignatureAttributes.HasUnsplatParameter) == 0) {
switch (parameterCount) {
- case 0: return typeof(BlockCallTarget0);
- case 1: return typeof(BlockCallTarget1);
- case 2: return typeof(BlockCallTarget2);
- case 3: return typeof(BlockCallTarget3);
- case 4: return typeof(BlockCallTarget4);
- default: return typeof(BlockCallTargetN);
+ case 0: return Ast.Lambda<BlockCallTarget0>(body, name, parameters);
+ case 1: return Ast.Lambda<BlockCallTarget1>(body, name, parameters);
+ case 2: return Ast.Lambda<BlockCallTarget2>(body, name, parameters);
+ case 3: return Ast.Lambda<BlockCallTarget3>(body, name, parameters);
+ case 4: return Ast.Lambda<BlockCallTarget4>(body, name, parameters);
+ default: return Ast.Lambda<BlockCallTargetN>(body, name, parameters);
}
}
- return typeof(BlockCallTargetUnsplatN);
+ return Ast.Lambda<BlockCallTargetUnsplatN>(body, name, parameters);
}
private static void CopyArgumentsFromSplattee(object[]/*!*/ args, int initializedArgCount, int parameterCount,
8 Merlin/Main/Languages/Ruby/Ruby/Runtime/Loader.cs
View
@@ -81,7 +81,6 @@ private struct CompiledFile {
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
private int _compiledFileCount;
- internal static long _ILGenerationTimeTicks;
internal static long _ScriptCodeGenerationTimeTicks;
/// <summary>
@@ -477,13 +476,6 @@ private class ResolvedFile {
}
internal object CompileAndRun(Scope globalScope, ScriptCode/*!*/ code, bool tryEvaluate) {
- long ts1 = Stopwatch.GetTimestamp();
- if (code is LegacyScriptCode) {
- ((LegacyScriptCode)code).EnsureCompiled();
- }
- long ts2 = Stopwatch.GetTimestamp();
- Interlocked.Add(ref _ILGenerationTimeTicks, ts2 - ts1);
-
return globalScope != null ? code.Run(globalScope) : code.Run();
}
20 Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyContext.cs
View
@@ -48,9 +48,9 @@ public sealed class RubyContext : LanguageContext {
public static readonly string/*!*/ MriReleaseDate = "2008-05-28";
// IronRuby:
- public const string/*!*/ IronRubyVersionString = "1.0.0.0";
- public static readonly Version IronRubyVersion = new Version(1, 0, 0, 0);
- internal const string/*!*/ IronRubyDisplayName = "IronRuby 1.0 Alpha";
+ public const string/*!*/ IronRubyVersionString = "0.3.0.0";
+ public static readonly Version IronRubyVersion = new Version(0, 3, 0, 0);
+ internal const string/*!*/ IronRubyDisplayName = "IronRuby 0.3";
internal const string/*!*/ IronRubyNames = "IronRuby;Ruby;rb";
internal const string/*!*/ IronRubyFileExtensions = ".rb";
@@ -1568,7 +1568,7 @@ public RubyContext(ScriptDomainManager/*!*/ manager, IDictionary<string, object>
}
#endif
- Expression<DlrMainCallTarget> lambda = ParseSourceCode<DlrMainCallTarget>(sourceUnit, (RubyCompilerOptions)options, errorSink);
+ var lambda = ParseSourceCode<Func<Scope, LanguageContext, object>>(sourceUnit, (RubyCompilerOptions)options, errorSink);
if (lambda == null) {
return null;
}
@@ -1576,7 +1576,7 @@ public RubyContext(ScriptDomainManager/*!*/ manager, IDictionary<string, object>
if (Options.InterpretedMode) {
return new InterpretedScriptCode(lambda, sourceUnit);
} else {
- return new LegacyScriptCode(lambda, sourceUnit);
+ return new RubyScriptCode(lambda, sourceUnit);
}
}
@@ -1662,6 +1662,12 @@ public RubyContext(ScriptDomainManager/*!*/ manager, IDictionary<string, object>
return _runtimeErrorSink;
}
+ protected override ScriptCode/*!*/ LoadCompiledCode(Delegate/*!*/ method, string path) {
+ // TODO:
+ SourceUnit su = new SourceUnit(this, NullTextContentProvider.Null, path, SourceCodeKind.File);
+ return new RubyScriptCode((Func<Scope, LanguageContext, object>)method, su);
+ }
+
public void CheckConstantName(string name) {
if (!Tokenizer.IsConstantName(name, _options.Compatibility >= RubyCompatibility.Ruby19 || KCode != null)) {
throw RubyExceptions.CreateNameError(String.Format("`{0}' is not allowed as a constant name", name));
@@ -1818,14 +1824,14 @@ public RubyContext(ScriptDomainManager/*!*/ manager, IDictionary<string, object>
parse: {1}
ast transform: {2}
script code: {3}
- il: {4}
+ il: {4} (TODO)
binding: {5} ({6} calls)
",
_upTime.Elapsed,
new TimeSpan(_ParseTimeTicks),
new TimeSpan(_AstGenerationTimeTicks),
new TimeSpan(Loader._ScriptCodeGenerationTimeTicks),
- new TimeSpan(Loader._ILGenerationTimeTicks),
+ new TimeSpan(), // TODO: new TimeSpan(Loader._ILGenerationTimeTicks),
#if MEASURE
new TimeSpan(MetaAction.BindingTimeTicks),
MetaAction.BindCallCount
16 Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs
View
@@ -227,13 +227,27 @@ public class RubyExceptionData {
methodName = method.Name;
fileName = (hasFileAccessPermission) ? frame.GetFileName() : null;
- line = frame.GetFileLineNumber();
+ var sourceLine = line = frame.GetFileLineNumber();
if (TryParseRubyMethodName(ref methodName, ref fileName, ref line)) {
// Ruby method:
if (methodName == TopLevelMethodName) {
methodName = null;
}
+
+ if (sourceLine == 0) {
+ RubyMethodDebugInfo debugInfo;
+ if (RubyMethodDebugInfo.TryGet(method, out debugInfo)) {
+ var ilOffset = frame.GetILOffset();
+ if (ilOffset >= 0) {
+ var mappedLine = debugInfo.Map(ilOffset);
+ if (mappedLine != 0) {
+ line = mappedLine;
+ }
+ }
+ }
+ }
+
return true;
} else if (method.IsDefined(typeof(RubyStackTraceHiddenAttribute), false)) {
return false;
65 Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyMethodDebugInfo.cs
View
@@ -0,0 +1,65 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection;
+
+namespace IronRuby.Runtime {
+ internal sealed class RubyMethodDebugInfo {
+ private static readonly Dictionary<string, RubyMethodDebugInfo> _Infos = new Dictionary<string, RubyMethodDebugInfo>();
+
+ private readonly List<int>/*!*/ _offsets = new List<int>();
+ private readonly List<int>/*!*/ _lines = new List<int>();
+
+ public static bool TryGet(MethodBase/*!*/ method, out RubyMethodDebugInfo info) {
+ lock (_Infos) {
+ return _Infos.TryGetValue(method.Name, out info);
+ }
+ }
+
+ public static RubyMethodDebugInfo GetOrCreate(string/*!*/ methodName) {
+ lock (_Infos) {
+ RubyMethodDebugInfo info;
+ if (!_Infos.TryGetValue(methodName, out info)) {
+ info = new RubyMethodDebugInfo();
+ _Infos.Add(methodName, info);
+ }
+ return info;
+ }
+ }
+
+ public void AddMapping(int ilOffset, int line) {
+ _offsets.Add(ilOffset);
+ _lines.Add(line);
+ }
+
+ public int Map(int ilOffset) {
+ int index =_offsets.BinarySearch(ilOffset);
+ if (index >= 0) {
+ return _lines[index];
+ }
+ index = ~index;
+ if (index > 0) {
+ return _lines[index - 1];
+ }
+ if (_lines.Count > 0) {
+ return _lines[0];
+ }
+ return 0;
+ }
+ }
+}
94 Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyScriptCode.cs
View
@@ -0,0 +1,94 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using ScriptCodeFunc = System.Func<Microsoft.Scripting.Runtime.Scope, Microsoft.Scripting.Runtime.LanguageContext, object>;
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Scripting;
+using System.Linq.Expressions;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Generation;
+using System.Threading;
+using System.Linq.Expressions.Compiler;
+using System.Reflection;
+using Microsoft.Scripting.Utils;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace IronRuby.Runtime {
+ internal sealed class RubyScriptCode : ScriptCode {
+ private sealed class CustomGenerator : DebugInfoGenerator {
+ public override void MarkSequencePoint(LambdaExpression method, int ilOffset, DebugInfoExpression node) {
+ RubyMethodDebugInfo.GetOrCreate(method.Name).AddMapping(ilOffset, node.StartLine);
+ }
+ }
+
+ private readonly Expression<ScriptCodeFunc> _code;
+ private ScriptCodeFunc _target;
+
+ public RubyScriptCode(Expression<ScriptCodeFunc>/*!*/ code, SourceUnit/*!*/ sourceUnit)
+ : base(sourceUnit) {
+ Assert.NotNull(code);
+ _code = code;
+ }
+
+ internal RubyScriptCode(ScriptCodeFunc/*!*/ target, SourceUnit/*!*/ sourceUnit)
+ : base(sourceUnit) {
+ Assert.NotNull(target);
+ _target = target;
+ }
+
+ private ScriptCodeFunc/*!*/ Target {
+ get {
+ if (_target == null) {
+ var compiledMethod = CompileLambda<ScriptCodeFunc>(_code, SourceUnit.LanguageContext.DomainManager.Configuration.DebugMode);
+ Interlocked.CompareExchange(ref _target, compiledMethod, null);
+ }
+ return _target;
+ }
+ }
+
+ public override object Run() {
+ return Target(CreateScope(), SourceUnit.LanguageContext);
+ }
+
+ public override object Run(Scope/*!*/ scope) {
+ return Target(scope, SourceUnit.LanguageContext);
+ }
+
+ private static bool _HasPdbPermissions = true;
+
+ internal static T/*!*/ CompileLambda<T>(Expression<T>/*!*/ lambda, bool debugMode) {
+ if (debugMode) {
+#if !SILVERLIGHT
+ // try to use PDBs and fallback to CustomGenerator if not allowed to:
+ if (_HasPdbPermissions) {
+ try {
+ return CompilerHelpers.CompileToMethod(lambda, DebugInfoGenerator.CreatePdbGenerator(), true);
+ } catch (SecurityException) {
+ // do not attempt next time in this app-domain:
+ _HasPdbPermissions = false;
+ }
+ }
+#endif
+ return CompilerHelpers.CompileToMethod(lambda, new CustomGenerator(), false);
+ } else {
+ return lambda.Compile();
+ }
+ }
+ }
+}
2  Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs
View
@@ -710,7 +710,7 @@ private class RecursionHandle : IDisposable {
targetScope.RuntimeFlowControl
);
} else {
- return lambda.Compile(source.EmitDebugSymbols)(
+ return RubyScriptCode.CompileLambda(lambda, context.DomainManager.Configuration.DebugMode)(
targetScope,
self,
module,
4 Merlin/Main/Languages/Ruby/Utils/IronRuby.Libraries.Scanner/Program.cs
View
@@ -167,9 +167,9 @@ where t.IsDefined(typeof(RubyModuleAttribute), false)
}
#if SIGNED
- const string RubyAssembly = @"IronRuby.Libraries, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
+ const string RubyAssembly = @"IronRuby.Libraries, Version=0.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
#else
- const string RubyAssembly = @"IronRuby.Libraries, Version=1.0.0.0, Culture=neutral";
+ const string RubyAssembly = @"IronRuby.Libraries, Version=0.3.0.0, Culture=neutral";
#endif
internal static Dictionary<Type, Type> ExtensionModules;
26 Merlin/Main/Runtime/Microsoft.Scripting/Generation/CompilerHelpers.cs
View
@@ -25,6 +25,7 @@
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
using Microsoft.Scripting.Interpreter;
+using System.Linq.Expressions.Compiler;
using AstUtils = Microsoft.Scripting.Ast.Utils;
namespace Microsoft.Scripting.Generation {
@@ -693,6 +694,22 @@ public static class CompilerHelpers {
}
/// <summary>
+ /// Compiles the lambda into a method definition.
+ /// </summary>
+ /// <param name="lambda">the lambda to compile</param>
+ /// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
+ /// <param name="emitDebugSymbols">A parameter that indicates if debugging information should be emitted to a PDB symbol store.</param>
+ public static void CompileToMethod(this LambdaExpression lambda, MethodBuilder method, bool emitDebugSymbols) {
+ if (emitDebugSymbols) {
+ var module = method.Module as ModuleBuilder;
+ ContractUtils.Requires(module != null, "method", "MethodBuilder does not have a valid ModuleBuilder");
+ lambda.CompileToMethod(method, DebugInfoGenerator.CreatePdbGenerator());
+ } else {
+ lambda.CompileToMethod(method);
+ }
+ }
+
+ /// <summary>
/// Compiles the LambdaExpression.
///
/// If the lambda is compiled with emitDebugSymbols, it will be
@@ -706,7 +723,7 @@ public static class CompilerHelpers {
/// <param name="emitDebugSymbols">true to generate a debuggable method, false otherwise</param>
/// <returns>the compiled delegate</returns>
public static T Compile<T>(this Expression<T> lambda, bool emitDebugSymbols) {
- return emitDebugSymbols ? CompileToMethod(lambda, true) : lambda.Compile();
+ return emitDebugSymbols ? CompileToMethod(lambda, DebugInfoGenerator.CreatePdbGenerator(), true) : lambda.Compile();
}
/// <summary>
@@ -717,10 +734,11 @@ public static class CompilerHelpers {
/// have debugging information.
/// </summary>
/// <param name="lambda">the lambda to compile</param>
- /// <param name="emitDebugSymbols">true to generate a debuggable method, false otherwise</param>
+ /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
+ /// <param name="emitDebugSymbols">True if debug symbols (PDBs) are emitted by the <paramref name="debugInfoGenerator"/>.</param>
/// <returns>the compiled delegate</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
- public static T CompileToMethod<T>(Expression<T> lambda, bool emitDebugSymbols) {
+ public static T CompileToMethod<T>(Expression<T> lambda, DebugInfoGenerator debugInfoGenerator, bool emitDebugSymbols) {
var type = Snippets.Shared.DefineType(lambda.Name, typeof(object), false, emitDebugSymbols).TypeBuilder;
var rewriter = new BoundConstantsRewriter(type);
lambda = (Expression<T>)rewriter.Visit(lambda);
@@ -728,7 +746,7 @@ public static class CompilerHelpers {
//Create a unique method name when the lambda doesn't have a name or the name is empty.
string methodName = String.IsNullOrEmpty(lambda.Name) ? GetUniqueMethodName() : lambda.Name;
var method = type.DefineMethod(methodName, CompilerHelpers.PublicStatic);
- lambda.CompileToMethod(method, emitDebugSymbols);
+ lambda.CompileToMethod(method, debugInfoGenerator);
var finished = type.CreateType();
2  Merlin/Main/Runtime/Microsoft.Scripting/Runtime/LanguageContext.cs
View
@@ -147,7 +147,7 @@ public abstract class LanguageContext {
internal protected abstract ScriptCode CompileSourceCode(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink);
internal protected virtual ScriptCode LoadCompiledCode(Delegate method, string path) {
- return LegacyScriptCode.Load((DlrMainCallTarget)method, this, path);
+ throw new NotSupportedException();
}
#endregion
50 ndp/fx/src/Core/Microsoft/Scripting/Ast/LambdaExpression.cs
View
@@ -21,6 +21,7 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
+using System.Runtime.CompilerServices;
namespace System.Linq.Expressions {
/// <summary>
@@ -115,27 +116,44 @@ ReadOnlyCollection<ParameterExpression> parameters
/// </summary>
/// <returns>A delegate containing the compiled version of the lambda.</returns>
public Delegate Compile() {
- return LambdaCompiler.Compile(this);
+ return LambdaCompiler.Compile(this, null);
+ }
+
+ /// <summary>
+ /// Produces a delegate that represents the lambda expression.
+ /// </summary>
+ /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
+ /// <returns>A delegate containing the compiled version of the lambda.</returns>
+ public Delegate Compile(DebugInfoGenerator debugInfoGenerator) {
+ ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator");
+ return LambdaCompiler.Compile(this, debugInfoGenerator);
}
/// <summary>
/// Compiles the lambda into a method definition.
/// </summary>
/// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
- /// <param name="emitDebugSymbols">A parameter that indicates if debugging information should be emitted.</param>
- public void CompileToMethod(MethodBuilder method, bool emitDebugSymbols) {
+ public void CompileToMethod(MethodBuilder method) {
+ CompileToMethodInternal(method, null);
+ }
+
+ /// <summary>
+ /// Compiles the lambda into a method definition and custom debug information.
+ /// </summary>
+ /// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
+ /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
+ public void CompileToMethod(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) {
+ ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator");
+ CompileToMethodInternal(method, debugInfoGenerator);
+ }
+
+ private void CompileToMethodInternal(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) {
ContractUtils.RequiresNotNull(method, "method");
ContractUtils.Requires(method.IsStatic, "method");
-
var type = method.DeclaringType as TypeBuilder;
ContractUtils.Requires(type != null, "method", Strings.MethodBuilderDoesNotHaveTypeBuilder);
-
- if (emitDebugSymbols) {
- var module = method.Module as ModuleBuilder;
- ContractUtils.Requires(module != null, "method", Strings.MethodBuilderDoesNotHaveModuleBuilder);
- }
- LambdaCompiler.Compile(this, method, emitDebugSymbols);
+ LambdaCompiler.Compile(this, method, debugInfoGenerator);
}
internal abstract LambdaExpression Accept(StackSpiller spiller);
@@ -159,7 +177,17 @@ internal Expression(Expression body, string name, bool tailCall, ReadOnlyCollect
/// </summary>
/// <returns>A delegate containing the compiled version of the lambda.</returns>
public new TDelegate Compile() {
- return (TDelegate)(object)LambdaCompiler.Compile(this);
+ return (TDelegate)(object)LambdaCompiler.Compile(this, null);
+ }
+
+ /// <summary>
+ /// Produces a delegate that represents the lambda expression.
+ /// </summary>
+ /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
+ /// <returns>A delegate containing the compiled version of the lambda.</returns>
+ public new TDelegate Compile(DebugInfoGenerator debugInfoGenerator) {
+ ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator");
+ return (TDelegate)(object)LambdaCompiler.Compile(this, debugInfoGenerator);
}
internal override Expression Accept(ExpressionVisitor visitor) {
12 ndp/fx/src/Core/Microsoft/Scripting/Compiler/AnalyzedTree.cs
View
@@ -17,22 +17,14 @@
using System.Collections.Generic;
using System.Diagnostics.SymbolStore;
using System.Dynamic.Utils;
+using System.Runtime.CompilerServices;
namespace System.Linq.Expressions.Compiler {
internal sealed class AnalyzedTree {
internal readonly Dictionary<object, CompilerScope> Scopes = new Dictionary<object, CompilerScope>();
internal readonly Dictionary<LambdaExpression, BoundConstants> Constants = new Dictionary<LambdaExpression, BoundConstants>();
- // Lazy initialized because many trees will not need it
- private Dictionary<SymbolDocumentInfo, ISymbolDocumentWriter> _symbolWriters;
- internal Dictionary<SymbolDocumentInfo, ISymbolDocumentWriter> SymbolWriters {
- get {
- if (_symbolWriters == null) {
- _symbolWriters = new Dictionary<SymbolDocumentInfo, ISymbolDocumentWriter>();
- }
- return _symbolWriters;
- }
- }
+ internal DebugInfoGenerator DebugInfoGenerator { get; set; }
// Created by VariableBinder
internal AnalyzedTree() {
8 ndp/fx/src/Core/Microsoft/Scripting/Compiler/CompilerScope.Storage.cs
View
@@ -46,13 +46,13 @@ private abstract class Storage {
private sealed class LocalStorage : Storage {
private readonly LocalBuilder _local;
- internal LocalStorage(LambdaCompiler compiler, ParameterExpression v)
- : base(compiler, v) {
+ internal LocalStorage(LambdaCompiler compiler, ParameterExpression variable)
+ : base(compiler, variable) {
// ByRef variables are supported. This is used internally by
// the compiler when emitting an inlined lambda invoke, to
// handle ByRef parameters. BlockExpression prevents this
// from being exposed to user created trees.
- _local = compiler.GetNamedLocal(v.IsByRef ? v.Type.MakeByRefType() : v.Type, v.Name);
+ _local = compiler.GetNamedLocal(variable.IsByRef ? variable.Type.MakeByRefType() : variable.Type, variable);
}
internal override void EmitLoad() {
@@ -145,7 +145,7 @@ internal LocalBoxStorage(LambdaCompiler compiler, ParameterExpression variable)
: base(compiler, variable) {
_boxType = typeof(StrongBox<>).MakeGenericType(variable.Type);
_boxValueField = _boxType.GetField("Value");
- _boxLocal = compiler.GetNamedLocal(_boxType, variable.Name);
+ _boxLocal = compiler.GetNamedLocal(_boxType, variable);
}
internal override void EmitLoad() {
56 ndp/fx/src/Core/Microsoft/Scripting/Compiler/DebugInfoGenerator.cs
View
@@ -0,0 +1,56 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, 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 Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection.Emit;
+using System.Diagnostics;
+using System.Diagnostics.SymbolStore;
+using System.Reflection;
+using System.Linq.Expressions;
+
+namespace System.Runtime.CompilerServices {
+ /// <summary>
+ /// Generates debug information for lambdas in an expression tree.
+ /// </summary>
+ public abstract class DebugInfoGenerator {
+ /// <summary>
+ /// Creates PDB symbol generator.
+ /// </summary>
+ /// <returns>PDB symbol generator.</returns>
+ public static DebugInfoGenerator CreatePdbGenerator() {
+ return new SymbolDocumentGenerator();
+ }
+
+ /// <summary>
+ /// Marks a sequence point.
+ /// </summary>
+ /// <param name="method">The lambda being generated.</param>
+ /// <param name="ilOffset">IL offset where to mark the sequence point.</param>
+ /// <param name="sequencePoint">Debug informaton corresponding to the sequence point.</param>
+ public abstract void MarkSequencePoint(LambdaExpression method, int ilOffset, DebugInfoExpression sequencePoint);
+
+ internal virtual void MarkSequencePoint(LambdaExpression method, MethodBase methodBase, ILGenerator ilg, DebugInfoExpression sequencePoint) {
+ MarkSequencePoint(method, ilg.CurrentOffset, sequencePoint);
+ }
+
+ internal virtual void SetLocalName(LocalBuilder localBuilder, string name) {
+ // nop
+ }
+ }
+}
2  ndp/fx/src/Core/Microsoft/Scripting/Compiler/ILGen.cs
View
@@ -13,6 +13,8 @@
*
* ***************************************************************************/
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic.Utils;
2  ndp/fx/src/Core/Microsoft/Scripting/Compiler/LabelInfo.cs
View
@@ -13,6 +13,8 @@
*
* ***************************************************************************/
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic.Utils;
20 ndp/fx/src/Core/Microsoft/Scripting/Compiler/LambdaCompiler.Expressions.cs
View
@@ -724,36 +724,22 @@ internal enum CompilationFlags {
}
private void EmitDebugInfoExpression(Expression expr) {
- if (!_emitDebugSymbols) {
+ if (!EmitDebugSymbols) {
return;
}
var node = (DebugInfoExpression)expr;
- var symbolWriter = GetSymbolWriter(node.Document);
-
if (node.IsClear && _sequencePointCleared) {
// Emitting another clearance after one clearance does not
// have any effect, so we can save it.
return;
}
- _ilg.MarkSequencePoint(symbolWriter, node.StartLine, node.StartColumn, node.EndLine, node.EndColumn);
+
+ _tree.DebugInfoGenerator.MarkSequencePoint(_lambda, _method, _ilg, node);
_ilg.Emit(OpCodes.Nop);
_sequencePointCleared = node.IsClear;
}
- private ISymbolDocumentWriter GetSymbolWriter(SymbolDocumentInfo document) {
- Debug.Assert(_emitDebugSymbols);
-
- ISymbolDocumentWriter result;
- if (!_tree.SymbolWriters.TryGetValue(document, out result)) {
- var module = (ModuleBuilder)_typeBuilder.Module;
- result = module.DefineDocument(document.FileName, document.Language, document.LanguageVendor, SymbolGuids.DocumentType_Text);
- _tree.SymbolWriters.Add(document, result);
- }
-
- return result;
- }
-
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "expr")]
private static void EmitExtensionExpression(Expression expr) {
throw Error.ExtensionNotReduced();
2  ndp/fx/src/Core/Microsoft/Scripting/Compiler/LambdaCompiler.Lambda.cs
View
@@ -113,7 +113,7 @@ partial class LambdaCompiler {
// When the lambda does not have a name or the name is empty, generate a unique name for it.
string name = String.IsNullOrEmpty(lambda.Name) ? GetUniqueMethodName() : lambda.Name;
MethodBuilder mb = _typeBuilder.DefineMethod(name, MethodAttributes.Private | MethodAttributes.Static);
- impl = new LambdaCompiler(_tree, lambda, mb, _emitDebugSymbols);
+ impl = new LambdaCompiler(_tree, lambda, mb);
}
// 2. emit the lambda
2  ndp/fx/src/Core/Microsoft/Scripting/Compiler/LambdaCompiler.Statements.cs
View
@@ -40,7 +40,7 @@ partial class LambdaCompiler {
var e = node.GetExpression(index);
var next = node.GetExpression(index + 1);
- if (_emitDebugSymbols) {
+ if (EmitDebugSymbols) {
// No need to emit a clearance if the next expression in the block is also a
// DebugInfoExprssion.
var debugInfo = e as DebugInfoExpression;
34 ndp/fx/src/Core/Microsoft/Scripting/Compiler/LambdaCompiler.cs
View
@@ -13,6 +13,8 @@
*
* ***************************************************************************/
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
@@ -59,7 +61,7 @@ internal sealed partial class LambdaCompiler {
private readonly bool _hasClosureArgument;
// True if we want to emitting debug symbols
- private readonly bool _emitDebugSymbols;
+ private bool EmitDebugSymbols { get { return _tree.DebugInfoGenerator != null; } }
// Runtime constants bound to the delegate
private readonly BoundConstants _boundConstants;
@@ -88,7 +90,9 @@ internal sealed partial class LambdaCompiler {
_tree = tree;
_lambda = lambda;
_method = method;
- _ilg = method.GetILGenerator();
+
+ _ilg = new OffsetTrackingILGenerator(method.GetILGenerator());
+
_hasClosureArgument = true;
// These are populated by AnalyzeTree/VariableBinder
@@ -101,7 +105,7 @@ internal sealed partial class LambdaCompiler {
/// <summary>
/// Creates a lambda compiler that will compile into the provided Methodbuilder
/// </summary>
- private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method, bool emitDebugSymbols) {
+ private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method) {
_hasClosureArgument = tree.Scopes[lambda].NeedsClosure;
Type[] paramTypes = GetParameterTypes(lambda);
if (_hasClosureArgument) {
@@ -121,8 +125,8 @@ internal sealed partial class LambdaCompiler {
_lambda = lambda;
_typeBuilder = (TypeBuilder)method.DeclaringType;
_method = method;
- _ilg = method.GetILGenerator();
- _emitDebugSymbols = emitDebugSymbols;
+
+ _ilg = new OffsetTrackingILGenerator(method.GetILGenerator());
// These are populated by AnalyzeTree/VariableBinder
_scope = tree.Scopes[lambda];
@@ -141,7 +145,6 @@ internal sealed partial class LambdaCompiler {
_ilg = parent._ilg;
_hasClosureArgument = parent._hasClosureArgument;
_typeBuilder = parent._typeBuilder;
- _emitDebugSymbols = parent._emitDebugSymbols;
_scope = _tree.Scopes[lambda];
_boundConstants = parent._boundConstants;
}
@@ -170,11 +173,14 @@ internal sealed partial class LambdaCompiler {
/// Compiler entry point
/// </summary>
/// <param name="lambda">LambdaExpression to compile.</param>
+ /// <param name="debugInfoGenerator">Debug info generator.</param>
/// <returns>The compiled delegate.</returns>
- internal static Delegate Compile(LambdaExpression lambda) {
+ internal static Delegate Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator) {
// 1. Bind lambda
AnalyzedTree tree = AnalyzeLambda(ref lambda);
+ tree.DebugInfoGenerator = debugInfoGenerator;
+
// 2. Create lambda compiler
LambdaCompiler c = new LambdaCompiler(tree, lambda);
@@ -191,12 +197,14 @@ internal sealed partial class LambdaCompiler {
///
/// (probably shouldn't be modifying parameters/return type...)
/// </summary>
- internal static void Compile(LambdaExpression lambda, MethodBuilder method, bool emitDebugSymbols) {
+ internal static void Compile(LambdaExpression lambda, MethodBuilder method, DebugInfoGenerator debugInfoGenerator) {
// 1. Bind lambda
AnalyzedTree tree = AnalyzeLambda(ref lambda);
+ tree.DebugInfoGenerator = debugInfoGenerator;
+
// 2. Create lambda compiler
- LambdaCompiler c = new LambdaCompiler(tree, lambda, method, emitDebugSymbols);
+ LambdaCompiler c = new LambdaCompiler(tree, lambda, method);
// 3. Emit
c.EmitLambdaBody();
@@ -231,12 +239,12 @@ internal sealed partial class LambdaCompiler {
}
}
- internal LocalBuilder GetNamedLocal(Type type, string name) {
- Debug.Assert(type != null);
+ internal LocalBuilder GetNamedLocal(Type type, ParameterExpression variable) {
+ Debug.Assert(type != null && variable != null);
LocalBuilder lb = _ilg.DeclareLocal(type);
- if (_emitDebugSymbols && name != null) {
- lb.SetLocalSymInfo(name);
+ if (EmitDebugSymbols && variable.Name != null) {
+ _tree.DebugInfoGenerator.SetLocalName(lb, variable.Name);
}
return lb;
}
357 ndp/fx/src/Core/Microsoft/Scripting/Compiler/OffsetTrackingILGenerator.cs
View
@@ -0,0 +1,357 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, 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 Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics.SymbolStore;
+
+namespace System.Linq.Expressions.Compiler {
+ /// <summary>
+ /// Wraps ILGenerator with code that tracks the current IL offset as instructions are emitted into the IL stream.
+ /// We can conditionally compile this for non-Dev10 release only (using #ifdef MICROSOFT_SCRIPTING)
+ /// as soon as Dev10 feature request (http://vstfdevdiv:8080/WorkItemTracking/WorkItem.aspx?artifactMoniker=599427) gets implemented.
+ /// </summary>
+ internal sealed class OffsetTrackingILGenerator {
+ private readonly ILGenerator _ilg;
+ internal int _offset;
+
+ internal int CurrentOffset { get { return _offset; } }
+
+ internal OffsetTrackingILGenerator(ILGenerator ilg) {
+ Debug.Assert(ilg != null);
+ _ilg = ilg;
+ }
+
+ private void AdvanceOffset(OpCode opcode) {
+ _offset += opcode.Size;
+ }
+
+ private void AdvanceOffsetWithLabel(OpCode opcode) {
+ AdvanceOffset(opcode);
+ if (OpCodes.TakesSingleByteArgument(opcode)) {
+ _offset++;
+ } else {
+ _offset += 4;
+ }
+ }
+
+ #region Simple Instructions
+
+ internal void Emit(OpCode opcode) {
+ _ilg.Emit(opcode);
+ AdvanceOffset(opcode);
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, byte arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset++;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, sbyte arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset++;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, int arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, MethodInfo meth) {
+ _ilg.Emit(opcode, meth);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes) {
+ _ilg.EmitCall(opcode, methodInfo, optionalParameterTypes);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, ConstructorInfo con) {
+ _ilg.Emit(opcode, con);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, Type cls) {
+ _ilg.Emit(opcode, cls);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, long arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset += 8;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, float arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, double arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset += 8;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, Label label) {
+ _ilg.Emit(opcode, label);
+ AdvanceOffsetWithLabel(opcode);
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, Label[] labels) {
+ _ilg.Emit(opcode, labels);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ for (int remaining = labels.Length * 4, i = 0; remaining > 0; remaining -= 4, i++) {
+ _offset += 4;
+ }
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, FieldInfo field) {
+ _ilg.Emit(opcode, field);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, String str) {
+ _ilg.Emit(opcode, str);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, LocalBuilder local) {
+ _ilg.Emit(opcode, local);
+ int tempVal = local.LocalIndex;
+ if (opcode.Equals(OpCodes.Ldloc)) {
+ switch (tempVal) {
+ case 0:
+ opcode = OpCodes.Ldloc_0;
+ break;
+ case 1:
+ opcode = OpCodes.Ldloc_1;
+ break;
+ case 2:
+ opcode = OpCodes.Ldloc_2;
+ break;
+ case 3:
+ opcode = OpCodes.Ldloc_3;
+ break;
+ default:
+ if (tempVal <= 255)
+ opcode = OpCodes.Ldloc_S;
+ break;
+ }
+ } else if (opcode.Equals(OpCodes.Stloc)) {
+ switch (tempVal) {
+ case 0:
+ opcode = OpCodes.Stloc_0;
+ break;
+ case 1:
+ opcode = OpCodes.Stloc_1;
+ break;
+ case 2:
+ opcode = OpCodes.Stloc_2;
+ break;
+ case 3:
+ opcode = OpCodes.Stloc_3;
+ break;
+ default:
+ if (tempVal <= 255)
+ opcode = OpCodes.Stloc_S;
+ break;
+ }
+ } else if (opcode.Equals(OpCodes.Ldloca)) {
+ if (tempVal <= 255)
+ opcode = OpCodes.Ldloca_S;
+ }
+
+ AdvanceOffset(opcode);
+
+ if (opcode.OperandType == OperandType.InlineNone)
+ return;
+ else if (!OpCodes.TakesSingleByteArgument(opcode)) {
+ _offset += 2;
+ } else {
+ _offset++;
+ }
+ AssertOffsetMatches();
+ }
+
+ #endregion
+
+ #region Exception Handling
+
+ private enum ExceptionState {
+ Try = 0,
+ Filter = 1,
+ Catch = 2,
+ Finally = 3,
+ Fault = 4,
+ }
+
+ private Stack<ExceptionState> _exceptionState = new Stack<ExceptionState>();
+
+ internal void BeginExceptionBlock() {
+ _ilg.BeginExceptionBlock();
+ _exceptionState.Push(ExceptionState.Try);
+ AssertOffsetMatches();
+ }
+
+ internal void EndExceptionBlock() {
+ _ilg.EndExceptionBlock();
+
+ ExceptionState state = _exceptionState.Pop();
+ if (state == ExceptionState.Catch) {
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ } else if (state == ExceptionState.Finally || state == ExceptionState.Fault) {
+ AdvanceOffset(OpCodes.Endfinally);
+ }
+
+ AssertOffsetMatches();
+ }
+
+ internal void BeginExceptFilterBlock() {
+ _ilg.BeginExceptFilterBlock();
+
+ _exceptionState.Pop();
+ _exceptionState.Push(ExceptionState.Filter);
+
+ AssertOffsetMatches();
+ }
+
+ internal void BeginCatchBlock(Type exceptionType) {
+ _ilg.BeginCatchBlock(exceptionType);
+
+ ExceptionState state = _exceptionState.Pop();
+ if (state == ExceptionState.Filter) {
+ AdvanceOffset(OpCodes.Endfilter);
+ } else {
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ }
+
+ _exceptionState.Push(ExceptionState.Catch);
+
+ AssertOffsetMatches();
+ }
+
+ internal void BeginFaultBlock() {
+ _ilg.BeginFaultBlock();
+
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ _exceptionState.Pop();
+ _exceptionState.Push(ExceptionState.Fault);
+
+ AssertOffsetMatches();
+ }
+
+ internal void BeginFinallyBlock() {
+ _ilg.BeginFinallyBlock();
+
+ ExceptionState state = _exceptionState.Pop();
+ if (state != ExceptionState.Try) {
+ // leave for any preceeding catch clause
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ }
+
+ // leave for try clause
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ _exceptionState.Push(ExceptionState.Finally);
+
+ AssertOffsetMatches();
+ }
+
+ #endregion
+
+ #region Labels and Locals
+
+ internal Label DefineLabel() {
+ return _ilg.DefineLabel();
+ }
+
+ internal void MarkLabel(Label loc) {
+ _ilg.MarkLabel(loc);
+ }
+
+ internal LocalBuilder DeclareLocal(Type localType) {
+ return _ilg.DeclareLocal(localType);
+ }
+
+ internal void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) {
+ _ilg.MarkSequencePoint(document, startLine, startColumn, endLine, endColumn);
+ }
+
+ #endregion
+
+ #region Assertions
+
+#if STRESS_DEBUG
+ private FieldInfo _ilgOffsetField;
+ private bool _checkOffset = true;
+#endif
+
+ [Conditional("STRESS_DEBUG")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
+ private void AssertOffsetMatches() {
+#if STRESS_DEBUG
+ if (!_checkOffset) {
+ return;
+ }
+
+ int m_length = -1;
+ try {
+ if (_ilgOffsetField == null) {
+ _ilgOffsetField = typeof(ILGenerator).GetField("m_length", BindingFlags.NonPublic | BindingFlags.Instance);
+ }
+ m_length = (int)_ilgOffsetField.GetValue(_ilg);
+ } catch (Exception) {
+ _checkOffset = false;
+ }
+
+ if (_checkOffset) {
+ Debug.Assert(m_length == _offset);
+ }
+#endif
+ }
+
+ #endregion
+ }
+
+}
61 ndp/fx/src/Core/Microsoft/Scripting/Compiler/SymbolDocumentGenerator.cs
View
@@ -0,0 +1,61 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, 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 Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.SymbolStore;
+using System.Linq.Expressions;
+using System.Linq.Expressions.Compiler;
+using System.Reflection;
+using System.Reflection.Emit;
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+
+namespace System.Runtime.CompilerServices {
+ /// <summary>
+ /// Generator of PDB debugging information for expression trees.
+ /// </summary>
+ internal sealed class SymbolDocumentGenerator : DebugInfoGenerator {
+ private Dictionary<SymbolDocumentInfo, ISymbolDocumentWriter> _symbolWriters;
+
+ private ISymbolDocumentWriter GetSymbolWriter(MethodBuilder method, SymbolDocumentInfo document) {
+ ISymbolDocumentWriter result;
+ if (_symbolWriters == null) {
+ _symbolWriters = new Dictionary<SymbolDocumentInfo, ISymbolDocumentWriter>();
+ }
+
+ if (!_symbolWriters.TryGetValue(document, out result)) {
+ result = ((ModuleBuilder)method.Module).DefineDocument(document.FileName, document.Language, document.LanguageVendor, SymbolGuids.DocumentType_Text);
+ _symbolWriters.Add(document, result);
+ }
+
+ return result;
+ }
+
+ internal override void MarkSequencePoint(LambdaExpression method, MethodBase methodBase, ILGenerator ilg, DebugInfoExpression sequencePoint) {
+ MethodBuilder builder = methodBase as MethodBuilder;
+ if (builder != null) {
+ ilg.MarkSequencePoint(GetSymbolWriter(builder, sequencePoint.Document), sequencePoint.StartLine, sequencePoint.StartColumn, sequencePoint.EndLine, sequencePoint.EndColumn);
+ }
+ }
+
+ public override void MarkSequencePoint(LambdaExpression method, int ilOffset, DebugInfoExpression sequencePoint) {
+ Debug.Assert(false);
+ }
+
+ internal override void SetLocalName(LocalBuilder localBuilder, string name) {
+ localBuilder.SetLocalSymInfo(name);
+ }
+ }
+}
3  ndp/fx/src/Core/Microsoft/Scripting/Microsoft.Scripting.Core.csproj
View
@@ -149,6 +149,7 @@
<Compile Include="Ast\GotoExpression.cs" />
<Compile Include="Compiler\LabelInfo.cs" />
<Compile Include="Compiler\AnalyzedTree.cs" />
+ <Compile Include="Compiler\OffsetTrackingILGenerator.cs" />
<Compile Include="Compiler\RuntimeVariableList.cs" />
<Compile Include="Actions\UpdateDelegates.Generated.cs" />
<Compile Include="Ast\DynamicExpression.cs" />
@@ -206,11 +207,13 @@
<Compile Include="Compiler\LambdaCompiler.Statements.cs" />
<Compile Include="Compiler\LambdaCompiler.Unary.cs" />
<Compile Include="Compiler\LambdaCompiler.cs" />
+ <Compile Include="Compiler\DebugInfoGenerator.cs" />
<Compile Include="Compiler\Set.cs" />
<Compile Include="Compiler\StackSpiller.Bindings.cs" />
<Compile Include="Compiler\StackSpiller.Generated.cs" />
<Compile Include="Compiler\StackSpiller.Temps.cs" />
<Compile Include="Compiler\StackSpiller.cs" />
+ <Compile Include="Compiler\SymbolDocumentGenerator.cs" />
<Compile Include="Compiler\VariableBinder.cs" />
<Compile Include="Compiler\AssemblyGen.cs" />
<Compile Include="Compiler\ILGen.cs" />
9 ndp/fx/src/Core/Microsoft/Scripting/Utils/ExceptionFactory.Generated.cs
View
@@ -320,15 +320,6 @@ internal static partial class Strings {
}
/// <summary>
- /// A string like "MethodBuilder does not have a valid ModuleBuilder"
- /// </summary>
- internal static string MethodBuilderDoesNotHaveModuleBuilder {
- get {
- return "MethodBuilder does not have a valid ModuleBuilder";
- }
- }
-
- /// <summary>
/// A string like "MethodBuilder does not have a valid TypeBuilder"
/// </summary>
internal static string MethodBuilderDoesNotHaveTypeBuilder {
Please sign in to comment.
Something went wrong with that request. Please try again.