Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from ruby:master #558

Merged
merged 13 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gc/extconf_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@

append_cflags("-fPIC")

def create_gc_makefile(name)
create_makefile("librubygc.#{name}")
def create_gc_makefile(name, &block)
create_makefile("librubygc.#{name}", &block)
end
18 changes: 18 additions & 0 deletions gc/mmtk/depend
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
$(TARGET_SO): $(MMTK_BUILD)/$(LIBMMTK_RUBY)

# Add the `libmmtk_ruby.a` target to run `cargo build`

release/$(LIBMMTK_RUBY) debug/$(LIBMMTK_RUBY): $(RUSTSRCS) $(srcdir)/Cargo.toml $(srcdir)/Cargo.toml

release/$(LIBMMTK_RUBY):
CARGO_TARGET_DIR="." cargo build --manifest-path=$(srcdir)/Cargo.toml --release

debug/$(LIBMMTK_RUBY):
CARGO_TARGET_DIR="." cargo build --manifest-path=$(srcdir)/Cargo.toml

clean: clean-mmtk

.PHONY: clean-mmtk
clean-mmtk:
-$(Q)$(RM_RF) debug release
-$(Q)$(RM) .rustc_info.json
48 changes: 12 additions & 36 deletions gc/mmtk/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,18 @@
require_relative "../extconf_base"

# Statically link `libmmtk_ruby.a`
$LIBS << " $(MMTK_BUILD)/libmmtk_ruby.#{RbConfig::CONFIG["LIBEXT"]}"
$LIBS << " $(MMTK_BUILD)/$(LIBMMTK_RUBY)"

create_gc_makefile("mmtk")
rustsrcs = Dir.glob("src/*.rs", base: __dir__).map {|s| "$(srcdir)/#{s}"}

makefile = File.read("Makefile")
create_gc_makefile("mmtk") do |makefile|
[
*makefile,

makefile.prepend("MMTK_BUILD=debug\n")

# Add `libmmtk_ruby.a` as an object file
makefile.gsub!(/^OBJS = (.*)$/, "OBJS = \\1 $(MMTK_BUILD)/libmmtk_ruby.#{RbConfig::CONFIG["LIBEXT"]}")

# Modify the `all` target to run the `libmmtk_ruby.a` target first
makefile.gsub!(/^all:\s+(.*)$/, "all: $(MMTK_BUILD)/libmmtk_ruby.#{RbConfig::CONFIG["LIBEXT"]} \\1")

# Add the `libmmtk_ruby.a` target to run `cargo build`
makefile << <<~MAKEFILE
$(MMTK_BUILD)/libmmtk_ruby.#{RbConfig::CONFIG["LIBEXT"]}: $(wildcard $(srcdir)/src/*.rs) $(srcdir)/Cargo.toml $(srcdir)/Cargo.toml
$(Q) case $(MMTK_BUILD) in \
release) \
CARGO_TARGET_DIR="." cargo build --manifest-path=$(srcdir)/Cargo.toml --release \
;; \
debug) \
CARGO_TARGET_DIR="." cargo build --manifest-path=$(srcdir)/Cargo.toml \
;; \
*) \
$(ECHO) Unknown MMTK_BUILD=$(MMTK_BUILD) \
exit 1 \
;; \
esac

clean: clean-mmtk

.PHONY: clean-mmtk
clean-mmtk:
-$(Q)$(RM_RF) debug release
-$(Q)$(RM) .rustc_info.json
MAKEFILE

File.open("Makefile", "w") { |file| file.puts(makefile) }
<<~MAKEFILE,
MMTK_BUILD = debug
LIBMMTK_RUBY = libmmtk_ruby.#$LIBEXT
RUSTSRCS = #{rustsrcs.join(" \\\n\t ")}
MAKEFILE
]
end
48 changes: 31 additions & 17 deletions gc/mmtk/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,35 @@ fn mmtk_builder_default_parse_heap_max() -> usize {
size
}

fn mmtk_builder_default_parse_heap_mode(heap_min: usize, heap_max: usize) -> GCTriggerSelector {
let heap_mode_str = std::env::var("MMTK_HEAP_MODE")
.unwrap_or("dynamic".to_string());

match heap_mode_str.as_str() {
"fixed" => GCTriggerSelector::FixedHeapSize(heap_max),
"dynamic" => GCTriggerSelector::DynamicHeapSize(heap_min, heap_max),
_ => {
eprintln!("[FATAL] Invalid MMTK_HEAP_MODE {}", heap_mode_str);
std::process::exit(1);
}
}
}

fn mmtk_builder_default_parse_plan() -> PlanSelector {
let plan_str = std::env::var("MMTK_PLAN")
.unwrap_or("MarkSweep".to_string());

match plan_str.as_str() {
"NoGC" => PlanSelector::NoGC,
"MarkSweep" => PlanSelector::MarkSweep,
"Immix" => PlanSelector::Immix,
_ => {
eprintln!("[FATAL] Invalid MMTK_PLAN {}", plan_str);
std::process::exit(1);
}
}
}

#[no_mangle]
pub extern "C" fn mmtk_builder_default() -> *mut MMTKBuilder {
let mut builder = MMTKBuilder::new_no_env_vars();
Expand All @@ -96,24 +125,9 @@ pub extern "C" fn mmtk_builder_default() -> *mut MMTKBuilder {
std::process::exit(1);
}

let mmtk_mode = match std::env::var("MMTK_HEAP_MODE") {
Ok(mode) if (mode == "fixed") => GCTriggerSelector::FixedHeapSize(heap_max),
Ok(_) | Err(_) => GCTriggerSelector::DynamicHeapSize(heap_min, heap_max)
};

// Parse the env var, if it's not found set the plan name to MarkSweep
let plan_name = std::env::var("MMTK_PLAN")
.unwrap_or(String::from("MarkSweep"));

// Parse the plan name into a valid MMTK Plan, if the name is not a valid plan use MarkSweep
let plan_selector = plan_name.parse::<PlanSelector>()
.unwrap_or("MarkSweep".parse::<PlanSelector>().unwrap());

builder.options.plan.set(plan_selector);

// Between 1MiB and 500MiB
builder.options.gc_trigger.set(mmtk_mode);
builder.options.gc_trigger.set(mmtk_builder_default_parse_heap_mode(heap_min, heap_max));

builder.options.plan.set(mmtk_builder_default_parse_plan());

Box::into_raw(Box::new(builder))
}
Expand Down
6 changes: 3 additions & 3 deletions lib/prism.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ def self.lex_ripper(source)
end

# :call-seq:
# Prism::load(source, serialized) -> ParseResult
# Prism::load(source, serialized, freeze) -> ParseResult
#
# Load the serialized AST using the source as a reference into a tree.
def self.load(source, serialized)
Serialize.load(source, serialized)
def self.load(source, serialized, freeze = false)
Serialize.load_parse(source, serialized, freeze)
end
end

Expand Down
41 changes: 16 additions & 25 deletions lib/prism/ffi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ module LibRubyParser # :nodoc:
# must align with the build shared library from make/rake.
libprism_in_build = File.expand_path("../../build/libprism.#{RbConfig::CONFIG["SOEXT"]}", __dir__)
libprism_in_libdir = "#{RbConfig::CONFIG["libdir"]}/prism/libprism.#{RbConfig::CONFIG["SOEXT"]}"
if File.exist? libprism_in_build

if File.exist?(libprism_in_build)
INCLUDE_DIR = File.expand_path("../../include", __dir__)
ffi_lib libprism_in_build
else
Expand Down Expand Up @@ -279,7 +280,7 @@ def parse_stream(stream, **options)
# access to the IO object already through the closure of the lambda, we
# can pass a null pointer here and not worry.
LibRubyParser.pm_serialize_parse_stream(buffer.pointer, nil, callback, dump_options(options))
Prism.load(source, buffer.read)
Prism.load(source, buffer.read, options.fetch(:freeze, false))
end
end

Expand Down Expand Up @@ -354,50 +355,37 @@ def profile_file(filepath, **options)
def dump_common(string, options) # :nodoc:
LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
buffer.read

dumped = buffer.read
dumped.freeze if options.fetch(:freeze, false)

dumped
end
end

def lex_common(string, code, options) # :nodoc:
serialized = LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser.pm_serialize_lex(buffer.pointer, string.pointer, string.length, dump_options(options))
buffer.read
Serialize.load_lex(code, buffer.read, options.fetch(:freeze, false))
end

Serialize.load_tokens(Source.for(code), serialized)
end

def parse_common(string, code, options) # :nodoc:
serialized = dump_common(string, options)
Prism.load(code, serialized)
Serialize.load_parse(code, serialized, options.fetch(:freeze, false))
end

def parse_comments_common(string, code, options) # :nodoc:
LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser.pm_serialize_parse_comments(buffer.pointer, string.pointer, string.length, dump_options(options))

source = Source.for(code)
loader = Serialize::Loader.new(source, buffer.read)

loader.load_header
loader.load_encoding
loader.load_start_line
loader.load_comments
Serialize.load_parse_comments(code, buffer.read, options.fetch(:freeze, false))
end
end

def parse_lex_common(string, code, options) # :nodoc:
LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser.pm_serialize_parse_lex(buffer.pointer, string.pointer, string.length, dump_options(options))

source = Source.for(code)
loader = Serialize::Loader.new(source, buffer.read)

tokens = loader.load_tokens
node, comments, magic_comments, data_loc, errors, warnings = loader.load_nodes
tokens.each { |token,| token.value.force_encoding(loader.encoding) }

ParseLexResult.new([node, tokens], comments, magic_comments, data_loc, errors, warnings, source)
Serialize.load_parse_lex(code, buffer.read, options.fetch(:freeze, false))
end
end

Expand Down Expand Up @@ -482,6 +470,9 @@ def dump_options(options)
template << "C"
values << (options.fetch(:partial_script, false) ? 1 : 0)

template << "C"
values << (options.fetch(:freeze, false) ? 1 : 0)

template << "L"
if (scopes = options[:scopes])
values << scopes.length
Expand Down
24 changes: 24 additions & 0 deletions lib/prism/parse_result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ def initialize(source, start_line = 1, offsets = [])
@offsets = offsets # set after parsing is done
end

# Replace the value of start_line with the given value.
def replace_start_line(start_line)
@start_line = start_line
end

# Replace the value of offsets with the given value.
def replace_offsets(offsets)
@offsets.replace(offsets)
end

# Returns the encoding of the source code, which is set by parameters to the
# parser or by the encoding magic comment.
def encoding
Expand Down Expand Up @@ -132,6 +142,13 @@ def code_units_column(byte_offset, encoding)
code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding)
end

# Freeze this object and the objects it contains.
def deep_freeze
source.freeze
offsets.freeze
freeze
end

private

# Binary search through the offsets to find the line number for the given
Expand Down Expand Up @@ -854,5 +871,12 @@ def inspect
location
super
end

# Freeze this object and the objects it contains.
def deep_freeze
value.freeze
location.freeze
freeze
end
end
end
2 changes: 1 addition & 1 deletion lib/prism/translation/ruby_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1559,7 +1559,7 @@ def visit_block(node, sexp, block)
else
parameters =
case block.parameters
when nil, NumberedParametersNode
when nil, ItParametersNode, NumberedParametersNode
0
else
visit(block.parameters)
Expand Down
Loading
Loading