introduce IBF_(MAJOR|MINOR)_VERSION.

RubyVM::InstructionSequence.to_binary generates a bytecode binary
representation. To check compatibility with binary and loading
MRI we prepared major/minor version and compare them at loading
time. However, development version of MRI can change this format
but we can not increment minor version to make them consistent
with Ruby's major/minor versions.

To solve this issue, we introduce new minor version scheme
(binary's minor_version = ruby's minor * 10000 + dev ver)
and we can check incompatibility with older dev version.
This commit is contained in:
Koichi Sasada 2019-09-13 16:24:28 +09:00
Родитель 3c162df9d4
Коммит 2da6b328bb
1 изменённых файлов: 13 добавлений и 5 удалений

Просмотреть файл

@ -9184,6 +9184,14 @@ rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func)
typedef unsigned int ibf_offset_t;
#define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr))
#define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
#if RUBY_DEVEL
#define IBF_DEVEL_VERSION 0
#define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
#else
#define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
#endif
struct ibf_header {
char magic[4]; /* YARB */
unsigned int major_version;
@ -10666,8 +10674,8 @@ rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
header.magic[1] = 'A';
header.magic[2] = 'R';
header.magic[3] = 'B';
header.major_version = ISEQ_MAJOR_VERSION;
header.minor_version = ISEQ_MINOR_VERSION;
header.major_version = IBF_MAJOR_VERSION;
header.minor_version = IBF_MINOR_VERSION;
ibf_dump_iseq_list(dump, &header);
ibf_dump_id_list(dump, &header);
ibf_dump_object_list(dump, &header);
@ -10804,10 +10812,10 @@ ibf_load_setup(struct ibf_load *load, VALUE loader_obj, VALUE str)
if (strncmp(load->header->magic, "YARB", 4) != 0) {
rb_raise(rb_eRuntimeError, "unknown binary format");
}
if (load->header->major_version != ISEQ_MAJOR_VERSION ||
load->header->minor_version != ISEQ_MINOR_VERSION) {
if (load->header->major_version != IBF_MAJOR_VERSION ||
load->header->minor_version != IBF_MINOR_VERSION) {
rb_raise(rb_eRuntimeError, "unmatched version file (%u.%u for %u.%u)",
load->header->major_version, load->header->minor_version, ISEQ_MAJOR_VERSION, ISEQ_MINOR_VERSION);
load->header->major_version, load->header->minor_version, IBF_MAJOR_VERSION, IBF_MINOR_VERSION);
}
if (strcmp(load->buff + sizeof(struct ibf_header), RUBY_PLATFORM) != 0) {
rb_raise(rb_eRuntimeError, "unmatched platform");