<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
Hi Eliot -<br>
<br>
On 1/25/2012 2:43, Eliot Miranda wrote:
<blockquote
cite="mid:CAC20JE0HciXBZT3M4s7o1z=ujNSuu7kS1bC5HjiWDJn3ctNO7Q@mail.gmail.com"
type="cite">On Tue, Jan 24, 2012 at 2:02 PM, Mariano Martinez Peck
<span dir="ltr"><<a moz-do-not-send="true"
href="mailto:marianopeck@gmail.com">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>
<br>
<blockquote
cite="mid:CAC20JE0HciXBZT3M4s7o1z=ujNSuu7kS1bC5HjiWDJn3ctNO7Q@mail.gmail.com"
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
cite="mid:CAC20JE0HciXBZT3M4s7o1z=ujNSuu7kS1bC5HjiWDJn3ctNO7Q@mail.gmail.com"
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
moz-do-not-send="true"
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
moz-do-not-send="true"
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 moz-do-not-send="true"
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 moz-do-not-send="true"
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 moz-do-not-send="true"
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 moz-do-not-send="true"
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>
</body>
</html>