我知道Parrot是一个虚拟机,但我觉得我并没有完全理解它背后的想法.
据我所知,它是一个虚拟机,可以处理多种语言.它是否正确?
使用虚拟机而不仅仅是解释器有什么好处?
Parrot做的具体是什么让它变得如此重要?
我有一个计算成本高昂的多线程C#应用程序,在运行30-90分钟后似乎一直崩溃.它给出的错误是
运行时遇到了致命错误.错误的地址是0xec37ebae,在线程0xbcc上.错误代码是0xc0000005.此错误可能是CLR中的错误,也可能是用户代码的不安全或不可验证部分中的错误.此错误的常见来源包括COM-interop或PInvoke的用户编组错误,这可能会破坏堆栈.
(0xc0000005是访问冲突的错误代码)
我的应用程序不会调用任何本机代码,或使用任何不安全的块,甚至任何非CLS兼容的类型,如uint.实际上,调试器所说的导致崩溃的代码行是
overallLength += distanceTravelled;
Run Code Online (Sandbox Code Playgroud)
两个值都是类型的 double
考虑到这一切,我认为崩溃必定是由于编译器或CLR或JIT中的错误造成的.我想找出导致它的原因,或者至少写一个较小的复制品发送到微软,但我不知道从哪里开始.我从来没有必要查看CIL二进制文件,或编译的JIT输出,或本机堆栈跟踪(崩溃时没有托管堆栈跟踪),所以我不确定如何.我甚至无法弄清楚如何在崩溃时查看所有变量的状态(很遗憾,VS不会告诉我像在托管异常之后那样,并将它们输出到控制台/文件会减慢应用程序1000倍,这显然不是一个选项).
那么,我该如何调试呢?
[编辑]在VS 2010 SP1下编译,运行最新版本的.Net 4.0 Client Profile.显然它是".Net 4.0C/.Net 4.0E,.Net CLR 1.1.4322"
MethodImplAttribute与选项MethodImplOptions.AggressiveInlining和TargetedPatchingOptOut?之间有什么区别?
当我在Google上搜索时,每个人似乎都说(可能)内联方法但没有给出差异.
我用C编写了一个虚拟机,它对非JIT VM有很好的性能,但我想学习一些新东西,并提高性能.我当前的实现只是使用一个开关从VM字节码转换为指令,并将其编译为跳转表.就像我说的那样,它的性能不错,但是我遇到了一个只能用JIT编译器克服的障碍.
不久前我已经问了一个关于自我修改代码的类似问题,但我开始意识到我并没有问正确的问题.
所以我的目标是为这个C虚拟机编写一个JIT编译器,我想在x86汇编中完成它.(我使用NASM作为我的汇编程序)我不太确定如何去做这个.我对汇编感到满意,并且我已经查看了一些自我修改的代码示例,但我还没有弄清楚如何进行代码生成.
到目前为止,我的主要部分是使用我的参数将指令复制到可执行的内存块.我知道我可以在NASM中标记某一行,并使用静态参数从该地址复制整行,但这不是非常动态的,并且不适用于JIT编译器.我需要能够解释字节码中的指令,将其复制到可执行内存,解释第一个参数,将其复制到内存,然后解释第二个参数,并将其复制到内存中.
我已经了解了几个可以简化这项任务的库,比如GNU闪电,甚至是LLVM.但是,在使用外部资源之前,我想首先手动编写,以了解它是如何工作的.
这个社区可以提供任何资源或示例来帮助我开始这项任务吗?一个简单的例子显示了两个或三个指令,例如"add"和"mov"用于生成可执行代码,带有参数,动态地,在内存中,会产生奇迹.
使用SQLHelper类来自动化存储过程调用的方式与XmlRpc.Net库中的方法类似,在运行从IL代码手动生成的方法时遇到了一个非常奇怪的问题.
我把它缩小到一个简单的生成方法(可能它可以简化得更多).我创建了一个新的程序集和类型,包含两个符合的方法
public interface iTestDecimal
{
void TestOk(ref decimal value);
void TestWrong(ref decimal value);
}
Run Code Online (Sandbox Code Playgroud)
测试方法只是将十进制参数加载到堆栈中,装箱,检查它是否为NULL,如果不是,则将其拆箱.
TestOk()方法的生成如下:
static void BuildMethodOk(TypeBuilder tb)
{
/* Create a method builder */
MethodBuilder mthdBldr = tb.DefineMethod( "TestOk", MethodAttributes.Public | MethodAttributes.Virtual,
typeof(void), new Type[] {typeof(decimal).MakeByRefType() });
ParameterBuilder paramBldr = mthdBldr.DefineParameter(1, ParameterAttributes.In | ParameterAttributes.Out, "value");
// generate IL
ILGenerator ilgen = mthdBldr.GetILGenerator();
/* Load argument to stack, and box the decimal value */
ilgen.Emit(OpCodes.Ldarg, 1);
ilgen.Emit(OpCodes.Dup);
ilgen.Emit(OpCodes.Ldobj, typeof(decimal));
ilgen.Emit(OpCodes.Box, typeof(decimal));
/* Some things were …Run Code Online (Sandbox Code Playgroud) 我想知道,为什么Math.sin(double)委托给StrictMath.sin(double)我在Reddit线程中发现问题.提到的代码片段看起来像这样(JDK 7u25):
Math.java:
public static double sin(double a) {
return StrictMath.sin(a); // default impl. delegates to StrictMath
}
Run Code Online (Sandbox Code Playgroud)
StrictMath.java:
public static native double sin(double a);
Run Code Online (Sandbox Code Playgroud)
第二个声明native对我来说是合理的.国家文件Math说:
鼓励代码生成器使用特定于平台的本机库或微处理器指令(如果可用)
问题是:是不是本机库实现了StrictMath足够的平台?JIT比安装的JRE更了解平台(请关注这个案例)?换句话说,为什么不是Math.sin()本地人呢?
标题几乎总结了一下,但我想知道为什么像.net这样的系统每次运行时都会编译代码而不是仅仅在目标机器上编译一次?
以下代码的结果不同如果它在后台启动调试器或没有调试器.如果开启优化,那么差异就在那里.
这是结果:
- >与优化:1000 2008 3016 1001 2009 3007 ...
- >无优化(如预期)1000 1008 1016 1001 1009 1017 ...
码:
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace OptimizerTest
{
public class Test
{
int dummy;
public void TestFunction(int stepWidth)
// stepWidth must be a parameter
{
for (int step = 0; step < stepWidth; step++)
{
dummy = step + 1000;
// addition with constant ( same value as later !)
for (int x = 0; x < 20; x += …Run Code Online (Sandbox Code Playgroud)