help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-smalltalk] Re: STCompiler repeats evaluation of "receiver" for Cas


From: Paolo Bonzini
Subject: [Help-smalltalk] Re: STCompiler repeats evaluation of "receiver" for CascadeNodes
Date: Fri, 29 Dec 2006 11:34:54 +0100
User-agent: Thunderbird 1.5.0.9 (Macintosh/20061207)

Stephen Compall wrote:
Have a look:

That's a bug. The attached patch should do the job, but I have to test it a bit more before committing, since I took the occasion to do some simple refactoring.

Paolo
2006-12-29  Paolo Bonzini  <address@hidden>

        * compiler/STCompLit.st: Don't use "nil" slots from VMSpecialMethods.
        * compiler/STCompiler.st: Remove dupReceiver.  Adjust for above change.
        Compile receiver in compileTimesRepeat: and compileLoop:, test for
        receiver being a block in compileWhileLoop:.  Extract part of
        acceptMessageNode: to compileMessage:.  Compile receiver in
        acceptCascadeNode: and call compileMessage: to avoid compiling the
        receiver of a cascaded message repeatedly (reported by Stephen Compall).

--- orig/compiler/STCompLit.st
+++ mod/compiler/STCompLit.st
@@ -88,10 +88,10 @@ VMOtherConstants at: #VMSpecialIdentifie
     yourself).
     
 VMOtherConstants at: #VMSpecialMethods put: ((IdentityDictionary new: 32)
-    at: #whileTrue             put: nil                 ;
-    at: #whileFalse            put: nil                 ;
-    at: #whileTrue:            put: nil                 ;
-    at: #whileFalse:           put: nil                 ;
+    at: #whileTrue             put: #compileWhileLoop:  ;
+    at: #whileFalse            put: #compileWhileLoop:  ;
+    at: #whileTrue:            put: #compileWhileLoop:  ;
+    at: #whileFalse:           put: #compileWhileLoop:  ;
     at: #timesRepeat:          put: #compileTimesRepeat:;
     at: #to:do:                        put: #compileLoop:       ;
     at: #to:by:do:             put: #compileLoop:       ;


--- orig/compiler/STCompiler.st
+++ mod/compiler/STCompiler.st
@@ -55,7 +55,7 @@ compile: methodDefNode for: aBehavior cl
 ! !
 
 STFakeCompiler subclass: #STCompiler
-       instanceVariableNames: 'node destClass symTable parser bytecodes depth 
maxDepth isInsideBlock dupReceiver'
+       instanceVariableNames: 'node destClass symTable parser bytecodes depth 
maxDepth isInsideBlock '
        classVariableNames: 'OneNode TrueNode FalseNode NilNode SuperVariable 
SelfVariable ThisContextVariable DoitToken'
        poolDictionaries: ''
        category: 'System-Compiler'
@@ -162,7 +162,6 @@ class: aBehavior parser: aParser
     symTable := STSymbolTable new.
     parser := aParser.
     bytecodes := WriteStream on: (ByteArray new: 240).
-    dupReceiver := false.
     isInsideBlock := 0.
 
     symTable declareEnvironment: aBehavior.
@@ -560,18 +559,18 @@ acceptCascadeNode: aNode
        ^aNode
     ].
 
-    dupReceiver := true.
-    first acceptVisitor: self.
+    first receiver acceptVisitor: self.
+    self depthIncr; compileByte: DupStackTop.
+    self compileMessage: first.
 
     messages
        from: 2 to: messages size - 1
        do: [ :each |
            self compileByte: PopStackTop; compileByte: DupStackTop.
-           each acceptVisitor: self ].
+           self compileMessage: each ].
 
-    self compileByte: PopStackTop.
-    self depthDecr: 1.
-    (messages at: messages size) acceptVisitor: self.
+    self depthDecr: 1; compileByte: PopStackTop.
+    self compileMessage: messages last.
 ! !
 
 "--------------------------------------------------------------------"
@@ -619,29 +618,26 @@ acceptAssignmentNode: aNode
 acceptMessageNode: aNode
     "RBMessageNode contains a message send. Its instance variable are
      a receiver, selector, and arguments."
-    | dup specialSelector args litIndex |
+    | specialSelector |
 
-    dup := dupReceiver. dupReceiver := false.
- 
     aNode receiver = SuperVariable ifTrue: [
        self compileSendToSuper: aNode.
        ^true
     ].
 
-    (VMSpecialMethods includesKey: aNode selector) ifTrue: [
-       specialSelector := VMSpecialMethods at: aNode selector.
-       (specialSelector isNil and: [aNode receiver isBlock and: [ dup not ]])
-           ifTrue: [
-               (self compileWhileLoop: aNode) ifTrue: [^false]
-           ]
-       ].
+    specialSelector := VMSpecialMethods at: aNode selector ifAbsent: [ nil ].
+    specialSelector isNil ifFalse: [
+       (self perform: specialSelector with: aNode) ifTrue: [ ^false ] ].
 
     aNode receiver acceptVisitor: self.
-    dup ifTrue: [ self depthIncr; compileByte: DupStackTop ].
-    specialSelector isNil ifFalse: [
-       (self perform: specialSelector with: aNode) ifTrue: [^false]
-    ].
+    self compileMessage: aNode
+!
 
+compileMessage: aNode
+    "RBMessageNode contains a message send. Its instance variable are
+     a receiver, selector, and arguments.  The receiver has already
+     been compiled."
+    | args litIndex |
     aNode arguments do: [ :each | each acceptVisitor: self ].
 
     VMSpecialSelectors at: aNode selector ifPresent: [ :idx |
@@ -662,6 +658,7 @@ compileWhileLoop: aNode
 
     | whileBytecodes argBytecodes jumpOffsets |
 
+    aNode receiver isBlock ifFalse: [ ^false ].
     (aNode receiver arguments isEmpty and: [
        aNode receiver body temporaries isEmpty ]) ifFalse: [ ^false ].
 
@@ -731,6 +728,7 @@ compileSendToSuper: aNode
 
 compileTimesRepeat: aNode
     | block |
+    aNode receiver acceptVisitor: self.
     block := aNode arguments first.
     (block arguments isEmpty and: [
        block body temporaries isEmpty ]) ifFalse: [ ^false ].
@@ -740,6 +738,7 @@ compileTimesRepeat: aNode
 
 compileLoop: aNode
     | stop step block |
+    aNode receiver acceptVisitor: self.
     aNode arguments do: [ :each |
        stop := step.                   "to:"
        step := block.                  "by:"
@@ -757,6 +756,7 @@ compileLoop: aNode
 
 compileBoolean: aNode
     | bc1 ret1 bc2 selector |
+    aNode receiver acceptVisitor: self.
     aNode arguments do: [ :each |
         (each arguments isEmpty and: [
            each body temporaries isEmpty ]) ifFalse: [ ^false ].




reply via email to

[Prev in Thread] Current Thread [Next in Thread]