Skip to content

Commit bd0bb40

Browse files
committed
Merge remote-tracking branch 'upstream/master' into Ractor-Local-GC-version-3
2 parents a2cc985 + 2183899 commit bd0bb40

File tree

20 files changed

+310
-889
lines changed

20 files changed

+310
-889
lines changed

LEGAL

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -371,33 +371,6 @@ mentioned below.
371371
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
372372
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
373373

374-
[spec/lib/turbo_tests/*]
375-
[spec/lib/turbo_tests.rb]
376-
[spec/lib/utils/*]
377-
378-
These files are under the MIT License.
379-
380-
>>>
381-
Copyright (c) 2020 Ilya Zub
382-
383-
Permission is hereby granted, free of charge, to any person obtaining a copy
384-
of this software and associated documentation files (the "Software"), to deal
385-
in the Software without restriction, including without limitation the rights
386-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
387-
copies of the Software, and to permit persons to whom the Software is
388-
furnished to do so, subject to the following conditions:
389-
390-
The above copyright notice and this permission notice shall be included in
391-
all copies or substantial portions of the Software.
392-
393-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
394-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
395-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
396-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
397-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
398-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
399-
THE SOFTWARE.
400-
401374
[parse.c]
402375
[parse.h]
403376

bootstraptest/test_fork.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,18 @@ def now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
8585
10.times do
8686
pid = fork{ exit!(0) }
8787
deadline = now + 10
88-
until Process.waitpid(pid, Process::WNOHANG)
88+
while true
89+
_, status = Process.waitpid2(pid, Process::WNOHANG)
90+
break if status
8991
if now > deadline
9092
Process.kill(:KILL, pid)
9193
raise "failed"
9294
end
9395
sleep 0.001
9496
end
97+
unless status.success?
98+
raise "child exited with status #{status}"
99+
end
95100
rescue NotImplementedError
96101
end
97102
:ok

common.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1683,7 +1683,7 @@ yes-test-bundler-parallel: $(PREPARE_BUNDLER)
16831683
-I$(srcdir)/spec/bundler \
16841684
-e "ruby = ENV['RUBY']" \
16851685
-e "ARGV[-1] = File.expand_path(ARGV[-1])" \
1686-
-e "ENV['PARALLEL_TESTS_EXECUTABLE'] = ruby + ARGV.shift" \
1686+
-e "ENV['RSPEC_EXECUTABLE'] = ruby + ARGV.shift" \
16871687
-e "load ARGV.shift" \
16881688
" -C $(srcdir) -Ispec/bundler -Ispec/lib .bundle/bin/rspec -r spec_helper" \
16891689
$(srcdir)/spec/bin/parallel_rspec $(RSPECOPTS) \

ext/etc/etc.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,14 +1163,26 @@ Init_etc(void)
11631163
{
11641164
VALUE mEtc;
11651165

1166-
#ifdef HAVE_RB_EXT_RACTOR_SAFE
1167-
RB_EXT_RACTOR_SAFE(true);
1168-
#endif
11691166
mEtc = rb_define_module("Etc");
11701167
/* The version */
11711168
rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION));
11721169
init_constants(mEtc);
11731170

1171+
/* Ractor-safe methods */
1172+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
1173+
RB_EXT_RACTOR_SAFE(true);
1174+
#endif
1175+
rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
1176+
rb_define_module_function(mEtc, "uname", etc_uname, 0);
1177+
rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
1178+
rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
1179+
rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
1180+
rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0);
1181+
1182+
/* Non-Ractor-safe methods, see https://bugs.ruby-lang.org/issues/21115 */
1183+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
1184+
RB_EXT_RACTOR_SAFE(false);
1185+
#endif
11741186
rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0);
11751187

11761188
rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1);
@@ -1186,13 +1198,9 @@ Init_etc(void)
11861198
rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0);
11871199
rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
11881200
rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
1201+
1202+
/* Uses RbConfig::CONFIG so does not work in a Ractor */
11891203
rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
1190-
rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
1191-
rb_define_module_function(mEtc, "uname", etc_uname, 0);
1192-
rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
1193-
rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
1194-
rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
1195-
rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0);
11961204

11971205
sPasswd = rb_struct_define_under(mEtc, "Passwd",
11981206
"name",

gc/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Two GC implementations are included in Ruby:
1717
1818
1. Configure Ruby with the `--with-modular-gc=<dir>` option, where `dir` is the directory you want to place the built GC libraries into.
1919
2. Build Ruby as usual.
20-
3. Build your desired GC implementation with `make modular-gc MODULAR_GC=<impl>`. This will build the GC implementation and place the built library into the `dir` specified in step 1. `impl` can be one of:
20+
3. Build your desired GC implementation with `make install-modular-gc MODULAR_GC=<impl>`. This will build the GC implementation and place the built library into the `dir` specified in step 1. `impl` can be one of:
2121
- `default`: The default GC that Ruby ships with.
2222
- `mmtk`: The GC that uses [MMTk](https://www.mmtk.io/) as the back-end. See Ruby-specific details in the [ruby/mmtk](https://github.com/ruby/mmtk) repository.
2323
4. Run your desired GC implementation by setting the `RUBY_GC_LIBRARY=<lib>` environment variable, where `lib` could be `default`, `mmtk`, or your own implementation (as long as you place it in the `dir` specified in step 1).

gc/default/default.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,9 +1039,9 @@ struct RZombie {
10391039

10401040
#define RZOMBIE(o) ((struct RZombie *)(o))
10411041

1042-
int ruby_enable_autocompact = 0;
1042+
static bool ruby_enable_autocompact = false;
10431043
#if RGENGC_CHECK_MODE
1044-
gc_compact_compare_func ruby_autocompact_compare_func;
1044+
static gc_compact_compare_func ruby_autocompact_compare_func;
10451045
#endif
10461046

10471047
static void init_mark_stack(mark_stack_t *stack);
@@ -3480,7 +3480,7 @@ rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj)
34803480
static VALUE
34813481
get_object_id_in_finalizer(rb_objspace_t *objspace, VALUE obj)
34823482
{
3483-
if (FL_TEST(obj, FL_SEEN_OBJ_ID)) {
3483+
if (FL_TEST_RAW(obj, FL_SEEN_OBJ_ID)) {
34843484
return rb_gc_impl_object_id(objspace, obj);
34853485
}
34863486
else {
@@ -3534,7 +3534,7 @@ finalize_list(rb_objspace_t *objspace, VALUE zombie)
35343534
OBJSPACE_LOCK_ENTER(objspace);
35353535
{
35363536
GC_ASSERT(BUILTIN_TYPE(zombie) == T_ZOMBIE);
3537-
if (FL_TEST(zombie, FL_SEEN_OBJ_ID)) {
3537+
if (FL_TEST_RAW(zombie, FL_SEEN_OBJ_ID)) {
35383538
obj_free_object_id(objspace, zombie);
35393539
}
35403540

@@ -4179,7 +4179,7 @@ gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bit
41794179

41804180
rb_gc_event_hook(vp, RUBY_INTERNAL_EVENT_FREEOBJ);
41814181

4182-
bool has_object_id = FL_TEST(vp, FL_SEEN_OBJ_ID);
4182+
bool has_object_id = FL_TEST_RAW(vp, FL_SEEN_OBJ_ID);
41834183
rb_gc_obj_free_vm_weak_references(vp);
41844184
if (rb_gc_obj_free(objspace, vp)) {
41854185
if (has_object_id) {
@@ -8030,7 +8030,7 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
80308030
case T_RATIONAL:
80318031
case T_NODE:
80328032
case T_CLASS:
8033-
if (FL_TEST(obj, FL_FINALIZE)) {
8033+
if (FL_TEST_RAW(obj, FL_FINALIZE)) {
80348034
/* The finalizer table is a numtable. It looks up objects by address.
80358035
* We can't mark the keys in the finalizer table because that would
80368036
* prevent the objects from being collected. This check prevents
@@ -8068,7 +8068,7 @@ static void
80688068
update_obj_id_mapping(rb_objspace_t *objspace, VALUE dest, VALUE src)
80698069
{
80708070
rb_native_mutex_lock(&objspace->obj_id_lock);
8071-
if (FL_TEST((VALUE)src, FL_SEEN_OBJ_ID)) {
8071+
if (FL_TEST_RAW((VALUE)src, FL_SEEN_OBJ_ID)) {
80728072
/* If the source object's object_id has been seen, we need to update
80738073
* the object to object id mapping. */
80748074
st_data_t srcid = (st_data_t)src, id;

hash.c

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3327,13 +3327,97 @@ static int flatten_i(VALUE key, VALUE val, VALUE ary);
33273327

33283328
/*
33293329
* call-seq:
3330-
* transform_keys! {|key| ... } -> self
3331-
* transform_keys!(hash2) -> self
3332-
* transform_keys!(hash2) {|other_key| ...} -> self
3330+
* transform_keys! {|old_key| ... } -> self
3331+
* transform_keys!(other_hash) -> self
3332+
* transform_keys!(other_hash) {|old_key| ...} -> self
33333333
* transform_keys! -> new_enumerator
33343334
*
3335-
* Same as Hash#transform_keys but modifies the receiver in place
3336-
* instead of returning a new hash.
3335+
* With an argument, a block, or both given,
3336+
* derives keys from the argument, the block, and +self+;
3337+
* all, some, or none of the keys in +self+ may be changed.
3338+
*
3339+
* With a block given and no argument,
3340+
* derives keys only from the block;
3341+
* all, some, or none of the keys in +self+ may be changed.
3342+
*
3343+
* For each key/value pair <tt>old_key/value</tt> in +self+, calls the block with +old_key+;
3344+
* the block's return value becomes +new_key+;
3345+
* removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
3346+
* sets <tt>self[new_key] = value</tt>;
3347+
* a duplicate key overwrites:
3348+
*
3349+
* h = {foo: 0, bar: 1, baz: 2}
3350+
* h.transform_keys! {|old_key| old_key.to_s }
3351+
* # => {"foo" => 0, "bar" => 1, "baz" => 2}
3352+
* h = {foo: 0, bar: 1, baz: 2}
3353+
* h.transform_keys! {|old_key| 'xxx' }
3354+
* # => {"xxx" => 2}
3355+
*
3356+
* With argument +other_hash+ given and no block,
3357+
* derives keys for +self+ from +other_hash+ and +self+;
3358+
* all, some, or none of the keys in +self+ may be changed.
3359+
*
3360+
* For each key/value pair <tt>old_key/old_value</tt> in +self+,
3361+
* looks for key +old_key+ in +other_hash+:
3362+
*
3363+
* - If +old_key+ is found, takes value <tt>other_hash[old_key]</tt> as +new_key+;
3364+
* removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
3365+
* sets <tt>self[new_key] = value</tt>;
3366+
* a duplicate key overwrites:
3367+
*
3368+
* h = {foo: 0, bar: 1, baz: 2}
3369+
* h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO)
3370+
* # => {FOO: 0, BAR: 1, BAZ: 2}
3371+
* h = {foo: 0, bar: 1, baz: 2}
3372+
* h.transform_keys!(baz: :FOO, bar: :FOO, foo: :FOO)
3373+
* # => {FOO: 2}
3374+
*
3375+
* - If +old_key+ is not found, does nothing:
3376+
*
3377+
* h = {foo: 0, bar: 1, baz: 2}
3378+
* h.transform_keys!({})
3379+
* # => {foo: 0, bar: 1, baz: 2}
3380+
* h.transform_keys!(baz: :foo)
3381+
* # => {foo: 2, bar: 1}
3382+
*
3383+
* Unused keys in +other_hash+ are ignored:
3384+
*
3385+
* h = {foo: 0, bar: 1, baz: 2}
3386+
* h.transform_keys!(bat: 3)
3387+
* # => {foo: 0, bar: 1, baz: 2}
3388+
*
3389+
* With both argument +other_hash+ and a block given,
3390+
* derives keys from +other_hash+, the block, and +self+;
3391+
* all, some, or none of the keys in +self+ may be changed.
3392+
*
3393+
* For each pair +old_key+ and +value+ in +self+:
3394+
*
3395+
* - If +other_hash+ has key +old_key+ (with value +new_key+),
3396+
* does not call the block for that key;
3397+
* removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
3398+
* sets <tt>self[new_key] = value</tt>;
3399+
* a duplicate key overwrites:
3400+
*
3401+
* h = {foo: 0, bar: 1, baz: 2}
3402+
* h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO) {|key| fail 'Not called' }
3403+
* # => {FOO: 0, BAR: 1, BAZ: 2}
3404+
*
3405+
* - If +other_hash+ does not have key +old_key+,
3406+
* calls the block with +old_key+ and takes its return value as +new_key+;
3407+
* removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
3408+
* sets <tt>self[new_key] = value</tt>;
3409+
* a duplicate key overwrites:
3410+
*
3411+
* h = {foo: 0, bar: 1, baz: 2}
3412+
* h.transform_keys!(baz: :BAZ) {|key| key.to_s.reverse }
3413+
* # => {"oof" => 0, "rab" => 1, BAZ: 2}
3414+
* h = {foo: 0, bar: 1, baz: 2}
3415+
* h.transform_keys!(baz: :BAZ) {|key| 'ook' }
3416+
* # => {"ook" => 1, BAZ: 2}
3417+
*
3418+
* With no argument and no block given, returns a new Enumerator.
3419+
*
3420+
* Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
33373421
*/
33383422
static VALUE
33393423
rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)

lib/bundler/definition.rb

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -953,11 +953,17 @@ def converge_dependencies
953953
unless name == "bundler"
954954
locked_specs = @originally_locked_specs[name]
955955

956-
if locked_specs.any? && !dep.matches_spec?(locked_specs.first)
957-
@gems_to_unlock << name
958-
dep_changed = true
959-
elsif locked_specs.empty? && dep_changed == false
960-
@missing_lockfile_dep = name
956+
if locked_specs.empty?
957+
@missing_lockfile_dep = name if dep_changed == false
958+
else
959+
if locked_specs.map(&:source).uniq.size > 1
960+
@locked_specs.delete(locked_specs.select {|s| s.source != dep.source })
961+
end
962+
963+
unless dep.matches_spec?(locked_specs.first)
964+
@gems_to_unlock << name
965+
dep_changed = true
966+
end
961967
end
962968
end
963969

0 commit comments

Comments
 (0)