Skip to content

Commit

Permalink
Adjust Ruby VM setup for Ruby 3.4
Browse files Browse the repository at this point in the history
  • Loading branch information
johnfairh committed Jan 10, 2025
1 parent 97ebe62 commit 3789efd
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 1 deletion.
22 changes: 22 additions & 0 deletions Sources/RubyGateway/RbVM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,28 @@ final class RbVM : @unchecked Sendable {
try RbError.raise(error: .setup("Has already been done (via C API?) for this process."))
}

// What is going on with init_stack
// --------------------------------
// Line added for Ruby 3.4 because of ruby/ruby:9505 that took it out of `ruby_setup()`.
//
// This stack frame we're in now isn't very interesting except for defining the native thread
// that will become the Ruby "main thread". Here is why it's OK to call this macro:
//
// `RUBY_INIT_STACK` declares a ‘stack’ variable and calls `vm.c:ruby_init_stack()` which
// stores that variable address in `native_main_thread_stack_top`, the only place that is set.
//
// `eval.c:ruby_setup()` -> `vm.c:Init_BareVM()` is the only place that refers to the static
// and passes to `thread.c:ruby_thread_init_stack()` for the current thread, which for platforms
// we care about[1] leads to `thread_pthread.c:native_thread_init_stack()`. We only care about the
// “main thread” use-case at this point and go to`thread_pthread.c:native_thread_init_main_thread_stack()`.
// We only care about `MAINSTACKADDR_AVAILABLE` and so do not use the address to figure the
// stack layout for GC. Then there is a sanity check which is the only place the address is
// used - as long as it is within the stack as reported by pthreads then we are good.
//
// [1] Brief eyeball the win32 version looks OK too.
//
rbg_RUBY_INIT_STACK()

let setup_rc = ruby_setup()
guard setup_rc == 0 else {
try RbError.raise(error: .setup("ruby_setup() failed: \(setup_rc)"))
Expand Down
3 changes: 3 additions & 0 deletions Sources/RubyGatewayHelpers/include/rbg_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
typedef unsigned long VALUE;
typedef VALUE ID;

/// Call `RUBY_INIT_STACK`
void rbg_RUBY_INIT_STACK(void);

/// Safely call `rb_load` and report exception status.
void rbg_load_protect(VALUE fname, int wrap, int * _Nonnull status);

Expand Down
5 changes: 5 additions & 0 deletions Sources/RubyGatewayHelpers/rbg_macros.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,8 @@ long rbg_RSTRING_LEN(VALUE v)
// These become inlines in Ruby 3 that get imported
int rbg_RB_TEST(VALUE v) { return RB_TEST(v); }
int rbg_RB_NIL_P(VALUE v) { return RB_NIL_P(v); }

// See comment on call in RbVM.swift
void rbg_RUBY_INIT_STACK(void) {
RUBY_INIT_STACK;
}
3 changes: 2 additions & 1 deletion Tests/RubyGatewayTests/TestVM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ class TestVM: XCTestCase {
try Ruby.load(filename: Helpers.fixturePath("unloadable.rb"))
XCTFail("Managed to load unloadable file")
} catch RbError.rubyException(let exn) {
XCTAssertTrue(exn.description.contains("SyntaxError:"))
let desc = exn.description
XCTAssertTrue(desc.hasPrefix("SyntaxError:") || desc.hasPrefix("NameError:"))
}
}
}
Expand Down

0 comments on commit 3789efd

Please sign in to comment.