Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f0f2acc32bfe
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 487b2c806065
Choose a head ref
  • 3 commits
  • 6 files changed
  • 1 contributor

Commits on Mar 12, 2015

  1. Copy the full SHA
    4df660d View commit details
  2. Copy the full SHA
    cffe91e View commit details
  3. Copy the full SHA
    487b2c8 View commit details
6 changes: 3 additions & 3 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -97,7 +97,7 @@
import org.jruby.ir.IRManager;
import org.jruby.ir.interpreter.Interpreter;
import org.jruby.ir.persistence.IRReader;
import org.jruby.ir.persistence.IRReaderFile;
import org.jruby.ir.persistence.IRReaderStream;
import org.jruby.ir.persistence.util.IRFileExpert;
import org.jruby.javasupport.proxy.JavaProxyClassFactory;
import org.jruby.management.BeanManager;
@@ -2698,7 +2698,7 @@ public ParseResult parseFile(String file, InputStream in, DynamicScope scope, in

try {
// Get IR from .ir file
return IRReader.load(getIRManager(), new IRReaderFile(getIRManager(), IRFileExpert.getIRPersistedFile(file)));
return IRReader.load(getIRManager(), new IRReaderStream(getIRManager(), IRFileExpert.getIRPersistedFile(file)));
} catch (IOException e) {
// FIXME: What is something actually throws IOException
return parseFileAndGetAST(in, file, scope, lineNumber, false);
@@ -2719,7 +2719,7 @@ public ParseResult parseFileFromMain(String file, InputStream in, DynamicScope s
if (!RubyInstanceConfig.IR_READING) return parseFileFromMainAndGetAST(in, file, scope);

try {
return IRReader.load(getIRManager(), new IRReaderFile(getIRManager(), IRFileExpert.getIRPersistedFile(file)));
return IRReader.load(getIRManager(), new IRReaderStream(getIRManager(), IRFileExpert.getIRPersistedFile(file)));
} catch (IOException e) {
System.out.println(e);
e.printStackTrace();
Original file line number Diff line number Diff line change
@@ -21,9 +21,11 @@
import org.jruby.ir.operands.Variable;
import org.jruby.parser.StaticScope;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
@@ -38,30 +40,47 @@
*
* @author enebo
*/
public class IRReaderFile implements IRReaderDecoder, IRPersistenceValues {
private ByteBuffer buf;
public class IRReaderStream implements IRReaderDecoder, IRPersistenceValues {
private final ByteBuffer buf;
private final InstrDecoderMap instrDecoderMap;
private final OperandDecoderMap operandDecoderMap;
private final List<IRScope> scopes = new ArrayList<IRScope>();
private IRScope currentScope = null; // FIXME: This is not thread-safe and more than a little gross

public IRReaderFile(IRManager manager, File file) {
try {
byte[] bytes = new byte[(int)file.length()];
if (RubyInstanceConfig.IR_READING_DEBUG) System.out.println("READING IN " + bytes.length + " BYTES OF DATA FROM " + file);
ByteBuffer buffer = ByteBuffer.wrap(bytes);
FileInputStream fis = new FileInputStream(file);
FileChannel fc = fis.getChannel();
fc.read(buffer);
fis.close();
buf = ByteBuffer.wrap(bytes);
} catch (IOException ex) {
Logger.getLogger(IRReaderFile.class.getName()).log(Level.SEVERE, null, ex);
public IRReaderStream(IRManager manager, InputStream stream) {
ByteBuffer buf = readIntoBuffer(stream);

this.buf = buf;
this.instrDecoderMap = new InstrDecoderMap(this);
this.operandDecoderMap = new OperandDecoderMap(manager, this);
}

public IRReaderStream(IRManager manager, File file) {
ByteBuffer buf = null;
try (FileInputStream fis = new FileInputStream(file)){
buf = readIntoBuffer(fis);
} catch (IOException ex) {
Logger.getLogger(IRReaderStream.class.getName()).log(Level.SEVERE, null, ex);
}

instrDecoderMap = new InstrDecoderMap(this);
operandDecoderMap = new OperandDecoderMap(manager, this);
this.buf = buf;
this.instrDecoderMap = new InstrDecoderMap(this);
this.operandDecoderMap = new OperandDecoderMap(manager, this);
}

private ByteBuffer readIntoBuffer(InputStream stream) {
ByteBuffer buf = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes = new byte[8192];
int r = 0;
while ((r = stream.read(bytes)) > 0) baos.write(bytes, 0, r);
if (RubyInstanceConfig.IR_READING_DEBUG) System.out.println("READ IN " + baos.size() + " BYTES OF DATA FROM");
buf = ByteBuffer.wrap(baos.toByteArray());
} catch (IOException ex) {
Logger.getLogger(IRReaderStream.class.getName()).log(Level.SEVERE, null, ex);
}
return buf;
}

@Override
24 changes: 13 additions & 11 deletions core/src/main/java/org/jruby/ir/persistence/IRWriterStream.java
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
@@ -35,17 +36,21 @@ public class IRWriterStream implements IRWriterEncoder, IRPersistenceValues {
private final Map<IRScope, Integer> scopeInstructionOffsets = new HashMap<>();
// FIXME: Allocate direct and use one per thread?
private final ByteBuffer buf = ByteBuffer.allocate(TWO_MEGS);
private final File file;
private final OutputStream stream;
private final IRWriterAnalzer analyzer;

int headersOffset = -1;
int poolOffset = -1;

public IRWriterStream(File file) throws FileNotFoundException {
this.file = file;
public IRWriterStream(OutputStream stream) {
this.stream = stream;
this.analyzer = new IRWriterAnalzer();
}

public IRWriterStream(File file) throws FileNotFoundException {
this(new FileOutputStream(file));
}

/**
* Record current offset as the beginning of specified scopes list of instructions.
*/
@@ -236,17 +241,14 @@ public void startEncoding(IRScope script) {

@Override
public void endEncoding(IRScope script) {
FileOutputStream fos = null;

try {
fos = new FileOutputStream(file);
fos.write(ByteBuffer.allocate(4).putInt(headersOffset).array());
fos.write(ByteBuffer.allocate(4).putInt(poolOffset).array());
stream.write(ByteBuffer.allocate(4).putInt(headersOffset).array());
stream.write(ByteBuffer.allocate(4).putInt(poolOffset).array());
buf.flip();
fos.getChannel().write(buf);
fos.close();
stream.write(buf.array(), buf.position(), buf.limit());
stream.close();
} catch (IOException e) {
try { if (fos != null) fos.close(); } catch (IOException e1) {}
try { if (stream != null) stream.close(); } catch (IOException e1) {}
}
}
}
15 changes: 15 additions & 0 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
import org.jruby.internal.runtime.methods.InterpretedIRMethod;
import org.jruby.internal.runtime.methods.MixedModeIRMethod;
import org.jruby.internal.runtime.methods.UndefinedMethod;
import org.jruby.ir.IRManager;
import org.jruby.ir.IRMetaClassBody;
import org.jruby.ir.IRScope;
import org.jruby.ir.IRScopeType;
@@ -23,6 +24,8 @@
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Splat;
import org.jruby.ir.operands.UndefinedValue;
import org.jruby.ir.persistence.IRReader;
import org.jruby.ir.persistence.IRReaderStream;
import org.jruby.javasupport.JavaUtil;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.*;
@@ -38,6 +41,8 @@
import org.jruby.util.log.LoggerFactory;
import org.objectweb.asm.Type;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.invoke.MethodHandle;

public class IRRuntimeHelpers {
@@ -1323,4 +1328,14 @@ public static NormalCachingCallSite newNormalCachingCallSite(String name) {
public static VariableCachingCallSite newVariableCachingCallSite(String name) {
return new VariableCachingCallSite(name);
}

@JIT
public static IRScope decodeScopeFromBytes(Ruby runtime, byte[] scopeBytes) {
try {
return IRReader.load(runtime.getIRManager(), new IRReaderStream(runtime.getIRManager(), new ByteArrayInputStream(scopeBytes)));
} catch (IOException ioe) {
// should not happen for bytes
return null;
}
}
}
5 changes: 4 additions & 1 deletion core/src/main/ruby/jruby/jruby.rb
Original file line number Diff line number Diff line change
@@ -70,7 +70,10 @@ def compile_ir(content = nil, filename = (default_filename = true; '-'), extra_p
parse(content, filename, extra_position_info, &block)
end

org.jruby.ir.IRBuilder.build_root(runtime.getIRManager(), node).scope
scope = org.jruby.ir.IRBuilder.build_root(runtime.getIRManager(), node).scope
scope.top_level_binding_scope = node.scope

scope
end

# Parse and compile the given block or provided content, returning a new
66 changes: 47 additions & 19 deletions lib/ruby/stdlib/jruby/compiler.rb
Original file line number Diff line number Diff line change
@@ -7,7 +7,12 @@
module JRuby::Compiler
BAIS = java.io.ByteArrayInputStream
Mangler = org.jruby.util.JavaNameMangler
JVMVisitor = org.jruby.ir.targets.JVMVisitor
Opcodes = org.objectweb.asm.Opcodes rescue org.jruby.org.objectweb.asm.Opcodes
ClassWriter = org.objectweb.asm.ClassWriter rescue org.jruby.org.objectweb.asm.ClassWriter
SkinnyMethodAdapter = org.jruby.compiler.impl.SkinnyMethodAdapter
ByteArrayOutputStream = java.io.ByteArrayOutputStream
IRWriterStream = org.jruby.ir.persistence.IRWriterStream
IRWriter = org.jruby.ir.persistence.IRWriter
JavaFile = java.io.File
MethodSignatureNode = org.jruby.ast.java_signature.MethodSignatureNode
DEFAULT_PREFIX = ""
@@ -152,36 +157,59 @@ def compile_files_with_options(filenames, options = default_options)
puts "Compiling #{filename}" if options[:verbose]

scope = JRuby.compile_ir(source, filename)

visitor = JVMVisitor.new

bytes = visitor.compileToBytecode(scope)

class_bytes = String.from_java_bytes(bytes)
bytes = ByteArrayOutputStream.new
stream = IRWriterStream.new(bytes)
IRWriter.persist(stream, scope)
string = String.from_java_bytes(bytes.to_byte_array, 'BINARY')

cls = ClassWriter.new(ClassWriter::COMPUTE_MAXS | ClassWriter::COMPUTE_FRAMES)
cls.visit(
Opcodes::V1_7,
Opcodes::ACC_PUBLIC,
pathname.gsub(".", "/"),
nil,
"java/lang/Object",
nil
)
cls.visit_source filename, nil

main = SkinnyMethodAdapter.new(
cls,
Opcodes::ACC_PUBLIC | Opcodes::ACC_STATIC,
"main",
"([Ljava/lang/String;)V",
nil,
nil)
main.start
main.invokestatic("org/jruby/Ruby", "newInstance", "()Lorg/jruby/Ruby;")
main.astore(1)
main.aload(1)
main.aload(1)
main.ldc(string)
main.ldc("ISO-8859-1")
main.invokevirtual("java/lang/String", "getBytes", "(Ljava/lang/String;)[B")
main.invokestatic("org/jruby/ir/runtime/IRRuntimeHelpers", "decodeScopeFromBytes", "(Lorg/jruby/Ruby;[B)Lorg/jruby/ir/IRScope;")
main.invokevirtual("org/jruby/Ruby", "runInterpreter", "(Lorg/jruby/ParseResult;)Lorg/jruby/runtime/builtin/IRubyObject;")
main.voidreturn
main.end

# prepare target
class_filename = filename.sub(/(\.rb)?$/, '.class')
target_file = File.join(options[:target], class_filename)
target_dir = File.dirname(target_file)
FileUtils.mkdir_p(target_dir)

# write class
File.open(target_file, 'wb') do |f|
f.write(class_bytes)
end

if options[:handles]
puts "Generating direct handles for #{filename}"# if options[:verbose]

asmCompiler.write_invokers(options[:target])
f.write(cls.to_byte_array)
end
end

0
rescue Exception
puts "Failure during compilation of file #{filename}:\n#{$!}"
puts $!.backtrace
1
# rescue Exception
# puts "Failure during compilation of file #{filename}:\n#{$!}"
# puts $!.backtrace
# 1
ensure
file.close unless file.nil?
end