-
Notifications
You must be signed in to change notification settings - Fork 10
Generation and handling of bytecode
NOTE: This feature is only available with mruby, not with MRI.
The combination of Crystal macros and mruby leads to the powerful option of converting Ruby scripts to bytecode files and even integrating the generated bytecode into the executable at compiletime.
To manage this, Anyolite implements the Anyolite::Preloader
module. To see how it works, let us assume that you have a script file "scripts/test.rb" in your source directory.
If you want to compile our example script to bytecode during runtime, you can use the following line:
Anyolite::Preloader.transform_script_to_bytecode("scripts/test.rb", "bytecode_test.mrb")
It can then be called using:
Anyolite::RbInterpreter.create do |rb|
rb.load_bytecode_from_file("bytecode_test.mrb")
end
The bytecode file does not need to be generated in this particular runtime. Another possibility is to create an array:
ary = Anyolite::Preloader.transform_script_to_bytecode_array("scripts/test.rb")
# ...
Anyolite::RbInterpreter.create do |rb|
rb.execute_bytecode(ary)
end
Even though compiling bytecode at the beginning of runtime can be extremely useful, it might also be beneficial to compile the bytecode at compiletime, so the Ruby script can be directly integrated into the executable.
This works similar to runtime compilation, but uses the Anyolite::Preloader::AtCompiletime
module:
Anyolite::Preloader::AtCompiletime.transform_script_to_bytecode("scripts/test.rb", "bytecode_test.mrb")
It is then possible to cache the bytecode file into the executable:
Anyolite::Preloader::AtCompiletime.load_bytecode_file("bytecode_test.mrb")
To call the cached bytecode, you need to call the following code:
Anyolite::RbInterpreter.create do |rb|
Anyolite::Preloader.execute_bytecode_from_cache_or_file(rb, "bytecode_test.mrb")
end
This will check the cache for any cached bytecode file with name "bytecode_test.mrb" and execute it. If there is no file with that name in the cache, it will attempt to execute the original file under the given file path.
If required, the whole procedure can be simplified slightly:
Anyolite::Preloader::AtCompiletime.load_bytecode_array_from_file("scripts/test.rb")
# ...
Anyolite::RbInterpreter.create do |rb|
Anyolite::Preloader.execute_bytecode_from_cache_or_file(rb, "scripts/test.rb")
end
Now, the bytecode file will be skipped and the bytecode will be stored directly into the executable. Note that the compiled script will be identified using its original file name here.
Finally, it is also possible to obtain the bytecode at compiletime as a string:
Anyolite::Preloader::AtCompiletime.transform_script_to_bytecode_string("scripts/test.rb")
The bytecode will not be cached and the function will return a string containing the whole bytecode content. It can be used in the following way:
BYTECODE_STRING = Anyolite::Preloader::AtCompiletime.transform_script_to_bytecode_string("scripts/test.rb")
# ...
Anyolite::RbInterpreter.create do |rb|
rb.execute_bytecode(BYTECODE_STRING.bytes)
end
The BYTECODE_STRING
constant is then still determined at compiletime. Note that manipulating any bytecode Array, String or file will most likely result in crashes unless you really know what you are doing.
Beginner topics:
Advanced topics:
Modifications of Anyolite:
Other useful links: