[Vm-dev] Explicitly avoiding process switch
leves at elte.hu
Fri Aug 12 13:07:04 UTC 2011
On Thu, 11 Aug 2011, stephane ducasse wrote:
> One idea marcus mentioned was to have an explicit bytecode for suspension point.
> I think that explicit semantics and behavior is always better.
What's the point of having a bytecode for suspension points?
Since the goal is to avoid suspension points, the best solution is to use
pragmas that the compiler takes into account. It can either be global for
the given method or it can specify some selectors which should be
optimized to avoid suspension points. Here's an example for the per
critical: mutuallyExcludedBlock ifLocked: alternativeBlock
"Evaluate mutuallyExcludedBlock only if the receiver is not currently in
the process of running the critical: message. If the receiver is, then evaluate
alternativeBlock and return."
"See the comment of #critical: for the explanation how this pattern works
before changing the code."
| caught |
<useByteCodesFor: #(== ifTrue:ifFalse: -)>
caught := false.
"We're using #== here instead of #=, because it won't introduce a
suspension point, while #= may do that."
excessSignals == 0
ifTrue: [ alternativeBlock value ]
excessSignals := excessSignals - 1.
caught := true.
mutuallyExcludedBlock value ] ]
ensure: [ caught ifTrue: [ self signal ] ]
> Marcus is also thinking about expression or method tagging that the compiler could take into account
> to generate this specific bytecode.
>> I would properly comment the places where this "ATOMIC" operation is
>> really used.
>> 2011/8/11 Mariano Martinez Peck <marianopeck at gmail.com>:
>>> Hi guys. We were discussing yesterday with Marcus about the following....
>>> I remember a problem we have in Pharo because of changing "foo == nil" to "foo isNil" in some important places like Process/Delay/Semaphore. Such change introduces a suspension point, where if I understand correctly, the scheduler can switch to another process only during method sends. #== is optimized with a special bytecode and there is no message send. Sending #isNil is a message sent, and hence we introduce a suspension point. In 99% of the cases this is not a problem. But I can imagine that there are places (mostly those related to Process/Delay/Semaphore) where this changes can be very very bad.
>>> To do some experiments, I want to remove the bytecode for #== but of course, I think I will have all these problems. And there are more. Marcus told me that some optimizations done by the compiler end up sending #==. And I also remember some code he told me (I think it was #allObjectsDo:) that would never finish because of the block closure objects creation.
>>> So...what about making the necessity of NOT sending a message or NOT introducing a suspension point more explicit? first we should have the support for that and second know each place where we need them.
>>> The most basic thing I can think of is doing something like:
>>> (ParseNode classVarNamed: 'StdSelectors') at: #== put: #bytecodedEqualEqual.
>>> Compiler recompileAll.
>>> And put a nice comment why one may want to use #optimizedEqualEqual. But again, in which places should I change #== for #bytecodedEqualEqual
>>> Any thought or idea about them is really appreciated.
More information about the Vm-dev