Created
December 2, 2025 02:52
-
-
Save headius/3f7a8ad94daf573de0afbfb243e452bb to your computer and use it in GitHub Desktop.
Removing ptr from StringIO, which is not compatible with dup'ing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/ext/java/org/jruby/ext/stringio/StringIO.java b/ext/java/org/jruby/ext/stringio/StringIO.java | |
| index f3ab1cf..9c58077 100644 | |
| --- a/ext/java/org/jruby/ext/stringio/StringIO.java | |
| +++ b/ext/java/org/jruby/ext/stringio/StringIO.java | |
| @@ -79,27 +79,17 @@ import static org.jruby.util.RubyStringBuilder.types; | |
| @JRubyClass(name="StringIO") | |
| @SuppressWarnings("serial") | |
| public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| - static class StringIOData { | |
| - /** | |
| - * ATTN: the value of internal might be reset to null | |
| - * (during StringIO.open with block), so watch out for that. | |
| - */ | |
| - RubyString string; | |
| - Encoding enc; | |
| - int pos; | |
| - int lineno; | |
| - int flags; | |
| - volatile Object owner; | |
| - } | |
| - private StringIOData ptr; | |
| - private byte flags; | |
| + private RubyString string; | |
| + private Encoding enc; | |
| + private int pos; | |
| + private int lineno; | |
| + private int flags; | |
| + private volatile Object owner; | |
| + private StringIO ptr; | |
| + | |
| + private byte strioFlags; | |
| // MRI: get_strio, StringIO macro | |
| - private StringIOData getPtr() { | |
| - // equivalent to rb_io_taint_check without tainting | |
| - checkFrozen(); | |
| - return ptr; | |
| - } | |
| private static final String | |
| STRINGIO_VERSION = "3.1.10"; | |
| @@ -108,7 +98,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| private static final byte STRIO_WRITABLE = 2; | |
| private static final byte STRIO_READWRITE = (STRIO_READABLE | STRIO_WRITABLE); | |
| - private static final AtomicReferenceFieldUpdater<StringIOData, Object> LOCKED_UPDATER = AtomicReferenceFieldUpdater.newUpdater(StringIOData.class, Object.class, "owner"); | |
| + private static final AtomicReferenceFieldUpdater<StringIO, Object> LOCKED_UPDATER = AtomicReferenceFieldUpdater.newUpdater(StringIO.class, Object.class, "owner"); | |
| private static final ThreadLocal<Object> VMODE_VPERM_TL = ThreadLocal.withInitial(() -> EncodingUtils.vmodeVperm(null, null)); | |
| private static final ThreadLocal<int[]> FMODE_TL = ThreadLocal.withInitial(() -> new int[]{0}); | |
| @@ -143,13 +133,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| // mri: get_enc | |
| public Encoding getEncoding() { | |
| - StringIOData ptr = this.getPtr(); | |
| - Encoding enc = ptr.enc; | |
| + checkFrozen(); | |
| + Encoding enc = this.enc; | |
| if (enc != null) { | |
| return enc; | |
| } | |
| - RubyString string = ptr.string; | |
| + RubyString string = this.string; | |
| if (string != null) { | |
| return string.getEncoding(); | |
| } | |
| @@ -158,7 +148,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| public void setEncoding(Encoding enc) { | |
| - getPtr().enc = enc; | |
| + checkFrozen(); | |
| + StringIO stringIO = ptr; | |
| + stringIO.enc = enc; | |
| } | |
| @JRubyMethod(name = "new", rest = true, meta = true) | |
| @@ -258,7 +250,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| try { | |
| val = block.yield(context, strio); | |
| } finally { | |
| - strio.getPtr().string = null; | |
| + strio.checkFrozen(); | |
| + strio.ptr.string = null; | |
| strio.flags &= ~STRIO_READWRITE; | |
| } | |
| } | |
| @@ -272,8 +265,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod(visibility = PRIVATE, keywords = true) | |
| public IRubyObject initialize(ThreadContext context) { | |
| - if (getPtr() == null) { | |
| - ptr = new StringIOData(); | |
| + checkFrozen(); | |
| + if (ptr == null) { | |
| + ptr = this; | |
| } | |
| // does not dispatch quite right and is not really necessary for us | |
| @@ -284,8 +278,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod(visibility = PRIVATE, keywords = true) | |
| public IRubyObject initialize(ThreadContext context, IRubyObject arg0) { | |
| - if (getPtr() == null) { | |
| - ptr = new StringIOData(); | |
| + checkFrozen(); | |
| + if (ptr == null) { | |
| + ptr = this; | |
| } | |
| // does not dispatch quite right and is not really necessary for us | |
| @@ -296,8 +291,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod(visibility = PRIVATE, keywords = true) | |
| public IRubyObject initialize(ThreadContext context, IRubyObject arg0, IRubyObject arg1) { | |
| - if (getPtr() == null) { | |
| - ptr = new StringIOData(); | |
| + checkFrozen(); | |
| + if (ptr == null) { | |
| + ptr = this; | |
| } | |
| // does not dispatch quite right and is not really necessary for us | |
| @@ -308,8 +304,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod(visibility = PRIVATE, keywords = true) | |
| public IRubyObject initialize(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { | |
| - if (getPtr() == null) { | |
| - ptr = new StringIOData(); | |
| + checkFrozen(); | |
| + if (ptr == null) { | |
| + ptr = this; | |
| } | |
| // does not dispatch quite right and is not really necessary for us | |
| @@ -324,7 +321,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| IRubyObject string = context.nil; | |
| IRubyObject vmode = context.nil; | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| @@ -362,7 +359,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| // switch to per-use oflags if it is ever used in the future | |
| EncodingUtils.extractModeEncoding(context, ioEncodable, vmodeAndVpermP, maybeOptions, OFLAGS_UNUSED, fmode); | |
| - ptr.flags = fmode[0]; | |
| + this.flags = fmode[0]; | |
| vmode = EncodingUtils.vmode(vmodeAndVpermP); | |
| // clear shared vmodeVperm | |
| @@ -380,25 +377,25 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| } else { | |
| if (vmode.isNil()) { | |
| - ptr.flags |= OpenFile.WRITABLE; | |
| + this.flags = this.flags | OpenFile.WRITABLE; | |
| } | |
| } | |
| if (!string.isNil() && (ptr.flags & OpenFile.TRUNC) != 0) { | |
| ((RubyString) string).clear(); | |
| } | |
| if (string instanceof RubyString) { | |
| - ptr.string = (RubyString) string; | |
| + this.string = (RubyString) string; | |
| } | |
| if (argc == 1 && !string.isNil()) { | |
| - ptr.enc = ((RubyString) string).getEncoding(); | |
| + this.enc = ((RubyString) string).getEncoding(); | |
| } else { | |
| - ptr.enc = ioEncodable.enc; | |
| + this.enc = ioEncodable.enc; | |
| } | |
| - ptr.pos = 0; | |
| - ptr.lineno = 0; | |
| + this.pos = 0; | |
| + this.lineno = 0; | |
| if ((ptr.flags & OpenFile.SETENC_BY_BOM) != 0) set_encoding_by_bom(context); | |
| // funky way of shifting readwrite flags into object flags | |
| - flags |= (ptr.flags & OpenFile.READWRITE) * (STRIO_READABLE / OpenFile.READABLE); | |
| + strioFlags |= (ptr.flags & OpenFile.READWRITE) * (STRIO_READABLE / OpenFile.READABLE); | |
| } finally { | |
| if (locked) unlock(ptr); | |
| } | |
| @@ -412,17 +409,23 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| if (this == otherIO) return this; | |
| - ptr = otherIO.getPtr(); | |
| - flags = (byte) (flags & ~STRIO_READWRITE | otherIO.flags & STRIO_READWRITE); | |
| + otherIO.checkFrozen(); | |
| + this.string = otherIO.string; | |
| + this.enc = otherIO.enc; | |
| + this.pos = otherIO.pos; | |
| + this.lineno = otherIO.lineno; | |
| + this.flags = otherIO.flags; | |
| + this.ptr = this; | |
| + strioFlags = (byte) (strioFlags & ~STRIO_READWRITE | otherIO.strioFlags & STRIO_READWRITE); | |
| return this; | |
| } | |
| @JRubyMethod | |
| public IRubyObject binmode(ThreadContext context) { | |
| - StringIOData ptr = this.getPtr(); | |
| - ptr.enc = EncodingUtils.ascii8bitEncoding(context.runtime); | |
| - if (writable()) ptr.string.setEncoding(ptr.enc); | |
| + checkFrozen(); | |
| + this.enc = EncodingUtils.ascii8bitEncoding(context.runtime); | |
| + if (writable()) this.string.setEncoding(ptr.enc); | |
| return this; | |
| } | |
| @@ -464,7 +467,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| if ( closed() ) return context.nil; | |
| // NOTE: This is 2.0 behavior to allow dup'ed StringIO to remain open when original is closed | |
| - flags &= ~STRIO_READWRITE; | |
| + strioFlags &= ~STRIO_READWRITE; | |
| return context.nil; | |
| } | |
| @@ -479,12 +482,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| public IRubyObject close_read(ThreadContext context) { | |
| // ~ checkReadable() : | |
| checkInitialized(); | |
| - if ( (getPtr().flags & OpenFile.READABLE) == 0 ) { | |
| + checkFrozen(); | |
| + if ( (ptr.flags & OpenFile.READABLE) == 0 ) { | |
| throw context.runtime.newIOError("not opened for reading"); | |
| } | |
| - int flags = this.flags; | |
| + int strioFlags = this.strioFlags; | |
| if ( ( flags & STRIO_READABLE ) != 0 ) { | |
| - this.flags = (byte) (flags & ~STRIO_READABLE); | |
| + this.strioFlags = (byte) (strioFlags & ~STRIO_READABLE); | |
| } | |
| return context.nil; | |
| } | |
| @@ -499,12 +503,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| public IRubyObject close_write(ThreadContext context) { | |
| // ~ checkWritable() : | |
| checkInitialized(); | |
| - if ( (getPtr().flags & OpenFile.WRITABLE) == 0 ) { | |
| + checkFrozen(); | |
| + if ( (ptr.flags & OpenFile.WRITABLE) == 0 ) { | |
| throw context.runtime.newIOError("not opened for writing"); | |
| } | |
| - int flags = this.flags; | |
| + int strioFlags = this.strioFlags; | |
| if ( ( flags & STRIO_WRITABLE ) != 0 ) { | |
| - this.flags = (byte) (flags & ~STRIO_WRITABLE); | |
| + this.strioFlags = (byte) (strioFlags & ~STRIO_WRITABLE); | |
| } | |
| return context.nil; | |
| } | |
| @@ -616,11 +621,11 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| if (!block.isGiven()) return enumeratorize(runtime, this, "each_byte"); | |
| checkReadable(); | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - ByteList bytes = ptr.string.getByteList(); | |
| + ByteList bytes = this.string.getByteList(); | |
| // Check the length every iteration, since | |
| // the block can modify this string. | |
| @@ -650,7 +655,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod(name = {"eof", "eof?"}) | |
| public IRubyObject eof(ThreadContext context) { | |
| checkReadable(); | |
| - StringIOData ptr = getPtr(); | |
| + checkFrozen(); | |
| if (!isEndOfString()) return context.fals; | |
| return context.tru; | |
| } | |
| @@ -660,8 +665,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| private boolean isOutside(int pos) { | |
| - StringIOData ptr = getPtr(); | |
| - return ptr.string == null || pos >= ptr.string.size(); | |
| + checkFrozen(); | |
| + return this.string == null || pos >= this.string.size(); | |
| } | |
| @JRubyMethod(name = "getc") | |
| @@ -670,15 +675,15 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| if (isEndOfString()) return context.nil; | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - int start = ptr.pos; | |
| - RubyString string = ptr.string; | |
| + int start = this.pos; | |
| + RubyString string = this.string; | |
| int total = 1 + StringSupport.bytesToFixBrokenTrailingCharacter(string.getByteList(), start + 1); | |
| - ptr.pos += total; | |
| + this.pos = this.pos + total; | |
| return context.runtime.newString(string.getByteList().makeShared(start, total)); | |
| } finally { | |
| @@ -693,10 +698,10 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| if (isEndOfString()) return context.nil; | |
| int c; | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - c = ptr.string.getByteList().get(ptr.pos++) & 0xFF; | |
| + c = this.string.getByteList().get(ptr.pos++) & 0xFF; | |
| } finally { | |
| if (locked) unlock(ptr); | |
| } | |
| @@ -707,9 +712,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| // MRI: strio_substr | |
| // must be called under lock | |
| private RubyString strioSubstr(Ruby runtime, int pos, int len, Encoding enc) { | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| - final RubyString string = ptr.string; | |
| + final RubyString string = this.string; | |
| int rlen = string.size() - pos; | |
| if (len > rlen) len = rlen; | |
| @@ -758,25 +763,29 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod(name = "gets", writes = FrameField.LASTLINE) | |
| public IRubyObject gets(ThreadContext context) { | |
| - if (getPtr().string == null) return context.nil; | |
| + checkFrozen(); | |
| + if (ptr.string == null) return context.nil; | |
| return Getline.getlineCall(context, GETLINE, this, getEncoding()); | |
| } | |
| @JRubyMethod(name = "gets", writes = FrameField.LASTLINE) | |
| public IRubyObject gets(ThreadContext context, IRubyObject arg0) { | |
| - if (getPtr().string == null) return context.nil; | |
| + checkFrozen(); | |
| + if (ptr.string == null) return context.nil; | |
| return Getline.getlineCall(context, GETLINE, this, getEncoding(), arg0); | |
| } | |
| @JRubyMethod(name = "gets", writes = FrameField.LASTLINE) | |
| public IRubyObject gets(ThreadContext context, IRubyObject arg0, IRubyObject arg1) { | |
| - if (getPtr().string == null) return context.nil; | |
| + checkFrozen(); | |
| + if (ptr.string == null) return context.nil; | |
| return Getline.getlineCall(context, GETLINE, this, getEncoding(), arg0, arg1); | |
| } | |
| @JRubyMethod(name = "gets", writes = FrameField.LASTLINE) | |
| public IRubyObject gets(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { | |
| - if (getPtr().string == null) return context.nil; | |
| + checkFrozen(); | |
| + if (ptr.string == null) return context.nil; | |
| return Getline.getlineCall(context, GETLINE, this, getEncoding(), arg0, arg1, arg2); | |
| } | |
| @@ -800,7 +809,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| self.checkReadable(); | |
| if (limit == 0) { | |
| - if (self.getPtr().string == null) return context.nil; | |
| + self.checkFrozen(); | |
| + if (self.ptr.string == null) return context.nil; | |
| return RubyString.newEmptyString(context.runtime, self.getEncoding()); | |
| } | |
| @@ -816,8 +826,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| private static final Getline.Callback<StringIO, StringIO> GETLINE_YIELD = (context, self, rs, limit, chomp, block) -> { | |
| IRubyObject line; | |
| - StringIOData ptr = self.getPtr(); | |
| - if (ptr.string == null || ptr.pos > ptr.string.size()) { | |
| + self.checkFrozen(); | |
| + if (self.string == null || self.pos > self.string.size()) { | |
| return self; | |
| } | |
| @@ -839,8 +849,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| RubyArray<IRubyObject> ary = (RubyArray<IRubyObject>) context.runtime.newArray(); | |
| IRubyObject line; | |
| - StringIOData ptr = self.getPtr(); | |
| - if (ptr.string == null || ptr.pos > ptr.string.size()) { | |
| + self.checkFrozen(); | |
| + if (self.string == null || self.pos > self.string.size()) { | |
| return null; | |
| } | |
| @@ -871,15 +881,15 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| return context.nil; | |
| } | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| Encoding enc = getEncoding(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - final ByteList string = ptr.string.getByteList(); | |
| + final ByteList string = this.string.getByteList(); | |
| final byte[] stringBytes = string.getUnsafeBytes(); | |
| int begin = string.getBegin(); | |
| - int pos = ptr.pos; | |
| + int pos = this.pos; | |
| int s = begin + pos; | |
| int e = begin + string.getRealSize(); | |
| int p; | |
| @@ -955,8 +965,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| str = strioSubstr(runtime, pos, e - s - w, enc); | |
| } | |
| - ptr.pos = e - begin; | |
| - ptr.lineno++; | |
| + this.pos = e - begin; | |
| + this.lineno = this.lineno + 1; | |
| } finally { | |
| if (locked) unlock(ptr); | |
| } | |
| @@ -975,19 +985,24 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod(name = {"length", "size"}) | |
| public IRubyObject length(ThreadContext context) { | |
| checkInitialized(); | |
| - RubyString myString = getPtr().string; | |
| + checkFrozen(); | |
| + RubyString myString = this.string; | |
| if (myString == null) return RubyFixnum.zero(context.runtime); | |
| return getRuntime().newFixnum(myString.size()); | |
| } | |
| @JRubyMethod(name = "lineno") | |
| public IRubyObject lineno(ThreadContext context) { | |
| - return context.runtime.newFixnum(getPtr().lineno); | |
| + checkFrozen(); | |
| + return context.runtime.newFixnum(ptr.lineno); | |
| } | |
| @JRubyMethod(name = "lineno=", required = 1) | |
| public IRubyObject set_lineno(ThreadContext context, IRubyObject arg) { | |
| - getPtr().lineno = RubyNumeric.fix2int(arg); | |
| + checkFrozen(); | |
| + StringIO stringIO = ptr; | |
| + int lineno1 = RubyNumeric.fix2int(arg); | |
| + stringIO.lineno = lineno1; | |
| return context.nil; | |
| } | |
| @@ -996,7 +1011,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| public IRubyObject pos(ThreadContext context) { | |
| checkInitialized(); | |
| - return context.runtime.newFixnum(getPtr().pos); | |
| + checkFrozen(); | |
| + return context.runtime.newFixnum(ptr.pos); | |
| } | |
| @JRubyMethod(name = "pos=", required = 1) | |
| @@ -1009,17 +1025,19 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| if (p > Integer.MAX_VALUE) throw getRuntime().newArgumentError("JRuby does not support StringIO larger than " + Integer.MAX_VALUE + " bytes"); | |
| - getPtr().pos = (int)p; | |
| + checkFrozen(); | |
| + StringIO stringIO = ptr; | |
| + stringIO.pos = (int)p; | |
| return arg; | |
| } | |
| private void strioExtend(ThreadContext context, int pos, int len) { | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - RubyString string = ptr.string; | |
| + RubyString string = this.string; | |
| final int olen = string.size(); | |
| long newSize = (long) pos + len; | |
| if (newSize > Integer.MAX_VALUE) { | |
| @@ -1054,12 +1072,14 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| checkModifiable(); | |
| if (ch instanceof RubyString) { | |
| - if (getPtr().string == null) return context.nil; | |
| + checkFrozen(); | |
| + if (ptr.string == null) return context.nil; | |
| str = substrString((RubyString) ch, str, runtime); | |
| } | |
| else { | |
| byte c = RubyNumeric.num2chr(ch); | |
| - if (getPtr().string == null) return context.nil; | |
| + checkFrozen(); | |
| + if (ptr.string == null) return context.nil; | |
| str = RubyString.newString(runtime, new byte[]{c}); | |
| } | |
| write(context, str); | |
| @@ -1091,8 +1111,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| IRubyObject str = context.nil; | |
| boolean binary = false; | |
| - StringIOData ptr = this.getPtr(); | |
| - int pos = ptr.pos; | |
| + checkFrozen(); | |
| + int pos = this.pos; | |
| boolean locked = lock(context, ptr); | |
| try { | |
| @@ -1120,11 +1140,11 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| break; | |
| } | |
| case 0: | |
| - RubyString myString = ptr.string; | |
| + RubyString myString = this.string; | |
| if (myString == null) { | |
| return context.nil; | |
| } | |
| - len = ptr.string.size(); | |
| + len = this.string.size(); | |
| if (len <= pos) { | |
| Encoding enc = binary ? ASCIIEncoding.INSTANCE : getEncoding(); | |
| if (str.isNil()) { | |
| @@ -1147,7 +1167,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| string = strioSubstr(runtime, pos, len, enc); | |
| } else { | |
| string = (RubyString) str; | |
| - RubyString myString = ptr.string; | |
| + RubyString myString = this.string; | |
| int rest = myString.size() - pos; | |
| if (len > rest) len = rest; | |
| string.resize(len); | |
| @@ -1161,7 +1181,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| } | |
| - ptr.pos += string.size(); | |
| + int pos1 = this.pos + string.size(); | |
| + this.pos = pos1; | |
| return string; | |
| } finally { | |
| @@ -1187,7 +1208,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @SuppressWarnings("fallthrough") | |
| private RubyString preadCommon(ThreadContext context, int argc, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { | |
| IRubyObject str = context.nil; | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| Ruby runtime = context.runtime; | |
| int offset; | |
| final RubyString string; | |
| @@ -1238,7 +1259,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| string = (RubyString) str; | |
| - RubyString myString = ptr.string; | |
| + RubyString myString = this.string; | |
| int rest = myString.size() - offset; | |
| if (len > rest) len = rest; | |
| string.resize(len); | |
| @@ -1337,12 +1358,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| public IRubyObject rewind(ThreadContext context) { | |
| checkInitialized(); | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - ptr.pos = 0; | |
| - ptr.lineno = 0; | |
| + this.pos = 0; | |
| + this.lineno = 0; | |
| } finally { | |
| if (locked) unlock(ptr); | |
| } | |
| @@ -1370,7 +1391,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| whence = arg1; | |
| } | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| checkOpen(); | |
| @@ -1380,13 +1401,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| case 0: | |
| break; | |
| case 1: | |
| - offset += ptr.pos; | |
| + offset += this.pos; | |
| break; | |
| case 2: | |
| if (ptr.string == null) { | |
| offset += 0; | |
| } else { | |
| - offset += ptr.string.size(); | |
| + offset += this.string.size(); | |
| } | |
| break; | |
| default: | |
| @@ -1395,7 +1416,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| if (offset < 0) throw runtime.newErrnoEINVALError("invalid seek value"); | |
| - ptr.pos = offset; | |
| + this.pos = offset; | |
| } finally { | |
| if (locked) unlock(ptr); | |
| } | |
| @@ -1406,16 +1427,18 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod(name = "string=", required = 1) | |
| public IRubyObject set_string(ThreadContext context, IRubyObject arg) { | |
| checkFrozen(); | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - ptr.flags &= ~OpenFile.READWRITE; | |
| + int flags2 = this.flags & ~OpenFile.READWRITE; | |
| + this.flags = flags2; | |
| RubyString str = arg.convertToString(); | |
| - ptr.flags = str.isFrozen() ? OpenFile.READABLE : OpenFile.READWRITE; | |
| - ptr.pos = 0; | |
| - ptr.lineno = 0; | |
| - return ptr.string = str; | |
| + int flags1 = str.isFrozen() ? OpenFile.READABLE : OpenFile.READWRITE; | |
| + this.flags = flags1; | |
| + this.pos = 0; | |
| + this.lineno = 0; | |
| + return this.string = str; | |
| } finally { | |
| if (locked) unlock(ptr); | |
| } | |
| @@ -1423,7 +1446,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod(name = "string") | |
| public IRubyObject string(ThreadContext context) { | |
| - RubyString string = getPtr().string; | |
| + checkFrozen(); | |
| + RubyString string = this.string; | |
| if (string == null) return context.nil; | |
| return string; | |
| @@ -1440,8 +1464,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| checkWritable(); | |
| int l = RubyFixnum.fix2int(len); | |
| - StringIOData ptr = this.getPtr(); | |
| - RubyString string = ptr.string; | |
| + checkFrozen(); | |
| + RubyString string = this.string; | |
| boolean locked = lock(context, ptr); | |
| try { | |
| @@ -1472,7 +1496,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| checkModifiable(); | |
| checkReadable(); | |
| - if (getPtr().string == null) return context.nil; | |
| + checkFrozen(); | |
| + if (ptr.string == null) return context.nil; | |
| if (arg.isNil()) return arg; | |
| if (arg instanceof RubyInteger) { | |
| @@ -1499,13 +1524,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| private void ungetbyteCommon(ThreadContext context, int c) { | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - RubyString string = ptr.string; | |
| + RubyString string = this.string; | |
| string.modify(); | |
| - ptr.pos--; | |
| + this.pos = this.pos - 1; | |
| ByteList bytes = string.getByteList(); | |
| @@ -1513,7 +1538,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| if (ptr.pos == -1) { | |
| bytes.prepend((byte) c); | |
| - ptr.pos = 0; | |
| + this.pos = 0; | |
| } else { | |
| bytes.set(ptr.pos, c); | |
| } | |
| @@ -1530,12 +1555,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| private void ungetbyteCommon(ThreadContext context, byte[] ungetBytes, int cp, int cl) { | |
| if (cl == 0) return; | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - int pos = ptr.pos, len, rest; | |
| - RubyString str = ptr.string; | |
| + int pos = this.pos, len, rest; | |
| + RubyString str = this.string; | |
| ByteList strBytelist; | |
| byte[] strBytes; | |
| int s; | |
| @@ -1571,7 +1596,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } else { | |
| System.arraycopy(strBytes, s, strBytes, s + pos, cl); | |
| } | |
| - ptr.pos = pos; | |
| + this.pos = pos; | |
| } finally { | |
| if (locked) unlock(ptr); | |
| } | |
| @@ -1585,7 +1610,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| if (arg.isNil()) return arg; | |
| checkModifiable(); | |
| - if (getPtr().string == null) return context.nil; | |
| + checkFrozen(); | |
| + if (ptr.string == null) return context.nil; | |
| if (arg instanceof RubyInteger) { | |
| ungetbyteCommon(context, ((RubyInteger) ((RubyInteger) arg).op_mod(context, 256)).getIntValue()); | |
| @@ -1699,7 +1725,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| RubyString str = arg.asString(); | |
| int len, olen; | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| @@ -1718,12 +1744,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| len = str.size(); | |
| if (len == 0) return 0; | |
| checkModifiable(); | |
| - RubyString myString = ptr.string; | |
| + RubyString myString = this.string; | |
| olen = myString.size(); | |
| if ((ptr.flags & OpenFile.APPEND) != 0) { | |
| - ptr.pos = olen; | |
| + this.pos = olen; | |
| } | |
| - int pos = ptr.pos; | |
| + int pos = this.pos; | |
| if (pos == olen) { | |
| if (enc == EncodingUtils.ascii8bitEncoding(runtime) || encStr == EncodingUtils.ascii8bitEncoding(runtime)) { | |
| EncodingUtils.encStrBufCat(runtime, myString, strByteList, enc); | |
| @@ -1736,7 +1762,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| ByteList ptrByteList = myString.getByteList(); | |
| System.arraycopy(strByteList.getUnsafeBytes(), strByteList.getBegin(), ptrByteList.getUnsafeBytes(), ptrByteList.begin() + pos, len); | |
| } | |
| - ptr.pos = pos + len; | |
| + this.pos = pos + len; | |
| } finally { | |
| if (locked) unlock(ptr); | |
| } | |
| @@ -1810,14 +1836,14 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| } | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| - ptr.enc = enc; | |
| + this.enc = enc; | |
| // in read-only mode, StringIO#set_encoding no longer sets the encoding | |
| - RubyString string = ptr.string; | |
| + RubyString string = this.string; | |
| if (string != null && writable() && string.getEncoding() != enc) { | |
| string.modify(); | |
| string.setEncoding(enc); | |
| @@ -1846,22 +1872,22 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| @JRubyMethod | |
| public IRubyObject set_encoding_by_bom(ThreadContext context) { | |
| - StringIOData ptr = getPtr(); | |
| + checkFrozen(); | |
| if (setEncodingByBOM(context, ptr) == null) return context.nil; | |
| return context.runtime.getEncodingService().convertEncodingToRubyEncoding(ptr.enc); | |
| } | |
| - private Encoding setEncodingByBOM(ThreadContext context, StringIOData ptr) { | |
| - Encoding enc = detectBOM(context, ptr.string, (ctx, enc2, bomlen) -> { | |
| - ptr.pos = bomlen; | |
| + private Encoding setEncodingByBOM(ThreadContext context, StringIO ptr) { | |
| + Encoding enc = detectBOM(context, this.string, (ctx, enc2, bomlen) -> { | |
| + this.pos = bomlen; | |
| if (writable()) { | |
| - ptr.string.setEncoding(enc2); | |
| + this.string.setEncoding(enc2); | |
| } | |
| return enc2; | |
| }); | |
| - ptr.enc = enc; | |
| + this.enc = enc; | |
| return enc; | |
| } | |
| @@ -1929,12 +1955,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| checkReadable(); | |
| - StringIOData ptr = this.getPtr(); | |
| + checkFrozen(); | |
| boolean locked = lock(context, ptr); | |
| try { | |
| final Encoding enc = getEncoding(); | |
| - RubyString myString = ptr.string; | |
| + RubyString myString = this.string; | |
| final ByteList string = myString.getByteList(); | |
| final byte[] stringBytes = string.getUnsafeBytes(); | |
| int begin = string.getBegin(); | |
| @@ -1942,12 +1968,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| // check readability for each loop, since it could get closed | |
| checkReadable(); | |
| - int pos = ptr.pos; | |
| + int pos = this.pos; | |
| if (pos >= string.realSize()) return this; | |
| int c = StringSupport.codePoint(runtime, enc, stringBytes, begin + pos, stringBytes.length); | |
| int n = StringSupport.codeLength(enc, c); | |
| - ptr.pos = pos + n; | |
| + this.pos = pos + n; | |
| block.yield(context, runtime.newFixnum(c)); | |
| } | |
| } finally { | |
| @@ -2178,18 +2204,21 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| private boolean readable() { | |
| - return (flags & STRIO_READABLE) != 0 | |
| - && (getPtr().flags & OpenFile.READABLE) != 0; | |
| + if ((strioFlags & STRIO_READABLE) == 0) return false; | |
| + checkFrozen(); | |
| + return (ptr.flags & OpenFile.READABLE) != 0; | |
| } | |
| private boolean writable() { | |
| - return (flags & STRIO_WRITABLE) != 0 | |
| - && (getPtr().flags & OpenFile.WRITABLE) != 0; | |
| + if ((strioFlags & STRIO_WRITABLE) == 0) return false; | |
| + checkFrozen(); | |
| + return (ptr.flags & OpenFile.WRITABLE) != 0; | |
| } | |
| private boolean closed() { | |
| - return !((flags & STRIO_READWRITE) != 0 | |
| - && (getPtr().flags & OpenFile.READWRITE) != 0); | |
| + checkFrozen(); | |
| + return !((strioFlags & STRIO_READWRITE) != 0 | |
| + && (ptr.flags & OpenFile.READWRITE) != 0); | |
| } | |
| /* rb: readable */ | |
| @@ -2211,7 +2240,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| private void checkModifiable() { | |
| - final RubyString string = getPtr().string; | |
| + checkFrozen(); | |
| + final RubyString string = this.string; | |
| if (string == null) { | |
| /* Null device StringIO */ | |
| } else if (string.isFrozen()) { | |
| @@ -2222,7 +2252,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| private void checkInitialized() { | |
| - if (getPtr() == null) { | |
| + checkFrozen(); | |
| + if (ptr == null) { | |
| throw getRuntime().newIOError("uninitialized stream"); | |
| } | |
| } | |
| @@ -2233,13 +2264,14 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType { | |
| } | |
| } | |
| - private static boolean lock(ThreadContext context, StringIOData ptr) { | |
| + private static boolean lock(ThreadContext context, StringIO ptr) { | |
| if (ptr.owner == context) return false; | |
| while (!LOCKED_UPDATER.compareAndSet(ptr, null, context)); // lock | |
| return true; | |
| } | |
| - private static void unlock(StringIOData ptr) { | |
| + private static void unlock(StringIO ptr) { | |
| ptr.owner = null; // unlock | |
| } | |
| + | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment