|
70 | 70 | import de.hpi.swa.trufflesqueak.nodes.plugins.JPEGReader;
|
71 | 71 | import de.hpi.swa.trufflesqueak.nodes.plugins.Zip;
|
72 | 72 | import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy;
|
| 73 | +import de.hpi.swa.trufflesqueak.nodes.process.SignalSemaphoreNodeGen; |
73 | 74 | import de.hpi.swa.trufflesqueak.shared.SqueakImageLocator;
|
74 | 75 | import de.hpi.swa.trufflesqueak.tools.SqueakMessageInterceptor;
|
75 | 76 | import de.hpi.swa.trufflesqueak.util.ArrayUtils;
|
@@ -168,6 +169,10 @@ public final class SqueakImageContext {
|
168 | 169 | private ContextObject interopExceptionThrowingContextPrototype;
|
169 | 170 | public ContextObject lastSeenContext;
|
170 | 171 |
|
| 172 | + /* Low space handling */ |
| 173 | + private static final int LOW_SPACE_NUM_SKIPPED_SENDS = 4; |
| 174 | + private int lowSpaceSkippedSendsCount; |
| 175 | + |
171 | 176 | @CompilationFinal private ClassObject fractionClass;
|
172 | 177 | private PointersObject parserSharedInstance;
|
173 | 178 | private AbstractSqueakObject requestorSharedInstanceOrNil;
|
@@ -679,6 +684,34 @@ public void setSemaphore(final int index, final AbstractSqueakObject semaphore)
|
679 | 684 | setSpecialObject(index, semaphore);
|
680 | 685 | }
|
681 | 686 |
|
| 687 | + /** |
| 688 | + * Ensure the active process is saved and try to signal low space semaphore (see |
| 689 | + * #setSignalLowSpaceFlagAndSaveProcess). The JVM has just thrown a {@link StackOverflowError}, |
| 690 | + * so thread stack space is limited. To avoid hitting the limit again, free up some space by |
| 691 | + * unwinding a couple of sends before actually signaling the low space semaphore. |
| 692 | + */ |
| 693 | + public StackOverflowError tryToSignalLowSpace(final VirtualFrame frame, final StackOverflowError stackOverflowError) { |
| 694 | + CompilerAsserts.neverPartOfCompilation(); |
| 695 | + final Object lastSavedProcess = getSpecialObject(SPECIAL_OBJECT.PROCESS_SIGNALING_LOW_SPACE); |
| 696 | + if (lastSavedProcess == NilObject.SINGLETON) { |
| 697 | + setSpecialObject(SPECIAL_OBJECT.PROCESS_SIGNALING_LOW_SPACE, getActiveProcessSlow()); |
| 698 | + } |
| 699 | + if (lowSpaceSkippedSendsCount < LOW_SPACE_NUM_SKIPPED_SENDS) { |
| 700 | + lowSpaceSkippedSendsCount++; |
| 701 | + throw stackOverflowError; // continue further up the sender chain |
| 702 | + } else { |
| 703 | + final Object lowSpaceSemaphoreOrNil = getSpecialObject(SPECIAL_OBJECT.THE_LOW_SPACE_SEMAPHORE); |
| 704 | + try { |
| 705 | + SignalSemaphoreNodeGen.executeUncached(frame, this, lowSpaceSemaphoreOrNil); |
| 706 | + } catch (final ProcessSwitch ps) { |
| 707 | + // success! reset counter and continue in new process |
| 708 | + lowSpaceSkippedSendsCount = 0; |
| 709 | + throw ps; |
| 710 | + } |
| 711 | + throw CompilerDirectives.shouldNotReachHere("Failed to signal low space semaphore.", stackOverflowError); |
| 712 | + } |
| 713 | + } |
| 714 | + |
682 | 715 | public boolean hasDisplay() {
|
683 | 716 | return display != null;
|
684 | 717 | }
|
|
0 commit comments