Skip to content
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

Fix cannotInterpret: and test many VM callback methods #14211

Open
wants to merge 19 commits into
base: Pharo13
Choose a base branch
from

Conversation

privat
Copy link
Contributor

@privat privat commented Jul 4, 2023

Fix and test ProtoObject>>cannotInterpret: as the implementation was broken at many levels.

The PR also add systematic tests for the special selectors that the VM might send in specific situations.
These tests try to check the callbacks as they are handled by default in ProtoObject/Object (booooriiiiing), but mostly check custom defined handling trough redefinition in subclasses (with more complex situations).

Tested:

  • #attemptToAssign:withIndex:
  • #cannotInterpret:
  • #doesNotUnderstand:
  • #mustBeBoolean
  • #run:with:in:

What is missing:

  • Method sends to the context because I am not sure how to provide custom Context class to the VM: #cannotReturn:, #aboutToReturn:through:, #unusedBytecode
  • Special selectors that are not implemented #conditionalBranchCounterTrippedOn: and #classTrapFor: (I did not look at them yet)

@privat privat changed the base branch from Pharo12 to Pharo6.1 July 5, 2023 12:02
@privat privat changed the base branch from Pharo6.1 to Pharo12 July 5, 2023 12:02
@privat privat changed the base branch from Pharo12 to Pharo6.1 July 5, 2023 14:58
@privat privat changed the base branch from Pharo6.1 to Pharo12 July 5, 2023 14:58
@privat privat changed the title Fix cannotInterpret: (attempt) Fix cannotInterpret: and test many VM callback methods Jul 5, 2023
Copy link
Member

@guillep guillep left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some little comments with committable suggestions.

Tests look good to me :)

About the cannotReturn:, why not just testing it with an exception?

block := self blockWithNonLocalReturn.
self should: [ block value ] raise: CannotReturn.

blockWithNonLocalReturn
  ^ [ ^ self "Should throw always a cannot return exception because the home will be always dead" ]

The about to return is probably a bit trickier to test, because it's called when unwinding the stack because of non-local returns. And it's implemented to look for the next method marked as "interested in the unwind", which boils down to ensure blocks (methods marked with primitive 198). Then the hook make sure of calling the block of the ensure.

However, if you carefully craft a context, you could set your own home context of your own class, and hook the return:through: below?

aboutToReturn: result through: firstUnwindContext

	"Called from VM when an unwindBlock is found between self and its home.
	 Return to home's sender, executing unwind blocks on the way."

	self home return: result through: firstUnwindContext


<primitive: 111>
self primitiveFailed
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is already available in MirrorPrimitives and there was a previous effort to have it only once in that place (otherwise it was repeated in many places). I propose we remove this method and we use the other.

Copy link
Contributor Author

@privat privat Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class is not in Kernel, so it introduces an unwanted package dependency with ReflectionMirrors-Primitives.
Kernel should try to be minimal and self-contained. Some small code duplication is a lesser concern.

Moreover, MirrorPrimitives is undocumented and almost not used (only 4 references in the whole image outside of its own package ReflectionMirrors-Primitives, and those 4 are only for tests), its methods are also undocumented and non-discoverable.

The version in Behavior is not that bad, as the class is meaningful for the intent.

Comment on lines +20 to +29
{ #category : #'simulation support' }
Behavior class >> classOf: anObject [
"The class of anObject.
This is equivalent to `anObject class` but without a message to be send to `anObject`.
This can be very handy if the class of `anObject` is unreliable.
e.g. no inheritance from ProtoObject, or having a nil methodDict."

<primitive: 111>
self primitiveFailed
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{ #category : #'simulation support' }
Behavior class >> classOf: anObject [
"The class of anObject.
This is equivalent to `anObject class` but without a message to be send to `anObject`.
This can be very handy if the class of `anObject` is unreliable.
e.g. no inheritance from ProtoObject, or having a nil methodDict."
<primitive: 111>
self primitiveFailed
]

(self class lookupSelector: aMessage selector) ifNotNil:
["Simulated lookup succeeded -- resend the message."
^ aMessage sentTo: self].
((Behavior classOf: self) lookupSelector: aMessage selector) ifNotNil:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
((Behavior classOf: self) lookupSelector: aMessage selector) ifNotNil:
((MirrorPrimitives classOf: self) lookupSelector: aMessage selector) ifNotNil:

src/Kernel/ProtoObject.class.st Outdated Show resolved Hide resolved
@Ducasse Ducasse requested a review from tesonep July 6, 2023 09:04
Co-authored-by: Guille Polito <guillermopolito@gmail.com>
@privat
Copy link
Contributor Author

privat commented Jul 6, 2023

About the cannotReturn:, why not just testing it with an exception? [...]

I have a work in progress branch with things more or less equivalent with your proposals.
Testing callbacks on real context objects is ok.

I also want to check directly the behaviour of the VM by instrumenting, diverting and hacking the receiver of these callbacks. I cannot really do that with the image implementation of Context.
But catching the callbacks on a made up context-ish class is not easy (and very low-level to debug).
Currently, I have some weird behavior that could be some programmer (me) errors (likely) or some VM limitations (possible).

Anyway, I plan to make a new PR special-methods-for-Context once this one is merged

@jecisc
Copy link
Member

jecisc commented Jul 12, 2023

What is the state of this PR?

Tests are green. Some changes were requested but Jean seems to think the changes requested are not needed.

Can we integrate this change?

@jecisc jecisc changed the base branch from Pharo12 to Pharo13 May 23, 2024 01:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants