Skip to content

Commit

Permalink
Merge branch 'master' into printf_temp_fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
enebo committed Nov 2, 2023
2 parents 1c29bb7 + edf1eea commit f373339
Show file tree
Hide file tree
Showing 213 changed files with 7,480 additions and 2,623 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.4.5.0-SNAPSHOT
9.4.6.0-SNAPSHOT
4 changes: 2 additions & 2 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ DO NOT MODIFY - GENERATED CODE
<parent>
<groupId>org.jruby</groupId>
<artifactId>jruby-parent</artifactId>
<version>9.4.5.0-SNAPSHOT</version>
<version>9.4.6.0-SNAPSHOT</version>
</parent>
<artifactId>jruby-base</artifactId>
<name>JRuby Base</name>
Expand Down Expand Up @@ -711,7 +711,7 @@ DO NOT MODIFY - GENERATED CODE
<path>
<groupId>org.jruby</groupId>
<artifactId>jruby-base</artifactId>
<version>9.4.5.0-SNAPSHOT</version>
<version>9.4.6.0-SNAPSHOT</version>
</path>
</annotationProcessorPaths>
</configuration>
Expand Down
210 changes: 210 additions & 0 deletions core/src/main/java/org/jruby/FiberScheduler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
package org.jruby;

import jnr.constants.platform.Errno;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.io.OpenFile;

import java.nio.ByteBuffer;

public class FiberScheduler {
// MRI: rb_fiber_scheduler_kernel_sleep
public static IRubyObject kernelSleep(ThreadContext context, IRubyObject scheduler, IRubyObject timeout) {
return scheduler.callMethod(context, "kernel_sleep", timeout);
}

// MRI: rb_fiber_scheduler_kernel_sleepv
public static IRubyObject kernelSleep(ThreadContext context, IRubyObject scheduler, IRubyObject[] args) {
return scheduler.callMethod(context, "kernel_sleep", args);
}

// MRI: rb_fiber_scheduler_process_wait
public static IRubyObject processWait(ThreadContext context, IRubyObject scheduler, long pid, int flags) {
return Helpers.invokeChecked(context, scheduler, "process_wait", context.runtime.newFixnum(pid), context.runtime.newFixnum(flags));
}

// MRI: rb_fiber_scheduler_block
public static IRubyObject block(ThreadContext context, IRubyObject scheduler, IRubyObject blocker, IRubyObject timeout) {
return Helpers.invoke(context, scheduler, "block", blocker, timeout);
}

// MRI: rb_fiber_scheduler_unblock
public static IRubyObject unblock(ThreadContext context, IRubyObject scheduler, IRubyObject blocker, IRubyObject fiber) {
return Helpers.invoke(context, scheduler, "unblock", blocker, fiber);
}

// MRI: rb_fiber_scheduler_io_wait
public static IRubyObject ioWait(ThreadContext context, IRubyObject scheduler, IRubyObject io, IRubyObject events, IRubyObject timeout) {
return Helpers.invoke(context, scheduler, "io_wait", io, events, timeout);
}

// MRI: rb_fiber_scheduler_io_wait_readable
public static IRubyObject ioWaitReadable(ThreadContext context, IRubyObject scheduler, IRubyObject io) {
return ioWait(context, scheduler, io, context.runtime.newFixnum(OpenFile.READABLE), context.nil);
}

// MRI: rb_fiber_scheduler_io_wait_writable
public static IRubyObject ioWaitWritable(ThreadContext context, IRubyObject scheduler, IRubyObject io) {
return ioWait(context, scheduler, io, context.runtime.newFixnum(OpenFile.WRITABLE), context.nil);
}

// MRI: rb_fiber_scheduler_io_select
public static IRubyObject ioSelect(ThreadContext context, IRubyObject scheduler, IRubyObject readables, IRubyObject writables, IRubyObject exceptables, IRubyObject timeout) {
return ioSelectv(context, scheduler, readables, writables, exceptables, timeout);
}

// MRI: rb_fiber_scheduler_io_selectv
public static IRubyObject ioSelectv(ThreadContext context, IRubyObject scheduler, IRubyObject... args) {
return Helpers.invokeChecked(context, scheduler, "io_select", args);
}

// MRI: rb_fiber_scheduler_io_read
public static IRubyObject ioRead(ThreadContext context, IRubyObject scheduler, IRubyObject io, IRubyObject buffer, int length, int offset) {
Ruby runtime = context.runtime;
return Helpers.invokeChecked(context, scheduler, "io_read", io, buffer, runtime.newFixnum(length), runtime.newFixnum(offset));
}

public static IRubyObject ioRead(ThreadContext context, IRubyObject scheduler, IRubyObject io, IRubyObject buffer, RubyInteger length, RubyInteger offset) {
return Helpers.invokeChecked(context, scheduler, "io_read", io, buffer, length, offset);
}

// MRI: rb_fiber_scheduler_io_pread
public static IRubyObject ioPRead(ThreadContext context, IRubyObject scheduler, IRubyObject io, IRubyObject buffer, int from, int length, int offset) {
return Helpers.invokeChecked(context, scheduler, "io_pread", io, buffer, context.runtime.newFixnum(from), context.runtime.newFixnum(length), context.runtime.newFixnum(offset));
}

public static IRubyObject ioPRead(ThreadContext context, IRubyObject scheduler, IRubyObject io, IRubyObject buffer, RubyInteger from, RubyInteger length, RubyInteger offset) {
return Helpers.invokeChecked(context, scheduler, "io_pread", io, buffer, from, length, offset);
}

// MRI: rb_fiber_scheduler_io_write
public static IRubyObject ioWrite(ThreadContext context, IRubyObject scheduler, IRubyObject io, IRubyObject buffer, int length, int offset) {
Ruby runtime = context.runtime;
return Helpers.invokeChecked(context, scheduler, "io_write", io, buffer, runtime.newFixnum(length), runtime.newFixnum(offset));
}

public static IRubyObject ioWrite(ThreadContext context, IRubyObject scheduler, IRubyObject io, IRubyObject buffer, RubyInteger length, RubyInteger offset) {
return Helpers.invokeChecked(context, scheduler, "io_write", io, buffer, length, offset);
}

// MRI: rb_fiber_scheduler_io_pwrite
public static IRubyObject ioPWrite(ThreadContext context, IRubyObject scheduler, IRubyObject io, IRubyObject buffer, int from, int length, int offset) {
return Helpers.invokeChecked(context, scheduler, "io_pwrite", io, buffer, context.runtime.newFixnum(from), context.runtime.newFixnum(length), context.runtime.newFixnum(offset));
}

public static IRubyObject ioPWrite(ThreadContext context, IRubyObject scheduler, IRubyObject io, IRubyObject buffer, RubyInteger from, RubyInteger length, RubyInteger offset) {
return Helpers.invokeChecked(context, scheduler, "io_pwrite", io, buffer, from, length, offset);
}

// MRI: rb_fiber_scheduler_io_read_memory
public static IRubyObject ioReadMemory(ThreadContext context, IRubyObject scheduler, IRubyObject io, ByteBuffer base, int size, int length) {
RubyIOBuffer buffer = RubyIOBuffer.newBuffer(context.runtime, base, size, RubyIOBuffer.LOCKED);

IRubyObject result = ioRead(context, scheduler, io, buffer, length, 0);

buffer.unlock(context);
buffer.free(context);

return result;
}

// MRI: rb_fiber_scheduler_io_pread_memory
public static IRubyObject ioPReadMemory(ThreadContext context, IRubyObject scheduler, IRubyObject io, ByteBuffer base, int from, int size, int length) {
RubyIOBuffer buffer = RubyIOBuffer.newBuffer(context.runtime, base, size, RubyIOBuffer.LOCKED);

IRubyObject result = ioPRead(context, scheduler, io, buffer, from, length, 0);

buffer.unlock(context);
buffer.free(context);

return result;
}

// MRI: rb_fiber_scheduler_io_write_memory
public static IRubyObject ioWriteMemory(ThreadContext context, IRubyObject scheduler, IRubyObject io, ByteBuffer base, int size, int length) {
RubyIOBuffer buffer = RubyIOBuffer.newBuffer(context.runtime, base, size, RubyIOBuffer.LOCKED | RubyIOBuffer.READONLY);

IRubyObject result = ioWrite(context, scheduler, io, buffer, length, 0);

buffer.unlock(context);
buffer.free(context);

return result;
}

// MRI: p
public static IRubyObject ioPWriteMemory(ThreadContext context, IRubyObject scheduler, IRubyObject io, ByteBuffer base, int from, int size, int length) {
RubyIOBuffer buffer = RubyIOBuffer.newBuffer(context.runtime, base, size, RubyIOBuffer.LOCKED | RubyIOBuffer.READONLY);

IRubyObject result = ioPWrite(context, scheduler, io, buffer, from, length, 0);

buffer.unlock(context);
buffer.free(context);

return result;
}

// MRI: rb_fiber_scheduler_io_close
public static IRubyObject ioClose(ThreadContext context, IRubyObject scheduler, IRubyObject io) {
return Helpers.invokeChecked(context, scheduler, "io_close", io);
}

// MRI: rb_fiber_scheduler_address_resolve
public static IRubyObject addressResolve(ThreadContext context, IRubyObject scheduler, IRubyObject hostname) {
return Helpers.invokeChecked(context, scheduler, "address_resolve", hostname);
}

// MRI: verify_scheduler
static void verifyInterface(IRubyObject scheduler) {
if (!scheduler.respondsTo("block")) {
throw scheduler.getRuntime().newArgumentError("Scheduler must implement #block");
}

if (!scheduler.respondsTo("unblock")) {
throw scheduler.getRuntime().newArgumentError("Scheduler must implement #unblock");
}

if (!scheduler.respondsTo("kernel_sleep")) {
throw scheduler.getRuntime().newArgumentError("Scheduler must implement #kernel_sleep");
}

if (!scheduler.respondsTo("io_wait")) {
throw scheduler.getRuntime().newArgumentError("Scheduler must implement #io_wait");
}
}

// MRI: rb_fiber_scheduler_close
public static IRubyObject close(ThreadContext context, IRubyObject scheduler) {
// VM_ASSERT(ruby_thread_has_gvl_p());

IRubyObject result;

result = Helpers.invokeChecked(context, scheduler, "scheduler_close");
if (result != null) return result;

result = Helpers.invokeChecked(context, scheduler, "close");
if (result != null) return result;

return context.nil;
}

// MRI: rb_fiber_scheduler_io_result_apply
public static int resultApply(ThreadContext context, IRubyObject result) {
int resultInt;
if (result instanceof RubyFixnum && (resultInt = RubyNumeric.num2int(result)) < 0) {
context.runtime.getPosix().errno(-resultInt);
return -1;
} else {
return RubyNumeric.num2int(result);
}
}

public static IRubyObject result(Ruby runtime, int result, Errno error) {
if (result == -1) {
return RubyFixnum.newFixnum(runtime, error.value());
} else {
return RubyFixnum.newFixnum(runtime, result);
}
}
}
67 changes: 67 additions & 0 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,11 @@ private Ruby(RubyInstanceConfig config) {
randomClass = null;
}
ioClass = RubyIO.createIOClass(this);
if (Options.FIBER_SCHEDULER.load()) {
ioBufferClass = RubyIOBuffer.createIOBufferClass(this);
} else {
ioBufferClass = null;
}

structClass = profile.allowClass("Struct") ? RubyStruct.createStructClass(this) : null;
bindingClass = profile.allowClass("Binding") ? RubyBinding.createBindingClass(this) : null;
Expand Down Expand Up @@ -590,6 +595,7 @@ private void initBootLibraries() {
loadService.provide("rational.rb");
loadService.provide("complex.rb");
loadService.provide("thread.rb");
loadService.provide("fiber.rb");
loadService.provide("ruby2_keywords.rb");

// Load preludes
Expand Down Expand Up @@ -1714,6 +1720,17 @@ private void initExceptions() {
ifAllowed("KeyError", (ruby) -> keyError = RubyKeyError.define(ruby, indexError));
ifAllowed("DomainError", (ruby) -> mathDomainError = RubyDomainError.define(ruby, argumentError, mathModule));

RubyClass runtimeError = this.runtimeError;
ObjectAllocator runtimeErrorAllocator = runtimeError.getAllocator();

if (Options.FIBER_SCHEDULER.load()) {
bufferLockedError = ioBufferClass.defineClassUnder("LockedError", runtimeError, runtimeErrorAllocator);
bufferAllocationError = ioBufferClass.defineClassUnder("AllocationError", runtimeError, runtimeErrorAllocator);
bufferAccessError = ioBufferClass.defineClassUnder("AccessError", runtimeError, runtimeErrorAllocator);
bufferInvalidatedError = ioBufferClass.defineClassUnder("InvalidatedError", runtimeError, runtimeErrorAllocator);
bufferMaskError = ioBufferClass.defineClassUnder("MaskError", runtimeError, runtimeErrorAllocator);
}

initErrno();

initNativeException();
Expand Down Expand Up @@ -2174,6 +2191,10 @@ public RubyClass getIO() {
return ioClass;
}

public RubyClass getIOBuffer() {
return ioBufferClass;
}

public RubyClass getThread() {
return threadClass;
}
Expand Down Expand Up @@ -2485,6 +2506,26 @@ public RubyClass getInvalidByteSequenceError() {
return invalidByteSequenceError;
}

public RubyClass getBufferLockedError() {
return bufferLockedError;
}

public RubyClass getBufferAllocationError() {
return bufferAllocationError;
}

public RubyClass getBufferAccessError() {
return bufferAccessError;
}

public RubyClass getBufferInvalidatedError() {
return bufferInvalidatedError;
}

public RubyClass getBufferMaskError() {
return bufferMaskError;
}

@Deprecated
RubyRandom.RandomType defaultRand;

Expand Down Expand Up @@ -4246,6 +4287,26 @@ public RaiseException newInvalidByteSequenceError(String message) {
return newRaiseException(getInvalidByteSequenceError(), message);
}

public RaiseException newBufferLockedError(String message) {
return newRaiseException(getBufferLockedError(), message);
}

public RaiseException newBufferAllocationError(String message) {
return newRaiseException(getBufferAllocationError(), message);
}

public RaiseException newBufferAccessError(String message) {
return newRaiseException(getBufferAccessError(), message);
}

public RaiseException newBufferInvalidatedError(String message) {
return newRaiseException(getBufferInvalidatedError(), message);
}

public RaiseException newBufferMaskError(String message) {
return newRaiseException(getBufferMaskError(), message);
}

/**
* Construct a new RaiseException wrapping a new Ruby exception object appropriate to the given exception class.
*
Expand Down Expand Up @@ -5361,6 +5422,7 @@ public RubyClass getData() {
private final RubyClass fileClass;
private final RubyClass fileStatClass;
private final RubyClass ioClass;
private final RubyClass ioBufferClass;
private final RubyClass threadClass;
private final RubyClass threadGroupClass;
private final RubyClass continuationClass;
Expand Down Expand Up @@ -5422,6 +5484,11 @@ public RubyClass getData() {
private RubyClass keyError;
private RubyClass locationClass;
private RubyClass interruptedRegexpError;
private RubyClass bufferLockedError;
private RubyClass bufferAllocationError;
private RubyClass bufferAccessError;
private RubyClass bufferInvalidatedError;
private RubyClass bufferMaskError;

/**
* All the core modules we keep direct references to, for quick access and
Expand Down
18 changes: 11 additions & 7 deletions core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -2924,7 +2924,7 @@ public IRubyObject select_bang(ThreadContext context, Block block) {
}
finally {
if (modified) checkFrozen();
selectBangEnsure(runtime, len, beg, len0, len1);
selectBangEnsure(runtime, len0, len1);
}
}

Expand Down Expand Up @@ -3082,17 +3082,20 @@ public IRubyObject rejectBang(ThreadContext context, Block block) {
}
finally {
if (modified) checkFrozen();
selectBangEnsure(runtime, realLength, beg, len0, len1);
selectBangEnsure(runtime, len0, len1);
}
}

// MRI: select_bang_ensure
private void selectBangEnsure(final Ruby runtime, final int len, final int beg,
int i1, int i2) {
if (i2 < i1) {
realLength = len - i1 + i2;
private void selectBangEnsure(final Ruby runtime, int i1, int i2) {
int len = realLength;

if (i2 < len && i2 < i1) {
int tail = 0;
int beg = begin;
if (i1 < len) {
safeArrayCopy(runtime, values, beg + i1, values, beg + i2, len - i1);
tail = len - i1;
safeArrayCopy(runtime, values, beg + i1, values, beg + i2, tail);
}
else if (realLength > 0) {
// nil out left-overs to avoid leaks (MRI doesn't)
Expand All @@ -3102,6 +3105,7 @@ else if (realLength > 0) {
throw concurrentModification(runtime, ex);
}
}
realLength = i2 + tail;
}
}

Expand Down
Loading

0 comments on commit f373339

Please sign in to comment.