<br><br><div class="gmail_quote">On Wed, Jan 25, 2012 at 5:21 AM, Andreas Raab <span dir="ltr"><<a href="mailto:andreas.raab@gmx.de">andreas.raab@gmx.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
<div bgcolor="#FFFFFF" text="#000000">
Hi Eliot -<br>
<br>
On 1/25/2012 2:43, Eliot Miranda wrote:
<blockquote type="cite">On Tue, Jan 24, 2012 at 2:02 PM, Mariano Martinez Peck
<span dir="ltr"><<a href="mailto:marianopeck@gmail.com" target="_blank">marianopeck@gmail.com</a>></span>
wrote:<br>
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
sorry...here is the attached. <br>
</blockquote>
<div><br>
</div>
<div>OK. What you've done will work. <br>
</div>
</div>
</blockquote>
<br>
I actually quite like it. Getting rid of all those methods in class
ProtoObject is definitely a good thing. Is there any downside other
than some possible performance issues? I.e., the code should work
everywhere, right?<br></div></blockquote><div><br></div><div>Right. The primitive I implemented at Qwaq/Teleplace (ContextPart>>#tryNamedPrimitiveIn:for:withArgs:) makes these methods obsolete but since this primitive isn't yet in the standard VM the body uses those old methods in case the primitive doesn't exist. As soon as the primitive is in the standard VM as well there's neither no need for those methods in ProtoObject nor the need to synthesize a method on each use. The synthesizing a method approach has a nice conceptual simplicity. It doesn't need a special primitive, and uses machinery that already exists. But IIRC we decided to go the primitive route because ContextPart>>#tryPrimitiveFor:receiver:args: already existed and provided a model.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div bgcolor="#FFFFFF" text="#000000">
<br>
<blockquote type="cite">
<div class="gmail_quote">
<div>Some criticism: Since the method is new the flushCache
should be unneeded. I think either copying a template method
(e.g. stored in a class variable) and changing its argument
count, or creating a method directly (look at the generate:
method) would be much faster. Speed can be important in the
debugger.</div>
</div>
</blockquote>
<br>
More important in my view is the misuse of the term "temporal" in
the method names. I find it quite confusing to read about "temporal"
compiled methods :-)<br>
<br>
Cheers,<br>
- Andreas<br>
<br>
<blockquote type="cite">
<div class="gmail_quote">
<div><br>
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
<div class="gmail_quote">On Tue, Jan 24, 2012 at 11:01 PM,
Mariano Martinez Peck <span dir="ltr"><<a href="mailto:marianopeck@gmail.com" target="_blank">marianopeck@gmail.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote">
<div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote">
<div><br>
</div>
<div>Analogously, one needs a way of
invoking named primitives in the
debugger, and using
tryNamedPrimitive[:with:with:...] et al
has exactly the same weaknesses
as tryPrimitiveN above. So introducing
a primitive to run named primitives is
in keeping with tryPrimitive:withArgs:.
Using the VisualWorks approach is
feasible but violates Occam's razor.</div>
</div>
</blockquote>
<div><br>
What what about temporally (to be removed in
the future) just when we are using older
VMs?<br>
</div>
</div>
</blockquote>
<div><br>
</div>
</div>
<div>If temporary, then fine. But its all work :)</div>
</div>
</blockquote>
<div><br>
<br>
Well...writing papers can be boring ;)<br>
Please, could you take a look to the attached .cs? I
tried to do what I had in mind. Since this part of the
system is new for me, I have not sure it is correct,
nor how to test it. So far what I did for testing it
is to take the #tryNamedPrimitiveIn: aCompiledMethod
for: aReceiver withArgs: arguments<br>
and (temporally) remove the <primitive: 218 error:
ec> and define 'ec' as a temporal variable. Since
it will be nil, the following code will be executed.<br>
Then I put a halt in #open: fileName forWrite:
writeMode from StandardFileStream and then I do it:<br>
FileDirectory default forceNewFileNamed: 'xxxxx'.<br>
Once in the debugger, I went to:<br>
<br>
StandardFileStream retryWithGC:[self primOpen: f
writable: writeMode] <br>
until:[:id| id notNil] <br>
forFileNamed: fileName.<br>
<br>
did a "through" in the close, and be sure I could do
"into" and "step" for #self primOpen: f writable:
writeMode (which is a named primitive).<br>
<br>
is this ok?<br>
<br>
Thanks Eliot!<br>
<br>
<br>
</div>
<div>
<div>
<blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote">
<div>
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote">
<div> </div>
<blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote">
<div><br>
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Why do we need them in ProtoObject?<br>
</blockquote>
<div><br>
</div>
<div>Once
tryNamedPrimitiveIn:for:withArgs: is
implemented in all relevant virtual
machines we don't need them. You'll
notice that there is no trace of the
tryPrimitiveN methods anymore, even
though they're in Smalltalk-80.</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Because I'm not sure that adding
primitive to VM is always a good
solution.<br>
</blockquote>
<div><br>
</div>
<div>Agreed. But it is in keeping with
the primitive for invoking numbered
primitives, tryPrimitive:withArgs:.</div>
<div><br>
</div>
<div><br>
</div>
<div>HTH</div>
<div>Eliot</div>
<div><br>
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Stef<br>
<div>
<div><br>
> On Mon, Jan 23, 2012 at 8:52
AM, Mariano Martinez Peck <<a href="mailto:marianopeck@gmail.com" target="_blank">marianopeck@gmail.com</a>>
wrote:<br>
> Hi guys. I usually like to
take a look to ProtoObject and see
what is really needed for the
minimal object. But having 30% of
the methods being
#tryNamedPrimitive:with: * is
not fun.<br>
> So...I wonder, do you think
there could be another way so that
to avoid having all those methods
in ProtoObject ?<br>
><br>
> Yes there is. I implemented
primitive 218 in Cog,
primitiveDoNamedPrimitiveWithArgs,
which is accessed via<br>
><br>
><br>
>
tryNamedPrimitiveIn:
aCompiledMethod for: aReceiver
withArgs: arguments<br>
> |
selector theMethod spec
receiverClass |<br>
>
<primitive: 218 error: ec><br>
> ec
ifNotNil:<br>
>
["If ec is an integer other than
-1 there was a problem with
primitive 218,<br>
>
not with the external primitive
itself. -1 indicates a generic
failure (where<br>
>
ec should be nil) but ec = nil
means primitive 218 is not
implemented. So<br>
>
interpret -1 to mean the
external primitive failed with a
nil error code."<br>
>
ec isInteger ifTrue:<br>
>
[ec = -1<br>
>
ifTrue: [ec :=
nil]<br>
>
ifFalse: [self
primitiveFailed]].<br>
>
^{PrimitiveFailToken. ec}].<br>
> "Assume
a nil error code implies the
primitive is not implemented and
fall back on the old code."<br>
> "Hack.
Attempt to execute the named
primitive from the given compiled
method"<br>
>
arguments size > 8 ifTrue:<br>
>
[^{PrimitiveFailToken. nil}].<br>
>
selector := #(<br>
>
tryNamedPrimitive<br>
>
tryNamedPrimitive:<br>
>
tryNamedPrimitive:with:<br>
>
tryNamedPrimitive:with:with:<br>
>
tryNamedPrimitive:with:with:with:<br>
>
tryNamedPrimitive:with:with:with:with:<br>
>
tryNamedPrimitive:with:with:with:with:with:<br>
>
tryNamedPrimitive:with:with:with:with:with:with:<br>
>
tryNamedPrimitive:with:with:with:with:with:with:with:)
at: arguments size+1.<br>
>
receiverClass := self objectClass:
aReceiver.<br>
>
theMethod := receiverClass
lookupSelector: selector.<br>
>
theMethod == nil ifTrue:<br>
>
[^{PrimitiveFailToken. nil}].<br>
> spec :=
theMethod literalAt: 1.<br>
> spec
replaceFrom: 1 to: spec size with:
(aCompiledMethod literalAt: 1)
startingAt: 1.<br>
>
Smalltalk
unbindExternalPrimitives.<br>
> ^self
object: aReceiver perform:
selector withArguments: arguments
inClass: receiverClass<br>
><br>
> (cf tryPrimitive: withArgs:)
and used in<br>
><br>
><br>
> doPrimitive:
primitiveIndex method: meth
receiver: receiver args: arguments<br>
>
"Simulate a primitive method whose
index is primitiveIndex. The
simulated receiver<br>
> and
arguments are given as arguments
to this message. Any primitive
which provokes<br>
>
execution needs to be intercepted
and simulated to avoid execution
running away."<br>
><br>
> | value
|<br>
> "If
successful, push result and return
resuming context, else ^ {
PrimitiveFailToken. errorCode }"<br>
>
(primitiveIndex = 19) ifTrue:<br>
>
[ToolSet<br>
>
debugContext: self<br>
>
label:'Code simulation
error'<br>
>
contents: nil].<br>
><br>
>
"ContextPart>>blockCopy:;
simulated to get startpc right"<br>
>
(primitiveIndex = 80 and: [(self
objectClass: receiver)
includesBehavior: ContextPart])<br>
>
ifTrue: [^self push:
((BlockContext newForMethod:
receiver method)<br>
>
home: receiver home<br>
>
startpc: pc + 2<br>
>
nargs: (arguments at: 1))].<br>
>
(primitiveIndex = 81 and: [(self
objectClass: receiver) ==
BlockContext])
"BlockContext>>value[:value:...]"<br>
>
ifTrue: [^receiver pushArgs:
arguments from: self].<br>
>
(primitiveIndex = 82 and: [(self
objectClass: receiver) ==
BlockContext])
"BlockContext>>valueWithArguments:"<br>
>
ifTrue: [^receiver pushArgs:
arguments first from: self].<br>
>
primitiveIndex = 83 "afr 9/11/1998
19:50"
"Object>>perform:[with:...]"<br>
>
ifTrue: [^self send: arguments
first<br>
>
to:
receiver<br>
>
with:
arguments allButFirst<br>
>
super:
false].<br>
>
primitiveIndex = 84 "afr 9/11/1998
19:50 & eem 8/18/2009 17:04"
"Object>>perform:withArguments:"<br>
>
ifTrue: [^self send: arguments
first<br>
>
to:
receiver<br>
>
with:
(arguments at: 2)<br>
>
startClass: nil].<br>
>
primitiveIndex = 100 "eem
8/18/2009 16:57"
"Object>>perform:withArguments:inSuperclass:"<br>
>
ifTrue: [^self send: arguments
first<br>
>
to:
receiver<br>
>
with:
(arguments at: 2)<br>
>
startClass: (arguments at: 3)].<br>
><br>
>
"Mutex>>primitiveEnterCriticalSection<br>
>
Mutex>>primitiveTestAndSetOwnershipOfCriticalSection"<br>
>
(primitiveIndex = 186 or:
[primitiveIndex = 187]) ifTrue:<br>
>
[| active effective |<br>
>
active := Processor
activeProcess.<br>
>
effective := active
effectiveProcess.<br>
>
"active == effective"<br>
>
value := primitiveIndex = 186<br>
>
ifTrue:
[receiver
primitiveEnterCriticalSectionOnBehalfOf:
effective]<br>
>
ifFalse:
[receiver
primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf:
effective].<br>
>
^(value isArray<br>
>
and: [value size = 2<br>
>
and: [value first ==
PrimitiveFailToken]])<br>
>
ifTrue: [value]<br>
>
ifFalse: [self push:
value]].<br>
><br>
>
primitiveIndex = 188 ifTrue: "eem
5/27/2008 11:10
Object>>withArgs:executeMethod:"<br>
>
[^MethodContext<br>
>
sender: self<br>
>
receiver: receiver<br>
>
method: (arguments at: 2)<br>
>
arguments: (arguments at:
1)].<br>
><br>
>
"Closure primitives"<br>
>
(primitiveIndex = 200 and: [self
== receiver]) ifTrue:<br>
>
"ContextPart>>closureCopy:copiedValues:;
simulated to get startpc right"<br>
>
[^self push: (BlockClosure<br>
>
outerContext: receiver<br>
>
startpc: pc + 2<br>
>
numArgs: arguments first<br>
>
copiedValues: arguments last)].<br>
>
((primitiveIndex between: 201 and:
205)
"BlockClosure>>value[:value:...]"<br>
> or:
[primitiveIndex between: 221 and:
222]) ifTrue:
"BlockClosure>>valueNoContextSwitch[:]"<br>
>
[^receiver
simulateValueWithArguments:
arguments caller: self].<br>
>
primitiveIndex = 206 ifTrue:
"BlockClosure>>valueWithArguments:"<br>
>
[^receiver
simulateValueWithArguments:
arguments first caller: self].<br>
><br>
>
primitiveIndex = 118 ifTrue:
"tryPrimitive:withArgs:; avoid
recursing in the VM"<br>
>
[(arguments size = 2<br>
>
and: [arguments first isInteger<br>
>
and: [arguments last class ==
Array]]) ifFalse:<br>
>
[^ContextPart
primitiveFailTokenFor: nil].<br>
>
^self doPrimitive: arguments
first method: meth receiver:
receiver args: arguments last].<br>
><br>
> value
:= primitiveIndex = 120 "FFI
method"<br>
>
ifTrue: [(meth
literalAt: 1)
tryInvokeWithArguments: arguments]<br>
>
ifFalse:<br>
>
[primitiveIndex = 117 "named
primitives"<br>
>
ifTrue: [self tryNamedPrimitiveIn:
meth for: receiver withArgs:
arguments]<br>
>
ifFalse:<br>
>
[receiver tryPrimitive:
primitiveIndex withArgs:
arguments]].<br>
> ^(value
isArray<br>
>
and: [value size = 2<br>
>
and: [value first ==
PrimitiveFailToken]])<br>
>
ifTrue: [value]<br>
>
ifFalse: [self push: value]<br>
><br>
> (find attached). But these
need implementing in the standard
VM before they can be used in
Pharo, Squeak, etc.<br>
><br>
><br>
> Thanks<br>
><br>
> --<br>
> Mariano<br>
> <a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
><br>
><br>
><br>
><br>
> --<br>
> best,<br>
> Eliot<br>
><br>
<br>
<br>
</div>
</div>
</blockquote>
</div>
<br>
<br clear="all">
<div><br>
</div>
-- <br>
best,
<div>Eliot</div>
<br>
<br>
</blockquote>
</div>
<br>
<br clear="all">
<br>
-- <br>
Mariano<br>
<a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
<br>
<br>
</blockquote>
</div>
<br>
<br clear="all">
<div><br>
</div>
-- <br>
best,
<div>Eliot</div>
<br>
<br>
</blockquote>
</div>
</div>
</div>
<span><font color="#888888"><br>
<br clear="all">
<br>
-- <br>
Mariano<br>
<a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
<br>
</font></span></blockquote>
</div>
<br>
<br clear="all">
<br>
-- <br>
Mariano<br>
<a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
<br>
<br>
</blockquote>
</div>
<br>
<br clear="all">
<div><br>
</div>
-- <br>
best,
<div>Eliot</div>
<br>
</blockquote>
</div>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div><br>