Writing a scripting engine and some generals

Started by
8 comments, last by a light breeze 7 months, 4 weeks ago

Is there, or has there ever been a scripting system that runs on machine code, and not byte code in a virtual machine. I gather that there are none that have been commercially released; this is probably due to the man hours I assume on such a project. Please someone give me some idea if there has ever been a scripting language translate into machine code.

Advertisement

Did you ever check what happens inside a virtual machine at runtime? There is at least JIT, where I have much doubt that it wouldn't pull tricks wrt runtime machine code generation.

A second point perhaps, what makes a scripting language a scripting language? How is it different from a programming language? I don't think there is much difference, so what subset of languages are you considering?

Also, why do you think switching to machine code is always a good move? Scripting languages are typically not performance critical (they are “glue” and spend no significant amount of cpu time). Even if they would be time critical, a VM can in theory out-perform compiled machine code, since it can tune the code at runtime.

Alberth said:
Did you ever check what happens inside a virtual machine at runtime? There is at least JIT, where I have much doubt that it wouldn't pull tricks wrt runtime machine code generation.

The whole point of a JIT is to translate to machine-code at run-time. So you are right that a JIT for a VM does that, but not one of it's tricks, it's the entire thing.

Alberth said:
Also, why do you think switching to machine code is always a good move? Scripting languages are typically not performance critical (they are “glue” and spend no significant amount of cpu time). Even if they would be time critical, a VM can in theory out-perform compiled machine code, since it can tune the code at runtime.

I'm not 100% sure if OP's actually asking about a JIT, or switching to a statically compiled model before shipping. Where the answer actually is: Many “scripting” languages have JIT-compilers to replace the VM with machine-code. This is almost always benificial - you might not need it if your specific use case only uses that particular language for mundane or minimalistic parts. There are many other use-cases where high-level languages are being used more widely, and where a JIT is absolutely necessary. C# is a language that technically runs on a VM, but the native runtime doesn't even offer an executable VM and instead compiles everything to machine code at runtime. More critically, if you want to make something large with a particular interpreted language and it doesn't have a JIT, you are often screwed. Unreals Blueprints are a prime example - they use a really terrible interpreted backend, with no (working) option to run at machine-code speed. Also, the Rpg-Maker XP used RGSS (based on Ruby), where 90% of the games code was executed that way, and it didn't have a JIT, so anything larger was very hard to get to perform right.

So a JIT is definately a good option for a VM-backed/interpreted language. From my own experience though, the partical benefits of JIT over static compilation (as you mentioned) are not that many - having written my own JIT, I can say that there are certain optimizations that you can do (like placing values that are not static at compile-time, but static when the JIT runs as constants directly in the code; or using smaller CALL operations than a traditional DLL-model can operate on), but they are not massive.

JIT can become pretty complex and complicated, however it can also be very simple. For my own visual programming language, I made a very simple JIT that basically does nothing more than lay out the instructions in machine-code, replacing the need to loop over a byte-array and have all parameters placed directly in the instructions instead of having to be fetched. This did allow for drastically improved speeds, while still having some overhead compared to fully native code (mainly as I still use the VMs stack instead of the native one, let alone registers. Still, this was very little work compared to the original VM-implementation thatI had to do. Just to answer OPs original question whether this costs “many hours”. Yes it does take some time, but little compared to making an entire language in the first place.

How do you define scripting language? I define it as a programming language that does not require a separate compilation step. The moment it compiles to native code is the moment it stops being a scripting language. Therefore a scripting language that compiles to native code is an oxymoron.

There are a lot of programming languages that do compile to native code. Why not use one of them?

a light breeze said:
How do you define scripting language? I define it as a programming language that does not require a separate compilation step. The moment it compiles to native code is the moment it stops being a scripting language. Therefore a scripting language that compiles to native code is an oxymoron.

Why though? What about “separate compilation” do you actually use for that definition? I'm just curious. Are you talking about the long compile-times of statically compiled languages like C++? If so, then thats a fair point, however do note that even many VM-based languages do actually use a form of compilation, even if not to native code directly - this includes one of the primary examples of “scripting languages”, lua (which is compiled to a bytecode-format before executed AFAIK). So if you actually define “scripting language” as “interpreting the text files as it comes", then the amount of languages that actually fulfill that definition are not very many.

Though again, if we are talking about avoiding long (re)compile-times, that is actually a good distinction. Though that isn't actually tied to native compilation, as well. JIT-compilers can be very fast; statically compiled languages like C++ are mainly slow because of the complexity of the language and cumbersome compilation model. In my own case, JITing the whole code based on bytecode only takes of the time that actual generation of the bytecode takes. For the bytecode for a medium sized project, we are talking about maybe 3s on a fast computer, and for the JIT generation its up to 0.5s come to worst.

light breeze I do see what your saying and I have the same viewpoint. I was not even certain if it is considered a scripting language and not a game engine programming language actually.

a light breeze said:
How do you define scripting language? I define it as a programming language that does not require a separate compilation step.

There are **very** few language definitions that define how to build an implementation. For example, while C is typically compiled as a separate step, nowhere in the C programming book it says that an implementation **must** compile to C code in that way. In fact, such software seems to exist: https://stackoverflow.com/questions/584714/is-there-an-interpreter-for-c

So while you may only know about implementations of a language that do a compile step or not, it's not a well-defined distinction, as an implementor of a language can pick any method they like to build an implementation.

This is the same confusion as saying that a language is slow. That is nonsense. Implementations of languages may be ineffective in computing the result, but a language itself has no speed, as it's an interface definition only.

Alberth said:
This is the same confusion as saying that a language is slow. That is nonsense. Implementations of languages may be ineffective in computing the result, but a language itself has no speed, as it's an interface definition only.

With some caveats. Languages do usually have a standard that mandates certain properties, and implementations cannot go willy-nilly unless they want to be incompatible with everything else. For example, the C++-STL has a lot of mandates on the O-complexity of their containers, so you'd have to adhere to those.

Also, certain language-features or concepts lend themselves to (in)efficiencies. A weak-typed languages like JavaScript allows fields to be added to objects at any time; and even reassignment of member-functions. This means that, no matter the implementation, access of fields has to be implemented with some type of hash-table, which is way more heavy than what a strong/statically typed language can achieve (where each field-access is essentially an integer-offset lookup); as well as no function inlining etc… not even a JIT could resolve those issues, as it's hard/impossible to prove in such a language that a certain function will only ever be invoked with an object with a certain layout.

So you are right that the implementation determines the speed of a language to a certain degree, but languages do have characteristics that determine their performance capabilities.

Alberth said:

a light breeze said:
How do you define scripting language? I define it as a programming language that does not require a separate compilation step.

There are **very** few language definitions that define how to build an implementation. For example, while C is typically compiled as a separate step, nowhere in the C programming book it says that an implementation **must** compile to C code in that way. In fact, such software seems to exist: https://stackoverflow.com/questions/584714/is-there-an-interpreter-for-c

While this is true, it doesn't really negate my definition of scripting language. Saying that there exists an interpreter for C is equivalent to saying that C can be used as a scripting language.

This topic is closed to new replies.

Advertisement