Skip to content

Commit

Permalink
Make __FILE__ dynamic for precompiled IR. See #3270.
Browse files Browse the repository at this point in the history
I opted to make the Filename operand load the filename set into
the containing scope, which makes it simple to set it in a single
place when loading IR. Unsure whether this is the best approach or
not.
headius committed Oct 18, 2015
1 parent 7f40a1d commit f37539a
Showing 10 changed files with 64 additions and 12 deletions.
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -544,6 +544,7 @@ public void runFromMain(InputStream inputStream, String filename) {
if (script == null) {
throw new MainExitException(1, "error: .class file specified is not a compiled JRuby script");
}
script.setFileName(filename);
runInterpreter(script);
return;
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
@@ -3308,7 +3308,7 @@ public Operand buildSplat(SplatNode splatNode) {

public Operand buildStr(StrNode strNode) {
if (strNode instanceof FileNode) {
return new Filename(strNode.getValue());
return new Filename();
}
return copyAndReturnValue(new StringLiteral(strNode.getValue(), strNode.getCodeRange()));
}
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/ir/IREvalScript.java
Original file line number Diff line number Diff line change
@@ -87,6 +87,11 @@ public boolean isFlipScope() {
return true;
}

@Override
public void setFileName(String fileName) {
this.fileName = fileName;
}

@Override
public String getFileName() {
return fileName;
10 changes: 5 additions & 5 deletions core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
@@ -341,12 +341,12 @@ public String getName() {
this.name = name;
}

public String getFileName() {
IRScope current = this;

for (; current != null && !current.isScriptScope(); current = current.getLexicalParent()) {}
public void setFileName(String filename) {
getTopLevelScope().setFileName(filename);
}

return current.getFileName();
public String getFileName() {
return getTopLevelScope().getFileName();
}

public int getLineNumber() {
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/ir/IRScriptBody.java
Original file line number Diff line number Diff line change
@@ -72,6 +72,11 @@ public boolean isScriptScope() {
return true;
}

@Override
public void setFileName(String fileName) {
this.fileName = fileName;
}

@Override
public String getFileName() {
return fileName;
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/ir/IRVisitor.java
Original file line number Diff line number Diff line change
@@ -153,6 +153,7 @@ private void error(Object object) {
public void Complex(Complex complex) { error(complex); }
public void CurrentScope(CurrentScope currentscope) { error(currentscope); }
public void DynamicSymbol(DynamicSymbol dynamicsymbol) { error(dynamicsymbol); }
public void Filename(Filename filename) { error(filename); }
public void Fixnum(Fixnum fixnum) { error(fixnum); }
public void FrozenString(FrozenString frozen) { error(frozen); }
public void UnboxedFixnum(UnboxedFixnum fixnum) { error(fixnum); }
37 changes: 32 additions & 5 deletions core/src/main/java/org/jruby/ir/operands/Filename.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package org.jruby.ir.operands;

import org.jruby.ir.IRVisitor;
import org.jruby.ir.persistence.IRReaderDecoder;
import org.jruby.ir.persistence.IRWriterEncoder;
import org.jruby.util.ByteList;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

import java.util.List;

/**
* Represents the script's __FILE__. Isolated as its own operand because we need to be able to replace it when loading
* persisted IR from a location different than original script.
*/
public class Filename extends StringLiteral {
public Filename(ByteList filename) {
super(filename, 0);
public class Filename extends Operand {
public Filename() {
super();
}

@Override
@@ -30,6 +37,26 @@ public void encode(IRWriterEncoder e) {
}

public static Filename decode(IRReaderDecoder d) {
return new Filename(d.getFilename());
return new Filename();
}

@Override
public void visit(IRVisitor visitor) {
visitor.Filename(this);
}

@Override
public Object retrieve(ThreadContext context, IRubyObject self, StaticScope currScope, DynamicScope currDynScope, Object[] temp) {
return context.runtime.newString(currScope.getIRScope().getFileName());
}

@Override
public Operand cloneForInlining(CloneInfo ii) {
return this;
}

@Override
public void addUsedVariables(List<Variable> l) {
/* Do nothing */
}
}
11 changes: 11 additions & 0 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
@@ -2026,6 +2026,17 @@ public void DynamicSymbol(DynamicSymbol dynamicsymbol) {
jvmAdapter().invokevirtual(p(Ruby.class), "newSymbol", sig(RubySymbol.class, String.class, Encoding.class));
}

@Override
public void Filename(Filename filename) {
// Fixme: Not very efficient to do all this every time
jvmMethod().loadRuntime();
jvmMethod().loadStaticScope();
jvmAdapter().invokevirtual(p(StaticScope.class), "getIRScope", sig(IRScope.class));
jvmAdapter().invokevirtual(p(IRScope.class), "getFileName", sig(String.class));
jvmAdapter().invokevirtual(p(Ruby.class), "newString", sig(String.class));
}


@Override
public void Fixnum(Fixnum fixnum) {
jvmMethod().pushFixnum(fixnum.getValue());
Original file line number Diff line number Diff line change
@@ -47,6 +47,7 @@ public void load(Ruby runtime, boolean wrap) {
// I don't like it, but until we restructure the code a bit more, we'll need to quietly let it by here.
return;
}
script.setFileName(resource.getName());
runtime.loadScope(script, wrap);
} catch (IOException e) {
throw runtime.newIOErrorFromException(e);
Original file line number Diff line number Diff line change
@@ -259,7 +259,8 @@ public void load(Ruby runtime, boolean wrap) {
// Depending on the side-effect of the load, which loads the class but does not turn it into a script.
// I don't like it, but until we restructure the code a bit more, we'll need to quietly let it by here.
if (script == null) return;


script.setFileName(scriptName);
runtime.loadScope(script, wrap);
} catch(IOException e) {
throw runtime.newLoadError("no such file to load -- " + searchName, searchName);

0 comments on commit f37539a

Please sign in to comment.