Skip to content

Commit

Permalink
Fork off NewMarshalCache and use identity for symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed May 26, 2024
1 parent b6c4bc8 commit 81b000f
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 27 deletions.
12 changes: 0 additions & 12 deletions core/src/main/java/org/jruby/runtime/marshal/MarshalCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,23 +73,11 @@ public void writeLink(MarshalStream output, IRubyObject value) throws IOExceptio
output.writeInt(registeredIndex(value));
}

public void writeLink(NewMarshal output, NewMarshal.RubyOutputStream out, IRubyObject value) {
assert !(value instanceof RubySymbol) : "Use writeSymbolLink for symbols";

out.write('@');
output.writeInt(out, registeredIndex(value));
}

public void writeSymbolLink(MarshalStream output, ByteList sym) throws IOException {
output.write(';');
output.writeInt(registeredSymbolIndex(sym));
}

public void writeSymbolLink(NewMarshal output, NewMarshal.RubyOutputStream out, ByteList sym) {
out.write(';');
output.writeInt(out, registeredSymbolIndex(sym));
}

private int registeredIndex(IRubyObject value) {
return linkCache.get(value);
}
Expand Down
30 changes: 15 additions & 15 deletions core/src/main/java/org/jruby/runtime/marshal/NewMarshal.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@
* @author Anders
*/
public class NewMarshal {
private final MarshalCache cache;
private final NewMarshalCache cache;
private final int depthLimit;
private int depth = 0;

public NewMarshal(int depthLimit) {
this.cache = new MarshalCache();
this.cache = new NewMarshalCache();
this.depthLimit = depthLimit >= 0 ? depthLimit : Integer.MAX_VALUE;
}

Expand Down Expand Up @@ -154,7 +154,7 @@ public void registerLinkTarget(IRubyObject newObject) {
}
}

public void registerSymbol(ByteList sym) {
public void registerSymbol(RubySymbol sym) {
cache.registerSymbol(sym);
}

Expand All @@ -173,12 +173,12 @@ private static boolean isMarshalFixnum(RubyFixnum fixnum) {
return fixnum.getLongValue() <= RubyFixnum.MAX_MARSHAL_FIXNUM && fixnum.getLongValue() >= RubyFixnum.MIN_MARSHAL_FIXNUM;
}

private void writeAndRegisterSymbol(RubyOutputStream out, ByteList sym) {
private void writeAndRegisterSymbol(RubyOutputStream out, RubySymbol sym) {
if (cache.isSymbolRegistered(sym)) {
cache.writeSymbolLink(this, out, sym);
} else {
registerSymbol(sym);
dumpSymbol(out, sym);
dumpSymbol(out, sym.getBytes());
}
}

Expand Down Expand Up @@ -386,7 +386,7 @@ private void writeObjectData(ThreadContext context, RubyOutputStream out, IRubyO
RubyStruct.marshalTo((RubyStruct)value, this, context, out);
return;
case SYMBOL:
writeAndRegisterSymbol(out, ((RubySymbol) value).getBytes());
writeAndRegisterSymbol(out, ((RubySymbol) value));
return;
case TRUE:
out.write('T');
Expand Down Expand Up @@ -415,7 +415,7 @@ private void userNewCommon(ThreadContext context, RubyOutputStream out, IRubyObj
out.write(TYPE_USRMARSHAL);
final RubyClass klass = getMetaClass(value);
final Ruby runtime = context.runtime;
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, klass.getRealClass().getName()).getBytes());
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, klass.getRealClass().getName()));

IRubyObject marshaled;
if (entry != null) {
Expand Down Expand Up @@ -483,7 +483,7 @@ private void userCommon(ThreadContext context, RubyOutputStream out, IRubyObject

private void dumpUserdefBase(RubyOutputStream out, Ruby runtime, RubyClass klass, RubyString marshaled) {
out.write(TYPE_USERDEF);
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, klass.getRealClass().getName()).getBytes());
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, klass.getRealClass().getName()));
writeString(out, marshaled.getByteList());
}

Expand All @@ -498,7 +498,7 @@ public void writeUserClass(ThreadContext context, RubyOutputStream out, RubyClas
}

// w_symbol
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, type.getName()).getBytes());
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, type.getName()));
}

public void dumpVariables(ThreadContext context, RubyOutputStream out, IRubyObject value) {
Expand Down Expand Up @@ -538,21 +538,21 @@ public <T extends IRubyObject> void dumpVariables(ThreadContext context, RubyOut

private static void dumpVariable(NewMarshal marshal, ThreadContext context, RubyOutputStream out, String name, Object value) {
if (value instanceof IRubyObject) {
marshal.writeAndRegisterSymbol(out, RubySymbol.newSymbol(context.runtime, name).getBytes());
marshal.writeAndRegisterSymbol(out, RubySymbol.newSymbol(context.runtime, name));
marshal.dumpObject(context, out, (IRubyObject) value);
}
}

public void writeEncoding(ThreadContext context, RubyOutputStream out, Encoding encoding) {
Ruby runtime = context.runtime;
if (encoding == null || encoding == USASCIIEncoding.INSTANCE) {
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, SYMBOL_ENCODING_SPECIAL).getBytes());
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, SYMBOL_ENCODING_SPECIAL));
writeObjectData(context, out, runtime.getFalse());
} else if (encoding == UTF8Encoding.INSTANCE) {
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, SYMBOL_ENCODING_SPECIAL).getBytes());
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, SYMBOL_ENCODING_SPECIAL));
writeObjectData(context, out, runtime.getTrue());
} else {
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, SYMBOL_ENCODING).getBytes());
writeAndRegisterSymbol(out, RubySymbol.newSymbol(runtime, SYMBOL_ENCODING));
RubyString encodingString = new RubyString(runtime, runtime.getString(), encoding.getName());
writeObjectData(context, out, encodingString);
}
Expand Down Expand Up @@ -580,7 +580,7 @@ private RubyClass dumpExtended(ThreadContext context, RubyOutputStream out, Ruby
}
while(type.isIncluded()) {
out.write('e');
writeAndRegisterSymbol(out, RubySymbol.newSymbol(context.runtime, type.getOrigin().getName()).getBytes());
writeAndRegisterSymbol(out, RubySymbol.newSymbol(context.runtime, type.getOrigin().getName()));
type = type.getSuperClass();
}
return type;
Expand All @@ -593,7 +593,7 @@ public void dumpDefaultObjectHeader(ThreadContext context, RubyOutputStream out,
public void dumpDefaultObjectHeader(ThreadContext context, RubyOutputStream out, char tp, RubyClass type) {
dumpExtended(context, out, type);
out.write(tp);
writeAndRegisterSymbol(out, RubySymbol.newSymbol(context.runtime, getPathFromClass(context, type.getRealClass())).getBytes());
writeAndRegisterSymbol(out, RubySymbol.newSymbol(context.runtime, getPathFromClass(context, type.getRealClass())));
}

public void writeString(RubyOutputStream out, String value) {
Expand Down
84 changes: 84 additions & 0 deletions core/src/main/java/org/jruby/runtime/marshal/NewMarshalCache.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/***** BEGIN LICENSE BLOCK *****
* Version: EPL 2.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v20.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2002 Jan Arne Petersen <jpetersen@uni-bonn.de>
* Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
* Copyright (C) 2007 Ola Bini <ola.bini@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/

package org.jruby.runtime.marshal;

import org.jruby.RubySymbol;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.collections.HashMapInt;

import java.io.IOException;

public class NewMarshalCache {
private final HashMapInt<IRubyObject> linkCache = new HashMapInt<>(true);
private final HashMapInt<RubySymbol> symbolCache = new HashMapInt<>(true);

public boolean isRegistered(IRubyObject value) {
assert !(value instanceof RubySymbol) : "Use isSymbolRegistered for symbol links";

return linkCache.containsKey(value);
}

public boolean isSymbolRegistered(RubySymbol sym) {
return symbolCache.containsKey(sym);
}

public void register(IRubyObject value) {
assert !(value instanceof RubySymbol) : "Use registeredSymbolIndex for symbols";

linkCache.put(value, Integer.valueOf(linkCache.size()));
}

public void registerSymbol(RubySymbol sym) {
symbolCache.put(sym, symbolCache.size());
}

public void writeLink(NewMarshal output, NewMarshal.RubyOutputStream out, IRubyObject value) {
assert !(value instanceof RubySymbol) : "Use writeSymbolLink for symbols";

out.write('@');
output.writeInt(out, registeredIndex(value));
}

public void writeSymbolLink(NewMarshal output, NewMarshal.RubyOutputStream out, RubySymbol sym) {
out.write(';');
output.writeInt(out, registeredSymbolIndex(sym));
}

private int registeredIndex(IRubyObject value) {
return linkCache.get(value);
}

private int registeredSymbolIndex(RubySymbol sym) {
return symbolCache.get(sym);
}
}

0 comments on commit 81b000f

Please sign in to comment.