-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Issue 214] Exception signaling without helper methods #251
[Issue 214] Exception signaling without helper methods #251
Conversation
For attribution purposes, I'd add a line like See There's also a compilation error: https://travis-ci.org/smarr/SOMns/jobs/382258342#L689 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments and potential improvements.
|
||
private signalArgumentError: message = ( | ||
ArgumentError signalWith: message. | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we also remove https://github.com/smarr/SOMns/blob/release/core-lib/Files.ns#L664-L672 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@Child protected ExpressionNode signalExceptionNode; | ||
protected final SObject module; | ||
|
||
public ExceptionSignalingNode(final String exceptionClassName, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, is that so common that it is worthwhile to have the standard parameter KernelObj.kernel
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a dozen senders, but we can remove it if you want to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about a named factory method?
I'd prefer that over a constructor, because it would be more explicit.
So, perhaps createForKernel(..)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to a factory as requested.
allArgs[0] = exceptionClass; | ||
for (int i = 0; i < args.length; i++) { | ||
allArgs[i + 1] = args[i]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to extract line 43-47 into a named method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -73,7 +98,8 @@ public SClass instantiateClass(final SObjectWithClass outerObj, | |||
public static SClass instantiate(final SObjectWithClass outerObj, | |||
final ClassFactory factory) { | |||
SClass classObj = new SClass(outerObj, instantiateMetaclassClass(factory, outerObj)); | |||
return singalExceptionsIfFaultFoundElseReturnClassObject(outerObj, factory, classObj); | |||
return signalExceptionsIfFaultFoundElseReturnClassObject(outerObj, factory, classObj, | |||
floatingNotAValueThrower, floatingCannotBeValuesThrower); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, can we improve this?
Ideally, the nodes should come from the caller.
The @Specialization
above could provide instance-specific nodes, and the other callers could pass them in from static fields, if really necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
|
||
@Child protected ExceptionSignalingNode thrower; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fields are ideally defined before the constructors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
return this; | ||
} | ||
|
||
@Child protected ExceptionSignalingNode thrower; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please before constructor
return this; | ||
} | ||
|
||
@Child protected ExceptionSignalingNode thrower; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please before constructor
src/som/primitives/BlockPrims.java
Outdated
@Child ExceptionSignalingNode thrower; | ||
|
||
@Override | ||
public void signalException(final String message) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, can this be done as a default method to avoid code duplication?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't.
We are not able to use a common superclass.
If we move the code out, methods such as insert are not visible anymore.
@@ -103,4 +103,5 @@ public final Object doException(final SBlock body, final SBlock ensureHandler) { | |||
} | |||
} | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't know how to remove that. CheckStyle added it for us I think.
CompilerAsserts.neverPartOfCompilation(); | ||
KernelObj.signalException("signalArgumentError:", "File access mode invalid, was: " | ||
+ Objects.toString(mode) + " " + AccessModes.VALID_MODES); | ||
this.accessMode = AccessModes.valueOf(mode.getString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get this change. Where did the exception go?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the sender, so it can have the exceptionSignalNode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@clementbera @daumayr I also just pushed a bunch of changes. They are mostly polish, stuff I didn't see from simple reviewing. Note, this is work in progress. Will continue later.
core-lib/Files.ns
Outdated
@@ -645,6 +645,7 @@ DAMAGE.>> *) | |||
) | |||
) : ( | |||
public signalWith: aMessage = ( | |||
vmMirror printStackTrace: nil. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's debugging code, we want to solve this not specific to an exception, but somewhat differently (there is no implementation of stack trace capturing at the moment)
src/som/primitives/SystemPrims.java
Outdated
} catch (NotAFileException e) { | ||
PathPrims.signalFileNotFoundException(e.getMessage(), | ||
"Path does not seem to be a file."); | ||
"Path does not seem to be a file.", thrower); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, that's FileNotFound
?
src/som/primitives/SystemPrims.java
Outdated
} catch (IOException e) { | ||
PathPrims.signalIOException(e.getMessage()); | ||
PathPrims.signalIOException(e.getMessage(), thrower); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here the same thrower node is IOException
? seems fishy
@clementbera @daumayr think this here is a slightly nicer solution, because it avoids an interface: 52a0041 Also, I am going to change all |
Ok, now I see why you might have decided for a lazy approach to initialize those exception nodes. |
@daumayr @clementbera please review 8412ba6 carefully (see comment). |
Ok, I am now happy with this. I did a bunch of other changes and clean ups. Please review carefully. |
Looks good to me. |
…lingTruffleNode - added JUnits tests for Files Co-authored-by: Dominik Aumayr <[email protected]>
65110a6
to
a2983fd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are some issues, sometimes nodes are initialized with insert(), sometimes not. I guess they should all have insert. Theres a single place where renaming was not done. I annotated all of them. I wanted to change, but for some reasons I have way too many conflicts when I pull.
public ClassInstantiationNode(final MixinDefinition mixinDefinition) { | ||
super(mixinDefinition); | ||
notAValueThrower = insert(ExceptionSignalingNode.createNotAValueNode( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was not renamed (still named thrower)
@@ -88,6 +103,11 @@ public SClass instantiateClassWithNewClassFactory(final SObjectWithClass outerOb | |||
|
|||
public ObjectLiteralInstantiationNode(final MixinDefinition mixinDefinition) { | |||
super(mixinDefinition); | |||
notAValueThrower = ExceptionSignalingNode.createNotAValueNode( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was not renamed (thrower) and it seems the insert() function is missing.
@SuppressWarnings("unchecked") | ||
public ValueCheckNode initialize(final SourceSection sourceSection) { | ||
super.initialize(sourceSection); | ||
notAValue = ExceptionSignalingNode.createNotAValueNode(sourceSection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems the insert() is missing.
@SuppressWarnings("unchecked") | ||
public NewImmutableArrayNode initialize(final SourceSection sourceSection) { | ||
super.initialize(sourceSection); | ||
notAValue = ExceptionSignalingNode.createNotAValueNode(sourceSection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No insert()
Inserts are needed when the nodes are added to a method after the whole method was construct. So, strictly speaking
As mentioned before, I started squashing commits that do not add helpful information to the history and only make it harder to understand why and how things changed (fixups, in-development bugs, other changes that are only side-effects of the development, and not relevant for the end result). |
Signed-off-by: Stefan Marr <[email protected]>
ad93285
to
ef3e9d9
Compare
Signed-off-by: Stefan Marr <[email protected]>
- pre-allocate commonly used exception-related symbols, and use instead of strings - rename execute to signal, and use directly - consistently use factory methods for exception nodes - reduce extensive verbosity, they are static methods, context is provided by the class name - change name of parameters: they are selectors, could be other things beside classes - restructure to enable lazy initialization on first activation - this is necessary to resolve modules which are loaded after parsing a method - also allocate the message send nodes lazily to avoid impact on startup performance - improve source section used for attribution to be the initializer - use node initializer methods consistently - remove ValuePrim, simply pass node instead - avoid `thrower` as name, instead use the type of the exception that’s going to be throw. Reads nicer: `argumentError.signal(…)` - remove unused code Signed-off-by: Stefan Marr <[email protected]>
Signed-off-by: Stefan Marr <[email protected]>
ef3e9d9
to
3406c63
Compare
I finished the final cleanups, squashed the history where useful, and updated the issue title/description to explain the changes. Note, there is another change hidden in here: the message send nodes for the exception handling are all allocated lazily now. There was some overhead on the startup performance, which is fixed by this. Will merge once all tests/benchmarks passed. |
This PR introduces the infrastructure to do exception signaling without relying on helper methods in the Newspeak code. Thereby, it addresses #214.
It introduces the
ExceptionSignalingNode
, which performs the message sends necessary to signal an exception.In the interpreter, this allows us to have for instance code like this:
Work with @daumayr.
This change does not yet fully optimize the exception signaling. For instance, it does not cache the exception class, which could avoid the message send for its lookup. However, this would need to be done very carefully, since the lookup is done via a normal message send, which could have side effects. Thus, it should only be optimized for well known and unproblematic cases.
[description updated by @smarr to be a summary of the change]