Skip to content

Commit 7b81ec5

Browse files
committed
Change specialisations to avoid race condition.
1 parent d9c0511 commit 7b81ec5

File tree

2 files changed

+35
-74
lines changed

2 files changed

+35
-74
lines changed

src/main/java/org/truffleruby/core/kernel/TruffleKernelNodes.java

Lines changed: 34 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import com.oracle.truffle.api.dsl.Specialization;
5454
import com.oracle.truffle.api.frame.FrameDescriptor;
5555
import com.oracle.truffle.api.frame.FrameSlot;
56+
import com.oracle.truffle.api.frame.FrameSlotKind;
5657
import com.oracle.truffle.api.frame.FrameUtil;
5758
import com.oracle.truffle.api.frame.MaterializedFrame;
5859
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -187,56 +188,37 @@ public abstract static class GetSpecialVariableStorage extends RubyContextNode {
187188
public abstract SpecialVariableStorage execute(VirtualFrame frame);
188189

189190
@Specialization(
190-
guards = { "frame.getFrameDescriptor() == descriptor", "slot != null" },
191+
guards = { "frame.getFrameDescriptor() == descriptor", "declarationFrameSlot != null" },
191192
assumptions = "frameAssumption",
192193
limit = "1")
193-
protected SpecialVariableStorage sameFrame(VirtualFrame frame,
194+
protected SpecialVariableStorage getFromKnownFrameDescriptor(VirtualFrame frame,
194195
@Cached("frame.getFrameDescriptor()") FrameDescriptor descriptor,
195-
@Cached("descriptor.findFrameSlot(SPECIAL_VARIABLES_STORAGE)") FrameSlot slot,
196-
@Cached("descriptor.getVersion()") Assumption frameAssumption) {
197-
Object storage = FrameUtil.getObjectSafe(frame, slot);
198-
if (storage == nil) {
199-
CompilerDirectives.transferToInterpreterAndInvalidate();
200-
storage = new SpecialVariableStorage();
201-
frame.setObject(slot, storage);
202-
}
203-
return (SpecialVariableStorage) storage;
204-
}
205-
206-
@Specialization(
207-
guards = { "frame.getFrameDescriptor() == descriptor", "slot == null", "declarationFrameSlot != null" },
208-
assumptions = "frameAssumption",
209-
limit = "1")
210-
protected SpecialVariableStorage declarationFrame(VirtualFrame frame,
211-
@Cached("frame.getFrameDescriptor()") FrameDescriptor descriptor,
212-
@Cached("descriptor.findFrameSlot(SPECIAL_VARIABLES_STORAGE)") FrameSlot slot,
213196
@Cached("declarationDepth(frame)") int declarationFrameDepth,
214-
@Cached("declarationSlot(frame)") FrameSlot declarationFrameSlot,
215-
@Cached("declarationDescriptor(frame).getVersion()") Assumption frameAssumption) {
216-
MaterializedFrame storageFrame = RubyArguments.getDeclarationFrame(frame, declarationFrameDepth);
217-
218-
Object storage = FrameUtil.getObjectSafe(storageFrame, declarationFrameSlot);
219-
if (storage == nil) {
220-
CompilerDirectives.transferToInterpreterAndInvalidate();
221-
storage = new SpecialVariableStorage();
222-
storageFrame.setObject(declarationFrameSlot, storage);
197+
@Cached("declarationDescriptor(frame, declarationFrameDepth)") FrameDescriptor declarationFrameDescriptor,
198+
@Cached("declarationSlot(declarationFrameDescriptor)") FrameSlot declarationFrameSlot,
199+
@Cached("declarationFrameDescriptor.getVersion()") Assumption frameAssumption) {
200+
Object storage;
201+
if (declarationFrameDepth == 0) {
202+
storage = FrameUtil.getObjectSafe(frame, declarationFrameSlot);
203+
if (storage == nil) {
204+
CompilerDirectives.transferToInterpreterAndInvalidate();
205+
storage = new SpecialVariableStorage();
206+
frame.setObject(declarationFrameSlot, storage);
207+
}
208+
} else {
209+
MaterializedFrame storageFrame = RubyArguments.getDeclarationFrame(frame, declarationFrameDepth);
210+
211+
storage = FrameUtil.getObjectSafe(storageFrame, declarationFrameSlot);
212+
if (storage == nil) {
213+
CompilerDirectives.transferToInterpreterAndInvalidate();
214+
storage = new SpecialVariableStorage();
215+
storageFrame.setObject(declarationFrameSlot, storage);
216+
}
223217
}
224218
return (SpecialVariableStorage) storage;
225219
}
226220

227-
@Specialization(
228-
guards = { "frame.getFrameDescriptor() == descriptor", "slot == null", "declarationFrameSlot == null" },
229-
assumptions = "frameAssumption",
230-
limit = "1")
231-
protected SpecialVariableStorage unset(VirtualFrame frame,
232-
@Cached("frame.getFrameDescriptor()") FrameDescriptor descriptor,
233-
@Cached("descriptor.findFrameSlot(SPECIAL_VARIABLES_STORAGE)") FrameSlot slot,
234-
@Cached("declarationSlot(frame)") FrameSlot declarationFrameSlot,
235-
@Cached("declarationDescriptor(frame).getVersion()") Assumption frameAssumption) {
236-
return getSlow(frame.materialize());
237-
}
238-
239-
@Specialization(replaces = { "sameFrame", "declarationFrame", "unset" })
221+
@Specialization(replaces = "getFromKnownFrameDescriptor")
240222
protected SpecialVariableStorage slowPath(VirtualFrame frame) {
241223
return getSlow(frame.materialize());
242224
}
@@ -290,40 +272,19 @@ protected int declarationDepth(VirtualFrame topFrame) {
290272
}
291273
}
292274

293-
protected FrameDescriptor declarationDescriptor(VirtualFrame topFrame) {
294-
MaterializedFrame frame = topFrame.materialize();
295-
296-
while (true) {
297-
final FrameSlot slot = getVariableSlot(frame);
298-
if (slot != null) {
299-
return frame.getFrameDescriptor();
300-
}
301-
302-
final MaterializedFrame nextFrame = RubyArguments.getDeclarationFrame(frame);
303-
if (nextFrame != null) {
304-
frame = nextFrame;
305-
} else {
306-
return frame.getFrameDescriptor();
307-
}
275+
protected FrameDescriptor declarationDescriptor(VirtualFrame topFrame, int depth) {
276+
MaterializedFrame frame;
277+
if (depth == 0) {
278+
frame = topFrame.materialize();
279+
} else {
280+
frame = RubyArguments.getDeclarationFrame(topFrame, depth);
308281
}
282+
return frame.getFrameDescriptor();
309283
}
310284

311-
protected FrameSlot declarationSlot(VirtualFrame topFrame) {
312-
MaterializedFrame frame = topFrame.materialize();
313-
314-
while (true) {
315-
final FrameSlot slot = getVariableSlot(frame);
316-
if (slot != null) {
317-
return slot;
318-
}
319-
320-
final MaterializedFrame nextFrame = RubyArguments.getDeclarationFrame(frame);
321-
if (nextFrame != null) {
322-
frame = nextFrame;
323-
} else {
324-
return null;
325-
}
326-
}
285+
@TruffleBoundary
286+
protected FrameSlot declarationSlot(FrameDescriptor descriptor) {
287+
return descriptor.findOrAddFrameSlot(Layouts.SPECIAL_VARIABLES_STORAGE, FrameSlotKind.Object);
327288
}
328289

329290
private static FrameSlot getVariableSlot(MaterializedFrame frame) {

src/main/java/org/truffleruby/language/backtrace/BacktraceFormatter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public void printRubyExceptionOnEnvStderr(String info, RubyException rubyExcepti
114114
context.getCoreLibrary().truffleExceptionOperationsModule,
115115
"get_formatted_backtrace",
116116
rubyException);
117-
final String formatted = ((RubyString) fullMessage).getJavaString();
117+
final String formatted = fullMessage != null ? ((RubyString) fullMessage).getJavaString() : "";
118118
if (formatted.endsWith("\n")) {
119119
printer.print(formatted);
120120
} else {

0 commit comments

Comments
 (0)