[squeak-dev] The Trunk: Kernel-ct.1438.mcz

christoph.thiede at student.hpi.uni-potsdam.de christoph.thiede at student.hpi.uni-potsdam.de
Sun Jan 2 21:57:04 UTC 2022

Hi Eliot, hi all,

have a wonderful new year, and thank you for the feedback! Again, I/we can change this of course until the code is perfect. :)

please continue reading below ...

On 2021-12-31T09:14:04+01:00, marcel.taeumel at hpi.de wrote:

> > Instead use this pattern:(self objectClass: meth) isCompiledCodeClass
> +1
> > But do you *really* need to deal with proxies here?  If not, then *please* revert to the simple and rational meth isCompiledCode.
> +1
> Best,
> Marcel
> Am 30.12.2021 20:01:54 schrieb Eliot Miranda <eliot.miranda at gmail.com>:
> Hi Christoph,
> On Tue, Dec 28, 2021 at 12:13 PM <commits at source.squeak.org [mailto:commits at source.squeak.org]> wrote:
> Christoph Thiede uploaded a new version of Kernel to project The Trunk:
> http://source.squeak.org/trunk/Kernel-ct.1438.mcz [http://source.squeak.org/trunk/Kernel-ct.1438.mcz]
> ==================== Summary ====================
> Name: Kernel-ct.1438
> Author: ct
> Time: 28 December 2021, 9:13:10.136249 pm
> UUID: 0477e714-e01d-d34d-b6aa-0939494a4abc
> Ancestors: Kernel-mt.1437, Kernel-ct.1403
> Merges Kernel-ct.1403 (fixes simulation of dynamic-forwarding objects as methods).
> =============== Diff against Kernel-mt.1437 ===============
> Item was changed:
>   ----- Method: Context>>send:to:with:lookupIn: (in category 'controlling') -----
>   send: selector to: rcvr with: arguments lookupIn: lookupClass
>         "Simulate the action of sending a message with selector and arguments to rcvr. The argument, lookupClass, is the class in which to lookup the message. This is the receiver's class for normal messages, but for super messages it will be some specific class related to the source method."
> +       | meth methClass primIndex val ctxt |
> -       | meth primIndex val ctxt |
>         (meth := lookupClass lookupSelector: selector) ifNil:
>                 [selector == #doesNotUnderstand: ifTrue:
>                         [self error: 'Recursive message not understood!!' translated].
>                 ^self send: #doesNotUnderstand:
>                                 to: rcvr
>                                 with: {(Message selector: selector arguments: arguments) lookupClass: lookupClass}
>                                 lookupIn: lookupClass].
> +       ((methClass := self objectClass: meth) == CompiledMethod or: [methClass == CompiledBlock]) ifFalse:
> Again this  cannot be allowed to stand.  It prevents adding subclasses of CompiledMethod & CompiledBlock, which is definitely something one would want to allow.  Instead use this pattern:
>    (self objectClass: meth) isCompiledCodeClass

Ah! Of course. There is no need to assume that primitiveClass would answer a proxy object. :)

> But do you *really* need to deal with proxies here?  If not, then *please* revert to the simple and rational meth isCompiledCode.

I will respect your eventual decision, but please give me another chance to argue for proxy-safe code in this place: There are not many implementations of the Objects as Methods pattern at all, but within these implementations, transparent proxies do not appear as something very unusual to me. I would even argue that transparent proxies are be the best practice here because otherwise, implementors are likely to break the default code browsing tools and literal search in the entire image [1].
In current Trunk, 2 out of 4 #run:with:in: implementors also override #doesNotUnderstand: and thus will not work during debugging. The pretty common (?) MethodWrappers package [2] does so, too.
If we add support for OaM in the image-side simulator, why not add full support? Is primitiveClass more expensive than I was assuming? :)

Here is a concrete example that you can evaluate but not debug without the current patch:

	Object compile: 'foo ^42'.
	cov := TestCoverage on: (Object >> #foo) asCodeReference.
	cov install.
	"[Context runSimulated: [self foo]] ensure: [cov uninstall]."
	self foo.
	self assert: cov hasRun.

> Remember you can always have overrides for your own project,  You don't need to inflict these special cases on the community code base (until they're fully justified).  For example, in Virtend (which used to be called Terf) we have several packages we load on top of Squeak 5.3, TerfExtensions-Kernel, TerfExtensions-Collections ,etc.  By organising like this we keep related changes organised by package and we don't have to disturb 5.3.

That is a good advice and one I'm already trying to follow, but I still feel the desire to contribute a maximum of conveniences and bugfixes upstream to the Trunk because I want other projects and people benefit from them as well. Provided that I do not disturb anyone, of course. :)
Besides, a concrete problem with too many override method can be that they intermix and shadow each other if I need to add the same override method to multiple packages (for instance, if we decide to revert this patch, I will feel tempted to override #send:to:with:lookupIn: not only in SimulationStudio but also in MethodWrappers, which will make it tricky to load both of them into one image).

> -       meth isCompiledMethod ifFalse:
>                 ["Object as Methods (OaM) protocol: 'The contract is that, when the VM encounters an ordinary object (rather than a compiled method) in the method dictionary during lookup, it sends it the special selector #run:with:in: providing the original selector, arguments, and receiver.'. DOI: 10.1145/2991041.2991062."
>                 ^self send: #run:with:in:
>                         to: meth
>                         with: {selector. arguments. rcvr}].
>         meth numArgs = arguments size ifFalse:
>                 [^ self error: ('Wrong number of arguments in simulated message {1}' translated format: {selector})].
>         (primIndex := meth primitive) > 0 ifTrue:
>                 [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments.
>                 (self isPrimFailToken: val) ifFalse:
>                         [^val]].
>         ctxt := self activateMethod: meth withArgs: arguments receiver: rcvr.
>         (primIndex isInteger and: [primIndex > 0]) ifTrue:
>                 [ctxt failPrimitiveWith: val].
>         ^ctxt!
> --
> _,,,^..^,,,_
> best, Eliot
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20211231/b1fe9232/attachment.html>

Looking forward to your feedback!


[1] http://forum.world.st/BUG-Objects-as-methods-break-method-search-td5112346.html
[2] https://github.com/hpi-swa/MethodWrappers

Sent from Squeak Inbox Talk
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220102/ddf47a84/attachment.html>

More information about the Squeak-dev mailing list