Skip to content

Commit

Permalink
Showing 108 changed files with 521 additions and 172 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyInstanceConfig.java
Original file line number Diff line number Diff line change
@@ -1861,7 +1861,7 @@ private static int initGlobalJavaVersion() {
return Opcodes.V1_5;
} else if (specVersion.equals("1.6")) {
return Opcodes.V1_6;
} else if (specVersion.equals("1.7") || specVersion.equals("1.8") || specVersion.equals("1.9")) {
} else if (specVersion.equals("1.7") || specVersion.equals("1.8") || specVersion.equals("1.9") || specVersion.equals("9")) {
return Opcodes.V1_7;
} else {
System.err.println("unsupported Java version \"" + specVersion + "\", defaulting to 1.5");
136 changes: 128 additions & 8 deletions core/src/main/java/org/jruby/ext/socket/RubyUNIXSocket.java
Original file line number Diff line number Diff line change
@@ -36,10 +36,15 @@
import jnr.unixsocket.UnixServerSocketChannel;
import jnr.unixsocket.UnixSocketAddress;
import jnr.unixsocket.UnixSocketChannel;
import jnr.posix.CmsgHdr;
import jnr.posix.MsgHdr;
import jnr.posix.POSIX;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyNumeric;
import org.jruby.RubyString;
import org.jruby.RubyIO;
import org.jruby.RubyFixnum;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Helpers;
@@ -49,10 +54,14 @@
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.io.ModeFlags;
import org.jruby.util.io.OpenFile;
import org.jruby.util.io.FilenoUtil;

import java.io.File;
import java.io.IOException;
import java.nio.channels.Channel;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;


@JRubyClass(name="UNIXSocket", parent="BasicSocket")
@@ -74,6 +83,18 @@ public RubyUNIXSocket(Ruby runtime, RubyClass type) {
super(runtime, type);
}

@JRubyMethod(meta = true)
public static IRubyObject for_fd(ThreadContext context, IRubyObject recv, IRubyObject _fileno) {
Ruby runtime = context.runtime;
int fileno = (int)_fileno.convertToInteger().getLongValue();

RubyClass klass = (RubyClass)recv;
RubyUNIXSocket unixSocket = (RubyUNIXSocket)(Helpers.invoke(context, klass, "allocate"));
UnixSocketChannel channel = UnixSocketChannel.fromFD(fileno);
unixSocket.init_sock(runtime, channel);
return unixSocket;
}

@JRubyMethod(visibility = Visibility.PRIVATE)
public IRubyObject initialize(ThreadContext context, IRubyObject path) {
init_unixsock(context.runtime, path, false);
@@ -133,16 +154,115 @@ public IRubyObject recvfrom(ThreadContext context, IRubyObject[] args) {
peeraddr(context));
}

@JRubyMethod(notImplemented = true)
public IRubyObject send_io(IRubyObject path) {
//TODO: implement, won't do this now
return getRuntime().getNil();
@JRubyMethod
public IRubyObject send_io(ThreadContext context, IRubyObject arg) {
final Ruby runtime = context.runtime;
final POSIX posix = runtime.getPosix();
OpenFile fptr = getOpenFileChecked();
int fd;

if (arg.callMethod(context, "kind_of?", runtime.getIO()).isTrue()) {
fd = ((RubyIO) arg).getOpenFileChecked().getFileno();
} else if (arg.callMethod(context, "kind_of?", runtime.getFixnum()).isTrue()) {
fd = ((RubyFixnum) arg).getIntValue();
} else {
throw runtime.newTypeError("neither IO nor file descriptor");
}

if (FilenoUtil.isFake(fd)) {
throw runtime.newTypeError("file descriptor is not native");
}

byte[] dataBytes = new byte[1];
dataBytes[0] = 0;

MsgHdr outMessage = posix.allocateMsgHdr();

ByteBuffer[] outIov = new ByteBuffer[1];
outIov[0] = ByteBuffer.allocateDirect(dataBytes.length);
outIov[0].put(dataBytes);
outIov[0].flip();

outMessage.setIov(outIov);

CmsgHdr outControl = outMessage.allocateControl(4);
outControl.setLevel(SocketLevel.SOL_SOCKET.intValue());
outControl.setType(0x01);

ByteBuffer fdBuf = ByteBuffer.allocateDirect(4);
fdBuf.order(ByteOrder.nativeOrder());
fdBuf.putInt(0, fd);
outControl.setData(fdBuf);

boolean locked = fptr.lock();
try {
while (posix.sendmsg(fptr.getFileno(), outMessage, 0) == -1) {
if (!fptr.waitWritable(context)) {
throw runtime.newErrnoFromInt(posix.errno(), "sendmsg(2)");
}
}
} finally {
if (locked) fptr.unlock();
}

return runtime.getNil();
}

@JRubyMethod(rest = true, notImplemented = true)
public IRubyObject recv_io(IRubyObject[] args) {
//TODO: implement, won't do this now
return getRuntime().getNil();
@JRubyMethod(optional = 2)
public IRubyObject recv_io(ThreadContext context, IRubyObject[] args) {
final Ruby runtime = context.runtime;
final POSIX posix = runtime.getPosix();
OpenFile fptr = getOpenFileChecked();

IRubyObject klass = runtime.getIO();
IRubyObject mode = runtime.getNil();
if (args.length > 0) {
klass = args[0];
}
if (args.length > 1) {
mode = args[1];
}

MsgHdr inMessage = posix.allocateMsgHdr();
ByteBuffer[] inIov = new ByteBuffer[1];
inIov[0] = ByteBuffer.allocateDirect(1);
inMessage.setIov(inIov);

CmsgHdr inControl = inMessage.allocateControl(4);
inControl.setLevel(SocketLevel.SOL_SOCKET.intValue());
inControl.setType(0x01);

ByteBuffer fdBuf = ByteBuffer.allocateDirect(4);
fdBuf.order(ByteOrder.nativeOrder());
fdBuf.putInt(0, -1);
inControl.setData(fdBuf);

boolean locked = fptr.lock();
try {
while (posix.recvmsg(fptr.getFileno(), inMessage, 0) == -1) {
if (!fptr.waitReadable(context)) {
throw runtime.newErrnoFromInt(posix.errno(), "recvmsg(2)");
}
}
} finally {
if (locked) fptr.unlock();
}


ByteBuffer inFdBuf = inMessage.getControls()[0].getData();
inFdBuf.order(ByteOrder.nativeOrder());

IRubyObject fd = runtime.newFixnum(inFdBuf.getInt());

if (klass.isNil()) {
return fd;
} else {
if (mode.isNil()) {
return Helpers.invoke(context, klass, "for_fd", fd);
} else {
return Helpers.invoke(context, klass, "for_fd", fd, mode);
}
}
}

@JRubyMethod(name = {"socketpair", "pair"}, optional = 2, meta = true)
Original file line number Diff line number Diff line change
@@ -20,18 +20,39 @@
// Represents a dynamic regexp in Ruby
// Ex: /#{a}#{b}/
public class BuildDynRegExpInstr extends NOperandResultBaseInstr {
final private RegexpOptions options;
// Create a cache object so that this can be shared
// through the lifetime of the original instruction independent
// of it being cloned (because of inlining, JIT-ting, whatever).
private static class RECache {
// Cached regexp
private volatile RubyRegexp rubyRegexp;
private static final AtomicReferenceFieldUpdater<RECache, RubyRegexp> UPDATER =
AtomicReferenceFieldUpdater.newUpdater(RECache.class, RubyRegexp.class, "rubyRegexp");
public void updateCache(boolean isOnce, RubyRegexp re) {
if (isOnce) {
// Atomically update this, so we only see one instance cached ever.
// See MRI's ruby/test_regexp.rb, test_once_multithread
UPDATER.compareAndSet(this, null, re);
} else {
rubyRegexp = re;
}
}
};

// Cached regexp
private volatile RubyRegexp rubyRegexp;
final private RegexpOptions options;
final private RECache reCache;

private static final AtomicReferenceFieldUpdater<BuildDynRegExpInstr, RubyRegexp> UPDATER =
AtomicReferenceFieldUpdater.newUpdater(BuildDynRegExpInstr.class, RubyRegexp.class, "rubyRegexp");
// Only used by cloning
private BuildDynRegExpInstr(Variable result, Operand[] pieces, RegexpOptions options, RECache reCache) {
super(Operation.BUILD_DREGEXP, result, pieces);
this.options = options;
this.reCache = reCache;
}

public BuildDynRegExpInstr(Variable result, Operand[] pieces, RegexpOptions options) {
super(Operation.BUILD_DREGEXP, result, pieces);

this.options = options;
this.reCache = new RECache();
}

public Operand[] getPieces() {
@@ -43,7 +64,7 @@ public RegexpOptions getOptions() {
}

public RubyRegexp getRegexp() {
return rubyRegexp;
return reCache.rubyRegexp;
}

@Override
@@ -53,7 +74,8 @@ public String[] toStringNonOperandArgs() {

@Override
public Instr clone(CloneInfo ii) {
return new BuildDynRegExpInstr(ii.getRenamedVariable(result), cloneOperands(ii), options);
// Share the cache!
return new BuildDynRegExpInstr(ii.getRenamedVariable(result), cloneOperands(ii), options, this.reCache);
}

private RubyString[] retrievePieces(ThreadContext context, IRubyObject self, StaticScope currScope, DynamicScope currDynScope, Object[] temp) {
@@ -82,21 +104,15 @@ public static BuildDynRegExpInstr decode(IRReaderDecoder d) {
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
// FIXME (from RegexpNode.java): 1.9 should care about internal or external encoding and not kcode.
// If we have a constant regexp string or if the regexp patterns asks for caching, cache the regexp
if (rubyRegexp == null || !options.isOnce() || context.runtime.getKCode() != rubyRegexp.getKCode()) {
if (reCache.rubyRegexp == null || !options.isOnce() || context.runtime.getKCode() != reCache.rubyRegexp.getKCode()) {
RubyString[] pieces = retrievePieces(context, self, currScope, currDynScope, temp);
RubyString pattern = RubyRegexp.preprocessDRegexp(context.runtime, pieces, options);
RubyRegexp re = RubyRegexp.newDRegexp(context.runtime, pattern, options);
re.setLiteral();
if (options.isOnce()) {
// Atomically update this, so we only see one instance cached ever.
// See MRI's ruby/test_regexp.rb, test_once_multithread
UPDATER.compareAndSet(this, null, re);
} else {
rubyRegexp = re;
}
reCache.updateCache(options.isOnce(), re);
}

return rubyRegexp;
return reCache.rubyRegexp;
}

@Override
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

require 'mkmf'
$CFLAGS << ' -Wall'
create_makefile('foo/foo')
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

require_relative '../../../../ruby/spec_helper'
require 'objspace'

8 changes: 8 additions & 0 deletions spec/truffle/truffle_formatter.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

require 'mspec/expectations/expectations'
require 'mspec/utils/ruby_name'
require 'mspec/runner/formatters/dotted'
8 changes: 4 additions & 4 deletions test/mri/excludes/TestSocket_UNIXSocket.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
exclude :test_addr, "needs investigation"
exclude :test_dgram_pair, "needs investigation"
exclude :test_epipe, "needs investigation"
exclude :test_fd_passing, "close_on_exec? not implemented"
exclude :test_fd_passing_race_condition, "needs investigation"
exclude :test_getpeereid, "needs investigation"
exclude :test_initialize, "needs investigation"
exclude :test_noname_recv_nonblock, "needs investigation"
exclude :test_noname_unpack_sockaddr_un, "needs investigation"
exclude :test_nul, "needs investigation"
exclude :test_socket_pair_with_block, "needs investigation"
exclude :test_too_long_path, "needs investigation"
exclude :test_unix_server_socket, "needs investigation"
exclude :test_unix_socket_pair_with_block, "needs investigation"
exclude :test_unix_socket_pair_with_block, "needs investigation"
exclude :test_cloexec, "needs investigation"
exclude :test_dgram_pair_sendrecvmsg_errno_set, "needs investigation"
8 changes: 8 additions & 0 deletions test/truffle/attachments-optimise.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

# -J-G:+TruffleCompilationExceptionsAreFatal

def foo
8 changes: 8 additions & 0 deletions test/truffle/cext/foo/ext/foo/extconf.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

require 'mkmf'
$CFLAGS << ' -Wall'
create_makefile('foo/foo')
8 changes: 8 additions & 0 deletions test/truffle/cext/inline.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

p Truffle::CExt.supported?

Truffle::CExt.inline %{
8 changes: 8 additions & 0 deletions test/truffle/cext/inline_capi.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

p Truffle::CExt.supported?

Truffle::CExt.inline %{
8 changes: 8 additions & 0 deletions test/truffle/cext/inline_flags.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

p Truffle::CExt.supported?

Truffle::CExt.inline %{
8 changes: 8 additions & 0 deletions test/truffle/cext/require.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

p Truffle::CExt.supported?

require 'foo/foo'
Loading

0 comments on commit 8478d61

Please sign in to comment.