Browse Source

Merge pull request #140 from nuskey8/util/vm-markers

Add: Add project and code to make it easier to check JIT asm
Akeit0 7 months ago
parent
commit
4ce8f598bd

+ 7 - 0
Lua.sln

@@ -24,6 +24,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lua.SourceGenerator", "src\
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp2", "sandbox\ConsoleApp2\ConsoleApp2.csproj", "{474D977A-946F-49F1-9293-F7F78E0F6A01}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JitTest", "sandbox\JitTest\JitTest.csproj", "{BF479E2C-AAF5-4128-B236-EC7D6092E1F8}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -57,6 +59,10 @@ Global
 		{474D977A-946F-49F1-9293-F7F78E0F6A01}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{474D977A-946F-49F1-9293-F7F78E0F6A01}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{474D977A-946F-49F1-9293-F7F78E0F6A01}.Release|Any CPU.Build.0 = Release|Any CPU
+		{BF479E2C-AAF5-4128-B236-EC7D6092E1F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BF479E2C-AAF5-4128-B236-EC7D6092E1F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BF479E2C-AAF5-4128-B236-EC7D6092E1F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BF479E2C-AAF5-4128-B236-EC7D6092E1F8}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(NestedProjects) = preSolution
 		{6E33BFBC-E51F-493E-9AF0-30C1100F5B5D} = {18A64E25-9557-457B-80AE-A6EFE853118D}
@@ -65,5 +71,6 @@ Global
 		{FC157C29-8AAE-49C8-9536-208E3F0698DA} = {33883F28-679F-48AD-8E64-3515C7BDAF5A}
 		{C4BB264C-4D37-4E2D-99FD-4918CE22D7E4} = {18A64E25-9557-457B-80AE-A6EFE853118D}
 		{474D977A-946F-49F1-9293-F7F78E0F6A01} = {33883F28-679F-48AD-8E64-3515C7BDAF5A}
+		{BF479E2C-AAF5-4128-B236-EC7D6092E1F8} = {33883F28-679F-48AD-8E64-3515C7BDAF5A}
 	EndGlobalSection
 EndGlobal

+ 479 - 0
sandbox/ConsoleApp2/.gitignore

@@ -0,0 +1,479 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from `dotnet new gitignore`
+
+# dotenv files
+.env
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.idea
+
+##
+## Visual studio for Mac
+##
+
+
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# Vim temporary swap files
+*.swp

+ 480 - 0
sandbox/JitTest/.gitignore

@@ -0,0 +1,480 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from `dotnet new gitignore`
+
+# dotenv files
+.env
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.idea
+
+##
+## Visual studio for Mac
+##
+
+
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# Vim temporary swap files
+*.swp
+/obj/

+ 20 - 0
sandbox/JitTest/JitTest.csproj

@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <OutputType>Exe</OutputType>
+        <TargetFramework>net9.0</TargetFramework>
+        <LangVersion>13</LangVersion>
+        <ImplicitUsings>enable</ImplicitUsings>
+        <Nullable>enable</Nullable>
+    </PropertyGroup>
+
+    <ItemGroup>
+      <ProjectReference Include="..\..\src\Lua.SourceGenerator\Lua.SourceGenerator.csproj" />
+      <ProjectReference Include="..\..\src\Lua\Lua.csproj" />
+    </ItemGroup>
+
+    <ItemGroup>
+      <PackageReference Include="JitInspect" Version="1.0.2" />
+    </ItemGroup>
+
+</Project>

+ 62 - 0
sandbox/JitTest/Program.cs

@@ -0,0 +1,62 @@
+// See https://aka.ms/new-console-template for more information
+
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using JitInspect;
+using Lua;
+using Lua.Runtime;
+using Lua.Standard;
+
+// dotnet run --configuration Release /p:DefineConstants="CASE_MARKER"
+// to activate the CASE_MARKER
+// JitInspect can be run in Windows and Linux (MacOS is not supported yet)
+var  luaState = LuaState.Create();
+luaState.OpenStandardLibraries();
+{
+   await luaState.DoFileAsync((GetAbsolutePath("db.lua")));
+}
+
+var closure = luaState.Load(File.ReadAllBytes(GetAbsolutePath("test.lua")),"test.lua");
+
+for (int i = 0; i < 1000; i++)
+{
+   await luaState.MainThread.RunAsync(closure);
+   luaState.MainThread.Stack.Clear();
+}
+
+var savePath = GetAbsolutePath("history");
+var thisDir = GetThisDirectoryName();
+var newJIitPath = Path.Join(thisDir, $"jit_{DateTime.Now:yyyy-MM-dd-HH-mm-ss}.txt");
+var lastJitPaths = Directory.GetFiles(thisDir).Where(x=>x.Contains("jit_"));
+if (!Directory.Exists(savePath))
+{
+    Directory.CreateDirectory(savePath);
+}
+if (lastJitPaths.Any())
+{
+    Console.WriteLine("Last:" + File.ReadAllLines(lastJitPaths.First())[^1]);
+    foreach (var jitPath in lastJitPaths)
+    {
+        var last = jitPath;
+        var dest = Path.Join(savePath, Path.GetFileName(jitPath));
+        File.Move(last, dest);
+    }
+    
+}
+var method = typeof(LuaVirtualMachine).GetMethod("MoveNext", BindingFlags.Static | BindingFlags.NonPublic)!;
+using var disassembler = JitDisassembler.Create();
+var nextJitText = disassembler.Disassemble(method);
+File.WriteAllText(newJIitPath, nextJitText);
+Console.WriteLine("New:" + nextJitText.Split("\n")[^1]);
+
+
+static string GetThisDirectoryName([CallerFilePath] string callerFilePath = "")
+{
+    return Path.GetDirectoryName(callerFilePath)!;
+}
+
+static string GetAbsolutePath(string relativePath, [CallerFilePath] string callerFilePath = "")
+{
+    return Path.Join(Path.GetDirectoryName(callerFilePath)!, relativePath);
+}

+ 630 - 0
sandbox/JitTest/db.lua

@@ -0,0 +1,630 @@
+-- testing debug library
+
+debug = require "debug"
+
+local function dostring(s) return assert(load(s))() end
+
+print"testing debug library and debug information"
+
+do
+local a=1
+end
+
+function test (s, l, p)
+  collectgarbage()   -- avoid gc during trace
+  local function f (event, line)
+    assert(event == 'line')
+    local l = table.remove(l, 1)
+    if p then print(l, line) end
+    assert(l == line, "wrong trace!!")
+  end
+  debug.sethook(f,"l"); load(s)(); debug.sethook()
+  assert(#l == 0)
+end
+
+
+do
+  assert(not pcall(debug.getinfo, print, "X"))   -- invalid option
+  assert(debug.getinfo(1000) == nil)   -- out of range level
+  assert(debug.getinfo(-1) == nil)     -- out of range level
+  local a = debug.getinfo(print)
+  assert(a.what == "C#" and a.short_src == "[C#]") -- changed C to C#
+  a = debug.getinfo(print, "L")
+  assert(a.activelines == nil)
+  local b = debug.getinfo(test, "SfL")
+  assert(b.name == nil and b.what == "Lua" and b.linedefined == 13 and
+         b.lastlinedefined == b.linedefined + 10 and
+         b.func == test and not string.find(b.short_src, "%["))
+  assert(b.activelines[b.linedefined + 1] and
+         b.activelines[b.lastlinedefined])
+  assert(not b.activelines[b.linedefined] and
+         not b.activelines[b.lastlinedefined + 1])
+end
+
+
+-- test file and string names truncation
+a = "function f () end"
+local function dostring (s, x) return load(s, x)() end
+dostring(a)
+assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a))
+dostring(a..string.format("; %s\n=1", string.rep('p', 400)))
+assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
+dostring(a..string.format("; %s=1", string.rep('p', 400)))
+assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
+dostring("\n"..a)
+assert(debug.getinfo(f).short_src == '[string "..."]')
+dostring(a, "")
+assert(debug.getinfo(f).short_src == '[string ""]')
+dostring(a, "@xuxu")
+assert(debug.getinfo(f).short_src == "xuxu")
+dostring(a, "@"..string.rep('p', 1000)..'t')
+assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$"))
+dostring(a, "=xuxu")
+assert(debug.getinfo(f).short_src == "xuxu")
+dostring(a, string.format("=%s", string.rep('x', 500)))
+assert(string.find(debug.getinfo(f).short_src, "^x*$"))
+dostring(a, "=")
+assert(debug.getinfo(f).short_src == "")
+a = nil; f = nil;
+
+
+repeat
+  local g = {x = function ()
+    local a = debug.getinfo(2)
+    assert(a.name == 'f' and a.namewhat == 'local')
+    a = debug.getinfo(1)
+    assert(a.name == 'x' and a.namewhat == 'field')
+    return 'xixi'
+  end}
+  local f = function () return 1+1 and (not 1 or g.x()) end
+  assert(f() == 'xixi')
+  g = debug.getinfo(f)
+  assert(g.what == "Lua" and g.func == f and g.namewhat == "" and not g.name)
+
+  function f (x, name)   -- local!
+    name = name or 'f'
+    local a = debug.getinfo(1)
+    assert(a.name == name and a.namewhat == 'local')
+    return x
+  end
+
+  -- breaks in different conditions
+  if 3>4 then break end; f()
+  if 3<4 then a=1 else break end; f()
+  while 1 do local x=10; break end; f()
+  local b = 1
+  if 3>4 then return math.sin(1) end; f()
+  a = 3<4; f()
+  a = 3<4 or 1; f()
+  repeat local x=20; if 4>3 then f() else break end; f() until 1
+  g = {}
+  f(g).x = f(2) and f(10)+f(9)
+  assert(g.x == f(19))
+  function g(x) if not x then return 3 end return (x('a', 'x')) end
+  assert(g(f) == 'a')
+until 1
+
+test([[if
+math.sin(1)
+then
+  a=1
+else
+  a=2
+end
+]], {2,3,4,7})
+
+test([[--
+if nil then
+  a=1
+else
+  a=2
+end
+]], {2,5,6})
+
+test([[a=1
+repeat
+  a=a+1
+until a==3
+]], {1,3,4,3,4})
+
+test([[ do
+  return
+end
+]], {2})
+
+test([[local a
+a=1
+while a<=3 do
+  a=a+1
+end
+]], {1,2,3,4,3,4,3,4,3,5})
+
+test([[while math.sin(1) do
+  if math.sin(1)
+  then break
+  end
+end
+a=1]], {1,2,3,6})
+
+test([[for i=1,3 do
+  a=i
+end
+]], {1,2,1,2,1,2,1,3})
+
+test([[for i,v in pairs{'a','b'} do
+  a=i..v
+end
+]], {1,2,1,2,1,3})
+
+test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
+
+
+
+print'+'
+
+-- invalid levels in [gs]etlocal
+assert(not pcall(debug.getlocal, 20, 1))
+assert(not pcall(debug.setlocal, -1, 1, 10))
+
+
+-- parameter names
+local function foo (a,b,...) local d, e end
+local co = coroutine.create(foo)
+
+assert(debug.getlocal(foo, 1) == 'a')
+assert(debug.getlocal(foo, 2) == 'b')
+assert(debug.getlocal(foo, 3) == nil)
+assert(debug.getlocal(co, foo, 1) == 'a')
+assert(debug.getlocal(co, foo, 2) == 'b')
+assert(debug.getlocal(co, foo, 3) == nil)
+
+assert(debug.getlocal(print, 1) == nil)
+
+
+-- varargs
+local function foo (a, ...)
+  local t = table.pack(...)
+  for i = 1, t.n do
+    local n, v = debug.getlocal(1, -i)
+    assert(n == "(*vararg)" and v == t[i])
+  end
+  assert(not debug.getlocal(1, -(t.n + 1)))
+  assert(not debug.setlocal(1, -(t.n + 1), 30))
+  if t.n > 0 then
+    (function (x)
+      assert(debug.setlocal(2, -1, x) == "(*vararg)")
+      assert(debug.setlocal(2, -t.n, x) == "(*vararg)")
+     end)(430)
+     assert(... == 430)
+  end
+end
+
+foo()
+foo(print)
+foo(200, 3, 4)
+local a = {}
+for i = 1,1000 do a[i] = i end
+foo(table.unpack(a))
+a = nil
+
+-- access to vararg in non-vararg function
+local function foo () return debug.getlocal(1, -1) end
+assert(foo(10) == nil)
+
+
+a = {}; L = nil
+local glob = 1
+local oldglob = glob
+debug.sethook(function (e,l)
+  collectgarbage()   -- force GC during a hook
+  local f, m, c = debug.gethook()
+  assert(m == 'crl' and c == 0)
+  if e == "line" then
+    if glob ~= oldglob then
+      L = l-1   -- get the first line where "glob" has changed
+      oldglob = glob
+    end
+  elseif e == "call" then
+      local f = debug.getinfo(2, "f").func
+      a[f] = 1
+  else assert(e == "return")
+  end
+end, "crl")
+
+
+function f(a,b)
+  collectgarbage()
+  local _, x = debug.getlocal(1, 1)
+  local _, y = debug.getlocal(1, 2)
+  assert(x == a and y == b)
+  assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
+  assert(debug.setlocal(2, 4, "ma��") == "B")
+  x = debug.getinfo(2)
+  assert(x.func == g and x.what == "Lua" and x.name == 'g' and
+         x.nups == 1 and string.find(x.source, "^@.*db%.lua$"))
+  glob = glob+1
+  assert(debug.getinfo(1, "l").currentline == L+1)
+  assert(debug.getinfo(1, "l").currentline == L+2)
+end
+
+function foo()
+  glob = glob+1
+  assert(debug.getinfo(1, "l").currentline == L+1)
+end; foo()  -- set L
+-- check line counting inside strings and empty lines
+
+--_ = 'alo\  -- todo fix compiler bug Lua-CSharp
+--alo' .. [[
+--
+--]]
+--[[
+]]
+assert(debug.getinfo(1, "l").currentline == L+11)  -- check count of lines
+
+
+function g(...)
+  local arg = {...}
+  do local a,b,c; a=math.sin(40); end
+  local feijao
+  local AAAA,B = "xuxu", "mam�o"
+  f(AAAA,B)
+  assert(AAAA == "pera" and B == "ma��")
+  do
+     local B = 13
+     local x,y = debug.getlocal(1,5)
+     assert(x == 'B' and y == 13)
+  end
+end
+
+g()
+
+
+assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
+
+
+-- tests for manipulating non-registered locals (C and Lua temporaries)
+
+local n, v = debug.getlocal(0, 1)
+assert(v == 0 and n == "(*temporary)")
+local n, v = debug.getlocal(0, 2)
+assert(v == 2 and n == "(*temporary)")
+assert(not debug.getlocal(0, 3))
+assert(not debug.getlocal(0, 0))
+
+function f()
+  assert(select(2, debug.getlocal(2,3)) == 1)
+  assert(not debug.getlocal(2,4))
+  debug.setlocal(2, 3, 10)
+  return 20
+end
+
+function g(a,b) return (a+1) + f() end
+
+assert(g(0,0) == 30)
+ 
+
+debug.sethook(nil);
+assert(debug.gethook() == nil)
+
+
+-- testing access to function arguments
+
+X = nil
+a = {}
+function a:f (a, b, ...) local arg = {...}; local c = 13 end
+debug.sethook(function (e)
+  assert(e == "call")
+  dostring("XX = 12")  -- test dostring inside hooks
+  -- testing errors inside hooks
+  assert(not pcall(load("a='joao'+1")))
+  debug.sethook(function (e, l) 
+    assert(debug.getinfo(2, "l").currentline == l)
+    local f,m,c = debug.gethook()
+    assert(e == "line")
+    assert(m == 'l' and c == 0)
+    debug.sethook(nil)  -- hook is called only once
+    assert(not X)       -- check that
+    X = {}; local i = 1
+    local x,y
+    while 1 do
+      x,y = debug.getlocal(2, i)
+      if x==nil then break end
+      X[x] = y
+      i = i+1
+    end
+  end, "l")
+end, "c")
+
+a:f(1,2,3,4,5)
+assert(X.self == a and X.a == 1   and X.b == 2 and X.c == nil)
+assert(XX == 12)
+assert(debug.gethook() == nil)
+
+
+-- testing upvalue access
+local function getupvalues (f)
+  local t = {}
+  local i = 1
+  while true do
+    local name, value = debug.getupvalue(f, i)
+    if not name then break end
+    assert(not t[name])
+    t[name] = value
+    i = i + 1
+  end
+  return t
+end
+
+local a,b,c = 1,2,3
+local function foo1 (a) b = a; return c end
+local function foo2 (x) a = x; return c+b end
+assert(debug.getupvalue(foo1, 3) == nil)
+assert(debug.getupvalue(foo1, 0) == nil)
+assert(debug.setupvalue(foo1, 3, "xuxu") == nil)
+local t = getupvalues(foo1)
+assert(t.a == nil and t.b == 2 and t.c == 3)
+t = getupvalues(foo2)
+assert(t.a == 1 and t.b == 2 and t.c == 3)
+assert(debug.setupvalue(foo1, 1, "xuxu") == "b")
+assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu")
+-- upvalues of C functions are allways "called" "" (the empty string)
+assert(debug.getupvalue(string.gmatch("x", "x"), 1) == "")  
+
+
+-- testing count hooks
+local a=0
+debug.sethook(function (e) a=a+1 end, "", 1)
+a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
+debug.sethook(function (e) a=a+1 end, "", 4)
+a=0; for i=1,1000 do end; assert(250 < a and a < 255)
+local f,m,c = debug.gethook()
+assert(m == "" and c == 4)
+debug.sethook(function (e) a=a+1 end, "", 4000)
+a=0; for i=1,1000 do end; assert(a == 0)
+
+if not _no32 then
+  debug.sethook(print, "", 2^24 - 1)   -- count upperbound
+  local f,m,c = debug.gethook()
+  assert(({debug.gethook()})[3] == 2^24 - 1)
+end
+
+debug.sethook()
+
+
+-- tests for tail calls
+local function f (x)
+  if x then
+    assert(debug.getinfo(1, "S").what == "Lua")
+    assert(debug.getinfo(1, "t").istailcall == true)
+    local tail = debug.getinfo(2)
+    assert(tail.func == g1 and tail.istailcall == true)
+    assert(debug.getinfo(3, "S").what == "main")
+    print"+"
+    end
+end
+
+function g(x) return f(x) end
+
+function g1(x) g(x) end
+
+local function h (x) local f=g1; return f(x) end
+
+h(true)
+
+local b = {}
+debug.sethook(function (e) table.insert(b, e) end, "cr")
+h(false)
+debug.sethook()
+local res = {"return",   -- first return (from sethook)
+  "call", "tail call", "call", "tail call",
+  "return", "return",
+  "call",    -- last call (to sethook)
+}
+for i = 1, #res do assert(res[i] == table.remove(b, 1)) end
+
+b = 0
+debug.sethook(function (e)
+                if e == "tail call" then
+                  b = b + 1
+                  assert(debug.getinfo(2, "t").istailcall == true)
+                else
+                  assert(debug.getinfo(2, "t").istailcall == false)
+                end
+              end, "c")
+h(false)
+debug.sethook()
+assert(b == 2)   -- two tail calls
+
+lim = 30000
+if _soft then limit = 3000 end
+local function foo (x)
+  if x==0 then
+    assert(debug.getinfo(2).what == "main")
+    local info = debug.getinfo(1)
+    assert(info.istailcall == true and info.func == foo)
+  else return foo(x-1)
+  end
+end
+
+foo(lim)
+
+
+print"+"
+
+
+-- testing local function information
+co = load[[
+  local A = function ()
+    return x
+  end
+  return
+]]
+
+local a = 0
+-- 'A' should be visible to debugger only after its complete definition
+debug.sethook(function (e, l)
+  if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == nil)-- assert(debug.getlocal(2, 1) == "(*temporary)") --changed behavior Lua-CSharp
+   elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A")
+  end
+end, "l")
+co()  -- run local function definition
+debug.sethook()  -- turn off hook
+assert(a == 2)   -- ensure all two lines where hooked
+
+-- testing traceback
+
+assert(debug.traceback(print) == print)
+assert(debug.traceback(print, 4) == print)
+assert(string.find(debug.traceback("hi", 4), "^hi\n"))
+assert(string.find(debug.traceback("hi"), "^hi\n"))
+assert(not string.find(debug.traceback("hi"), "'traceback'"))
+assert(string.find(debug.traceback("hi", 0), "'traceback'"))
+assert(string.find(debug.traceback(), "^stack traceback:\n"))
+
+
+-- testing nparams, nups e isvararg
+local t = debug.getinfo(print, "u")
+assert(t.isvararg == true and t.nparams == 0 and t.nups == 0)
+
+t = debug.getinfo(function (a,b,c) end, "u")
+assert(t.isvararg == false and t.nparams == 3 and t.nups == 0)
+
+t = debug.getinfo(function (a,b,...) return t[a] end, "u")
+assert(t.isvararg == true and t.nparams == 2 and t.nups == 1)
+
+t = debug.getinfo(1)   -- main
+assert(t.isvararg == true and t.nparams == 0 and t.nups == 1 and
+       debug.getupvalue(t.func, 1) == "_ENV")
+
+
+-- testing debugging of coroutines
+
+local function checktraceback (co, p, level)
+  local tb = debug.traceback(co, nil, level)
+  local i = 0
+  for l in string.gmatch(tb, "[^\n]+\n?") do
+    assert(i == 0 or string.find(l, p[i]))
+    i = i+1
+  end
+  assert(p[i] == nil)
+end
+
+
+local function f (n)
+  if n > 0 then f(n-1)
+  else coroutine.yield() end
+end
+
+local co = coroutine.create(f)
+coroutine.resume(co, 3)
+checktraceback(co, {"yield", "db.lua", "db.lua", "db.lua", "db.lua"})
+checktraceback(co, {"db.lua", "db.lua", "db.lua", "db.lua"}, 1)
+checktraceback(co, {"db.lua", "db.lua", "db.lua"}, 2)
+checktraceback(co, {"db.lua"}, 4)
+checktraceback(co, {}, 40)
+
+
+co = coroutine.create(function (x)
+       local a = 1
+       coroutine.yield(debug.getinfo(1, "l"))
+       coroutine.yield(debug.getinfo(1, "l").currentline)
+       return a
+     end)
+
+local tr = {}
+local foo = function (e, l) if l then table.insert(tr, l) end end
+debug.sethook(co, foo, "lcr")
+
+local _, l = coroutine.resume(co, 10)
+local x = debug.getinfo(co, 1, "lfLS")
+assert(x.currentline == l.currentline and x.activelines[x.currentline])
+assert(type(x.func) == "function")
+for i=x.linedefined + 1, x.lastlinedefined do
+  assert(x.activelines[i])
+  x.activelines[i] = nil
+end
+assert(next(x.activelines) == nil)   -- no 'extra' elements
+assert(debug.getinfo(co, 2) == nil)
+local a,b = debug.getlocal(co, 1, 1)
+assert(a == "x" and b == 10)
+a,b = debug.getlocal(co, 1, 2)
+assert(a == "a" and b == 1)
+debug.setlocal(co, 1, 2, "hi")
+assert(debug.gethook(co) == foo)
+assert(#tr == 2 and
+       tr[1] == l.currentline-1 and tr[2] == l.currentline)
+
+a,b,c = pcall(coroutine.resume, co)
+assert(a and b and c == l.currentline+1)
+checktraceback(co, {"yield", "in function <"})
+
+a,b = coroutine.resume(co)
+assert(a and b == "hi")
+assert(#tr == 4 and tr[4] == l.currentline+2)
+assert(debug.gethook(co) == foo)
+assert(debug.gethook() == nil)
+checktraceback(co, {})
+
+
+-- check traceback of suspended (or dead with error) coroutines
+
+function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end
+
+co = coroutine.create(function (x) f(x) end)
+a, b = coroutine.resume(co, 3)
+t = {"'yield'", "'f'", "in function <"}
+while coroutine.status(co) == "suspended" do
+  checktraceback(co, t)
+  a, b = coroutine.resume(co)
+  table.insert(t, 2, "'f'")   -- one more recursive call to 'f'
+end
+t[1] = "'error'"
+checktraceback(co, t)
+
+
+-- test acessing line numbers of a coroutine from a resume inside
+-- a C function (this is a known bug in Lua 5.0)
+
+local function g(x)
+    coroutine.yield(x)
+end
+
+local function f (i)
+  debug.sethook(function () end, "l")
+  for j=1,1000 do
+    g(i+j)
+  end
+end
+
+local co = coroutine.wrap(f)
+co(10)
+pcall(co)
+pcall(co)
+
+
+assert(type(debug.getregistry()) == "table")
+
+
+-- test tagmethod information
+local a = {}
+local function f (t)
+  local info = debug.getinfo(1);
+  assert(info.namewhat == "metamethod")
+  a.op = info.name
+  return info.name
+end
+setmetatable(a, {
+  __index = f; __add = f; __div = f; __mod = f; __concat = f; __pow = f;
+  __eq = f; __le = f; __lt = f;
+})
+
+local b = setmetatable({}, getmetatable(a))
+
+assert(a[3] == "index" and a^3 == "pow" and a..a == "concat")
+assert(a/3 == "div" and 3%a == "mod")
+assert (a==b and a.op == "eq")
+assert (a>=b and a.op == "le")
+assert (a>b and a.op == "lt")
+
+
+print"OK"

+ 118 - 0
sandbox/JitTest/test.lua

@@ -0,0 +1,118 @@
+
+local temp = 3 %"4"
+
+sun = {}
+jupiter = {}
+saturn = {}
+uranus = {}
+neptune = {}
+
+local sqrt = math.sqrt
+
+local PI = 3.141592653589793
+local SOLAR_MASS = 4 * PI * PI
+local DAYS_PER_YEAR = 365.24
+sun.x = 0.0
+sun.y = 0.0
+sun.z = 0.0
+sun.vx = 0.0
+sun.vy = 0.0
+sun.vz = 0.0
+sun.mass = SOLAR_MASS
+jupiter.x = 4.84143144246472090e+00
+jupiter.y = -1.16032004402742839e+00
+jupiter.z = -1.03622044471123109e-01
+jupiter.vx = 1.66007664274403694e-03 * DAYS_PER_YEAR
+jupiter.vy = 7.69901118419740425e-03 * DAYS_PER_YEAR
+jupiter.vz = -6.90460016972063023e-05 * DAYS_PER_YEAR
+jupiter.mass = 9.54791938424326609e-04 * SOLAR_MASS
+saturn.x = 8.34336671824457987e+00
+saturn.y = 4.12479856412430479e+00
+saturn.z = -4.03523417114321381e-01
+saturn.vx = -2.76742510726862411e-03 * DAYS_PER_YEAR
+saturn.vy = 4.99852801234917238e-03 * DAYS_PER_YEAR
+saturn.vz = 2.30417297573763929e-05 * DAYS_PER_YEAR
+saturn.mass = 2.85885980666130812e-04 * SOLAR_MASS
+uranus.x = 1.28943695621391310e+01
+uranus.y = -1.51111514016986312e+01
+uranus.z = -2.23307578892655734e-01
+uranus.vx = 2.96460137564761618e-03 * DAYS_PER_YEAR
+uranus.vy = 2.37847173959480950e-03 * DAYS_PER_YEAR
+uranus.vz = -2.96589568540237556e-05 * DAYS_PER_YEAR
+uranus.mass = 4.36624404335156298e-05 * SOLAR_MASS
+neptune.x = 1.53796971148509165e+01
+neptune.y = -2.59193146099879641e+01
+neptune.z = 1.79258772950371181e-01
+neptune.vx = 2.68067772490389322e-03 * DAYS_PER_YEAR
+neptune.vy = 1.62824170038242295e-03 * DAYS_PER_YEAR
+neptune.vz = -9.51592254519715870e-05 * DAYS_PER_YEAR
+neptune.mass = 5.15138902046611451e-05 * SOLAR_MASS
+
+local bodies = { sun, jupiter, saturn, uranus, neptune }
+
+local function advance(bodies, nbody, dt)
+    for i = 1, nbody do
+        local bi = bodies[i]
+        local bix, biy, biz, bimass = bi.x, bi.y, bi.z, bi.mass
+        local bivx, bivy, bivz = bi.vx, bi.vy, bi.vz
+        for j = i + 1, nbody do
+            local bj = bodies[j]
+            local dx, dy, dz = bix - bj.x, biy - bj.y, biz - bj.z
+            local dist2 = dx * dx + dy * dy + dz * dz
+            local mag = sqrt(dist2)
+            mag = dt / (mag * dist2)
+            local bm = bj.mass * mag
+            bivx = bivx - (dx * bm)
+            bivy = bivy - (dy * bm)
+            bivz = bivz - (dz * bm)
+            bm = bimass * mag
+            bj.vx = bj.vx + (dx * bm)
+            bj.vy = bj.vy + (dy * bm)
+            bj.vz = bj.vz + (dz * bm)
+        end
+        bi.vx = bivx
+        bi.vy = bivy
+        bi.vz = bivz
+        bi.x = bix + dt * bivx
+        bi.y = biy + dt * bivy
+        bi.z = biz + dt * bivz
+    end
+end
+
+local function energy(bodies, nbody)
+    local e = 0
+    for i = 1, nbody do
+        local bi = bodies[i]
+        local vx, vy, vz, bim = bi.vx, bi.vy, bi.vz, bi.mass
+        e = e + (0.5 * bim * (vx * vx + vy * vy + vz * vz))
+        for j = i + 1, nbody do
+            local bj = bodies[j]
+            local dx, dy, dz = bi.x - bj.x, bi.y - bj.y, bi.z - bj.z
+            local distance = sqrt(dx * dx + dy * dy + dz * dz)
+            e = e - ((bim * bj.mass) / distance)
+        end
+    end
+    return e
+end
+
+local function offsetMomentum(b, nbody)
+    local px, py, pz = 0, 0, 0
+    for i = 1, nbody do
+        local bi = b[i]
+        local bim = bi.mass
+        px = px + (bi.vx * bim)
+        py = py + (bi.vy * bim)
+        pz = pz + (bi.vz * bim)
+    end
+    b[1].vx = -px / SOLAR_MASS
+    b[1].vy = -py / SOLAR_MASS
+    b[1].vz = -pz / SOLAR_MASS
+end
+
+local N = tonumber(arg and arg[1]) or 1000
+local nbody = #bodies
+
+offsetMomentum(bodies, nbody)
+energy(bodies, nbody)
+for i = 1, N do advance(bodies, nbody, 0.01) end
+energy(bodies, nbody)

+ 3 - 2
src/Lua/Internal/CompilerServices/AsyncMethodBuilderAttribute.cs

@@ -1,10 +1,11 @@
 #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
 #pragma warning disable CS0436
-
+#if !NET5_0_OR_GREATER
 namespace System.Runtime.CompilerServices
 {
     internal sealed class AsyncMethodBuilderAttribute(Type builderType) : Attribute
     {
         public Type BuilderType { get; } = builderType;
     }
-}
+}
+#endif

+ 310 - 0
src/Lua/Runtime/LuaVirtualMachine.Markers.cs

@@ -0,0 +1,310 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using Lua.Internal;
+using System.Diagnostics;
+
+// ReSharper disable InconsistentNaming
+
+namespace Lua.Runtime;
+
+static partial class LuaVirtualMachine
+{
+    static class Markers
+    {
+        static Markers()
+        {
+            InitializeMarkers();
+        }
+
+        /// <summary>
+        /// This method is used to call the marker method once for the JIT decompiler.
+        /// ClrMd, used for the JIT decompiler, cannot identify a method unless that method is called at least once.
+        /// </summary>
+        [Conditional("CASE_MARKER")]
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static void InitializeMarkers()
+        {
+            Move();
+            LoadK();
+            LoadKX();
+            LoadBool();
+            LoadNil();
+            GetUpVal();
+            GetTabUp();
+            GetTable();
+            SetTabUp();
+            SetUpVal();
+            SetTable();
+            NewTable();
+            Self();
+            Add();
+            Sub();
+            Mul();
+            Div();
+            Mod();
+            Pow();
+            Unm();
+            Not();
+            Len();
+            Concat();
+            Jmp();
+            Eq();
+            Lt();
+            Le();
+            Test();
+            TestSet();
+            Call();
+            TailCall();
+            Return();
+            ForLoop();
+            ForPrep();
+            TForCall();
+            TForLoop();
+            SetList();
+            Closure();
+            VarArg();
+            ExtraArg();
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Move()
+        {
+        }
+
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void LoadK()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void LoadKX()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void LoadBool()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void LoadNil()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void GetUpVal()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void GetTabUp()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void GetTable()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void SetTabUp()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void SetUpVal()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void SetTable()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void NewTable()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Self()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Add()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Sub()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Mul()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Div()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Mod()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Pow()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Unm()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Not()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Len()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Concat()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Jmp()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Eq()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Lt()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Le()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Test()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void TestSet()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Call()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void TailCall()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Return()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void ForLoop()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void ForPrep()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void TForCall()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void TForLoop()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void SetList()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void Closure()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void VarArg()
+        {
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        [Conditional("CASE_MARKER")]
+        public static void ExtraArg()
+        {
+        }
+    }
+}

+ 39 - 1
src/Lua/Runtime/LuaVirtualMachine.cs

@@ -340,31 +340,39 @@ public static partial class LuaVirtualMachine
                 switch (opCode)
                 {
                     case OpCode.Move:
+                        Markers.Move();
                         ref var stackHead = ref stack.FastGet(frameBase);
                         Unsafe.Add(ref stackHead, iA) = Unsafe.Add(ref stackHead, instruction.B);
                         stack.NotifyTop(iA + frameBase + 1);
                         continue;
                     case OpCode.LoadK:
+                        Markers.LoadK();
                         stack.GetWithNotifyTop(iA + frameBase) = Unsafe.Add(ref constHead, instruction.Bx);
                         continue;
                     case OpCode.LoadKX:
+                        Markers.LoadKX();
                         stack.GetWithNotifyTop(iA + frameBase) = Unsafe.Add(ref constHead, Unsafe.Add(ref instructionsHead, ++context.Pc).Ax);
                         continue;
                     case OpCode.LoadBool:
+                        Markers.LoadBool();
                         stack.GetWithNotifyTop(iA + frameBase) = instruction.B != 0;
                         if (instruction.C != 0) context.Pc++;
                         continue;
                     case OpCode.LoadNil:
+                        Markers.LoadNil();
                         var ra1 = iA + frameBase + 1;
                         var iB = instruction.B;
                         stack.GetBuffer().Slice(ra1 - 1, iB + 1).Clear();
                         stack.NotifyTop(ra1 + iB);
                         continue;
                     case OpCode.GetUpVal:
+                        Markers.GetUpVal();
                         stack.GetWithNotifyTop(iA + frameBase) = context.LuaClosure.GetUpValue(instruction.B);
                         continue;
                     case OpCode.GetTabUp:
                     case OpCode.GetTable:
+                        Markers.GetTabUp();
+                        Markers.GetTable();
                         stackHead = ref stack.FastGet(frameBase);
                         ref readonly var vc = ref RKC(ref stackHead, ref constHead, instruction);
                         ref readonly var vb = ref (instruction.OpCode == OpCode.GetTable ? ref Unsafe.Add(ref stackHead, instruction.B) : ref context.LuaClosure.GetUpValueRef(instruction.B));
@@ -379,6 +387,8 @@ public static partial class LuaVirtualMachine
                         return true;
                     case OpCode.SetTabUp:
                     case OpCode.SetTable:
+                        Markers.SetTabUp();
+                        Markers.SetTable();
                         stackHead = ref stack.FastGet(frameBase);
                         vb = ref RKB(ref stackHead, ref constHead, instruction);
                         if (vb.TryReadNumber(out var numB))
@@ -411,13 +421,15 @@ public static partial class LuaVirtualMachine
 
                         return true;
                     case OpCode.SetUpVal:
+                        Markers.SetUpVal();
                         context.LuaClosure.SetUpValue(instruction.B, stack.FastGet(iA + frameBase));
                         continue;
                     case OpCode.NewTable:
-
+                        Markers.NewTable();
                         stack.GetWithNotifyTop(iA + frameBase) = new LuaTable(instruction.B, instruction.C);
                         continue;
                     case OpCode.Self:
+                        Markers.Self();
                         stackHead = ref stack.FastGet(frameBase);
                         vc = ref RKC(ref stackHead, ref constHead, instruction);
                         table = Unsafe.Add(ref stackHead, instruction.B);
@@ -439,6 +451,12 @@ public static partial class LuaVirtualMachine
                     case OpCode.Div:
                     case OpCode.Mod:
                     case OpCode.Pow:
+                        Markers.Add();
+                        Markers.Sub();
+                        Markers.Mul();
+                        Markers.Div();
+                        Markers.Mod();
+                        Markers.Pow();
                         stackHead = ref stack.FastGet(frameBase);
                         vb = ref RKB(ref stackHead, ref constHead, instruction);
                         vc = ref RKC(ref stackHead, ref constHead, instruction);
@@ -492,6 +510,7 @@ public static partial class LuaVirtualMachine
 
                         return true;
                     case OpCode.Unm:
+                        Markers.Unm();
                         stackHead = ref stack.FastGet(frameBase);
                         vb = ref Unsafe.Add(ref stackHead, instruction.B);
 
@@ -511,12 +530,14 @@ public static partial class LuaVirtualMachine
 
                         return true;
                     case OpCode.Not:
+                        Markers.Not();
                         stackHead = ref stack.FastGet(frameBase);
                         Unsafe.Add(ref stackHead, iA) = !Unsafe.Add(ref stackHead, instruction.B).ToBoolean();
                         stack.NotifyTop(iA + frameBase + 1);
                         continue;
 
                     case OpCode.Len:
+                        Markers.Len();
                         stackHead = ref stack.FastGet(frameBase);
                         vb = ref Unsafe.Add(ref stackHead, instruction.B);
 
@@ -536,6 +557,7 @@ public static partial class LuaVirtualMachine
 
                         return true;
                     case OpCode.Concat:
+                        Markers.Concat();
                         if (Concat(context))
                         {
                             //if (doRestart) goto Restart;
@@ -544,6 +566,7 @@ public static partial class LuaVirtualMachine
 
                         return true;
                     case OpCode.Jmp:
+                        Markers.Jmp();
                         context.Pc += instruction.SBx;
 
                         if (iA != 0)
@@ -553,6 +576,7 @@ public static partial class LuaVirtualMachine
 
                         continue;
                     case OpCode.Eq:
+                        Markers.Eq();
                         stackHead = ref stack.Get(frameBase);
                         vb = ref RKB(ref stackHead, ref constHead, instruction);
                         vc = ref RKC(ref stackHead, ref constHead, instruction);
@@ -575,6 +599,8 @@ public static partial class LuaVirtualMachine
                         return true;
                     case OpCode.Lt:
                     case OpCode.Le:
+                        Markers.Lt();
+                        Markers.Le();
                         stackHead = ref stack.Get(frameBase);
                         vb = ref RKB(ref stackHead, ref constHead, instruction);
                         vc = ref RKC(ref stackHead, ref constHead, instruction);
@@ -610,6 +636,7 @@ public static partial class LuaVirtualMachine
 
                         return true;
                     case OpCode.Test:
+                        Markers.Test();
                         if (stack.Get(iA + frameBase).ToBoolean() != (instruction.C == 1))
                         {
                             context.Pc++;
@@ -617,6 +644,7 @@ public static partial class LuaVirtualMachine
 
                         continue;
                     case OpCode.TestSet:
+                        Markers.TestSet();
                         vb = ref stack.Get(instruction.B + frameBase);
                         if (vb.ToBoolean() != (instruction.C == 1))
                         {
@@ -630,6 +658,7 @@ public static partial class LuaVirtualMachine
                         continue;
 
                     case OpCode.Call:
+                        Markers.Call();
                         if (Call(context, out doRestart))
                         {
                             if (doRestart)
@@ -642,6 +671,7 @@ public static partial class LuaVirtualMachine
 
                         return true;
                     case OpCode.TailCall:
+                        Markers.TailCall();
                         if (TailCall(context, out doRestart))
                         {
                             if (doRestart) goto Restart;
@@ -651,6 +681,7 @@ public static partial class LuaVirtualMachine
 
                         return true;
                     case OpCode.Return:
+                        Markers.Return();
                         context.State.CloseUpValues(context.Thread, frameBase);
                         if (context.Pop(instruction, frameBase))
                         {
@@ -659,6 +690,7 @@ public static partial class LuaVirtualMachine
 
                         goto End;
                     case OpCode.ForLoop:
+                        Markers.ForLoop();
                         ref var indexRef = ref stack.Get(iA + frameBase);
                         var limit = Unsafe.Add(ref indexRef, 1).UnsafeReadDouble();
                         var step = Unsafe.Add(ref indexRef, 2).UnsafeReadDouble();
@@ -676,6 +708,7 @@ public static partial class LuaVirtualMachine
                         stack.NotifyTop(iA + frameBase + 1);
                         continue;
                     case OpCode.ForPrep:
+                        Markers.ForPrep();
                         indexRef = ref stack.Get(iA + frameBase);
 
                         if (!indexRef.TryReadDouble(out var init))
@@ -701,6 +734,7 @@ public static partial class LuaVirtualMachine
                         context.Pc += instruction.SBx;
                         continue;
                     case OpCode.TForCall:
+                        Markers.TForCall();
                         if (TForCall(context, out doRestart))
                         {
                             if (doRestart) goto Restart;
@@ -709,6 +743,7 @@ public static partial class LuaVirtualMachine
 
                         return true;
                     case OpCode.TForLoop:
+                        Markers.TForLoop();
                         ref var forState = ref stack.Get(iA + frameBase + 1);
 
                         if (forState.Type is not LuaValueType.Nil)
@@ -719,15 +754,18 @@ public static partial class LuaVirtualMachine
 
                         continue;
                     case OpCode.SetList:
+                        Markers.SetList();
                         SetList(context);
                         continue;
                     case OpCode.Closure:
+                        Markers.Closure();
                         ra1 = iA + frameBase + 1;
                         stack.EnsureCapacity(ra1);
                         stack.Get(ra1 - 1) = new LuaClosure(context.Thread, context.Prototype.ChildPrototypes[instruction.Bx]);
                         stack.NotifyTop(ra1);
                         continue;
                     case OpCode.VarArg:
+                        Markers.VarArg();
                         VarArg(context);
 
                         static void VarArg(VirtualMachineExecutionContext context)