The Trunk: Kernel-eem.1318.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Kernel-eem.1318.mcz

commits-2
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1318.mcz

==================== Summary ====================

Name: Kernel-eem.1318
Author: eem
Time: 11 March 2020, 6:49:23.875063 pm
UUID: 25265ede-0f88-439d-8800-8a39e3f1898a
Ancestors: Kernel-eem.1317

Read-only object support.

Have ModificationForbidden allow retrying modification without resuming (retryModificationNoResume) or resuming (retryModificatio).  Ideally this would just be retryModification and resume but Pharo got there first and compatibility is a virtue.

Add BinaryModificationForbidden to support Array and the elementsExchangeIdentityWith: become machinery, and simplify the Behavior adoptInstance: mchinery.  Decouople resumeValue from newValue to allow Array and the elementsExchangeIdentityWith: become machinery to answer the correct result.

Extend the execution simulation machionery to correctly simulate attempting to assign the inst vars of read-only objects.

Add Object class>>releaseNotes as a scratch pad for people to add things that should appear in the release notes.

=============== Diff against Kernel-eem.1317 ===============

Item was removed:
- ----- Method: Behavior>>adoptInstance:ignore: (in category 'read-only objects') -----
- adoptInstance: anInstance ignore: ignore
- "This method exists only to adapt to the pattern used in ModificationForbidden>>retryModification,
- which expects all mutators to take an argument."
- ^self adoptInstance: anInstance!

Item was changed:
  ----- Method: Behavior>>modificationForbiddenAdopting: (in category 'read-only objects') -----
  modificationForbiddenAdopting: anObject
+ ^(BinaryModificationForbidden new
- ^(ModificationForbidden new
  mirror: self
  object: anObject
  index: nil
  newValue: nil
+ retrySelector: #adoptInstance:) signal!
- retrySelector: #adoptInstance:ignore:) signal!

Item was added:
+ ModificationForbidden subclass: #BinaryModificationForbidden
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Kernel-Exceptions'!
+
+ !BinaryModificationForbidden commentStamp: 'eem 3/11/2020 15:56' prior: 0!
+ A BinaryModificationForbidden is a variation of ModificationForbidden for messages that need neither fieldIndex nor newObject, such as elementsExchangeIdentityWith: and adoptInstance:. It overrides the retryModification method.
+
+ Instance Variables
+ !

Item was added:
+ ----- Method: BinaryModificationForbidden>>retryModification (in category 'retrying') -----
+ retryModification
+ mirror perform: retrySelector with: object.
+ self resume: resumptionValue!

Item was added:
+ ----- Method: BinaryModificationForbidden>>retryModificationNoResume (in category 'retrying') -----
+ retryModificationNoResume
+ mirror perform: retrySelector with: object!

Item was added:
+ ----- Method: Context>>attemptToAssign:to:withIndex: (in category 'read-only objects') -----
+ attemptToAssign: value to: anObject withIndex: index
+ "Sent by the execution simulation machinery when attempting to assign an instance
+ variable of an read-only object.  This mimics the VM's send of attemptToAssign:withIndex:
+ when trying to do the same. Upon return, executing will resume *after* the inst var assignment.
+ This method differs from Object>>attemptToAssign:withIndex: in not doing a Context>>jump,
+ which does not simulate properly."
+
+ self modificationForbiddenFor: anObject instVarAt: index put: value!

Item was changed:
  ----- Method: Context>>modificationForbiddenFor:at:put: (in category 'read-only objects') -----
+ modificationForbiddenFor: target at: index put: anObject
- modificationForbiddenFor: target at: index put: aCharacter
  ^(ModificationForbidden new
  mirror: self
  object: target
  index: index
+ newValue: anObject
- newValue: aCharacter
  retrySelector: #object:basicAt:put:) signal!

Item was changed:
  ----- Method: Context>>modificationForbiddenFor:instVarAt:put: (in category 'read-only objects') -----
+ modificationForbiddenFor: target instVarAt: index put: anObject
- modificationForbiddenFor: target instVarAt: index put: aCharacter
  ^(ModificationForbidden new
  mirror: self
  object: target
  index: index
+ newValue: anObject
- newValue: aCharacter
  retrySelector: #object:instVarAt:put:) signal!

Item was changed:
  ----- Method: Context>>object:instVarAt:put: (in category 'mirror primitives') -----
  object: anObject instVarAt: anIndex put: aValue
  "Primitive. Store a value into a fixed variable in the argument anObject.
  The numbering of the variables corresponds to the named instance
  variables.  Fail if the index is not an Integer or is not the index of a
+ fixed variable, or if anObject is read-only.  Answer the value stored as
+ the result. Using this message violates the  principle that each object
+ has sovereign control over the storing of values into its instance variables.
+ Essential for the debugger. See Object documentation whatIsAPrimitive."
- fixed variable.  Answer the value stored as the result. Using this
- message violates the  principle that each object has sovereign control
- over the storing of values into its instance variables. Essential for the
- debugger. See Object documentation whatIsAPrimitive."
 
  <primitive: 174 error: ec>
+ ec == #'no modification' ifTrue:
+ [^self modificationForbiddenFor: anObject instVarAt: anIndex put: aValue].
  self primitiveFailed!

Item was changed:
  ----- Method: Context>>popIntoLiteralVariable: (in category 'instruction decoding') -----
  popIntoLiteralVariable: value
  "Simulate the action of bytecode that removes the top of the stack and
+ stores it into a literal variable of my method. If the receiver is read-only
+ this will provoke a send of #attemptToAssign:withIndex:"
- stores it into a literal variable of my method."
 
+ | top result |
+ top := self pop.
+ result := self simulatedObject: value instVarAt: ValueIndex put: top.
+ ^(self object: result eqeq: top)
+ ifTrue: [self]
+ ifFalse: [result]!
- self object: value instVarAt: ValueIndex put: self pop!

Item was changed:
  ----- Method: Context>>popIntoReceiverVariable: (in category 'instruction decoding') -----
  popIntoReceiverVariable: offset
  "Simulate the action of bytecode that removes the top of the stack and
+ stores it into an instance variable of my receiver. If the receiver is read-only
+ this will provoke a send of #attemptToAssign:withIndex:"
- stores it into an instance variable of my receiver."
 
+ | top result |
+ top := self pop.
+ result := self simulatedObject: self receiver instVarAt: offset + 1 put: top.
+ ^(self object: result eqeq: top)
+ ifTrue: [self]
+ ifFalse: [result]!
- self object: self receiver instVarAt: offset + 1 put: self pop!

Item was added:
+ ----- Method: Context>>simulatedObject:instVarAt:put: (in category 'read-only objects') -----
+ simulatedObject: anObject instVarAt: anIndex put: aValue
+ "Primitive. Store a value into a fixed variable in the argument anObject.
+ The numbering of the variables corresponds to the named instance
+ variables.  Fail if the index is not an Integer or is not the index of a
+ fixed variable, or if anObject is read-only. This version correctly simulates
+ assigning to a read-only object. Answer the value stored as the result.
+ Using this message violates the  principle that each object has sovereign
+ control over the storing of values into its instance variables. Essential for
+ the debugger. See Object documentation whatIsAPrimitive."
+
+ <primitive: 174 error: ec>
+ ec == #'no modification' ifTrue:
+ [^self send: #attemptToAssign:to:withIndex: to: self with: {aValue. anObject. anIndex} lookupIn: self class].
+ self primitiveFailed!

Item was changed:
  ----- Method: Context>>storeIntoLiteralVariable: (in category 'instruction decoding') -----
  storeIntoLiteralVariable: value
  "Simulate the action of bytecode that stores the top of the stack into a
+ literal variable of my method. If the receiver is read-only
+ this will provoke a send of #attemptToAssign:withIndex:"
- literal variable of my method."
 
+ | top result |
+ top := self top.
+ result := self simulatedObject: value instVarAt: ValueIndex put: top.
+ ^(self object: result eqeq: top)
+ ifTrue: [self]
+ ifFalse: [result]!
- self object: value instVarAt: ValueIndex put: self top!

Item was changed:
  ----- Method: Context>>storeIntoReceiverVariable: (in category 'instruction decoding') -----
  storeIntoReceiverVariable: offset
  "Simulate the action of bytecode that stores the top of the stack into an
+ instance variable of my receiver. If the receiver is read-only
+ this will provoke a send of #attemptToAssign:withIndex:"
- instance variable of my receiver."
 
+ | top result |
+ top := self top.
+ result := self simulatedObject: self receiver instVarAt: offset + 1 put: top.
+ ^(self object: result eqeq: top)
+ ifTrue: [self]
+ ifFalse: [result]!
- self object: self receiver instVarAt: offset + 1 put: self top!

Item was changed:
  Exception subclass: #ModificationForbidden
+ instanceVariableNames: 'mirror object fieldIndex newValue retrySelector resumptionValue'
- instanceVariableNames: 'mirror object fieldIndex newValue retrySelector'
  classVariableNames: ''
  poolDictionaries: ''
  category: 'Kernel-Exceptions'!
 
+ !ModificationForbidden commentStamp: 'eem 3/11/2020 15:46' prior: 0!
- !ModificationForbidden commentStamp: 'eem 3/11/2020 11:53' prior: 0!
  This exception is raised when attempting to mutate a read-only object.
 
  My instances have 5 fields to be able to reproduce the modification via the retryModification method.
 
+ mirror <Context|Behavior|Array> the object that will perform the modification on object if modificationRetried
+ object <Object> read-only object that attempted to mutate
+ index <SmallInteger | nil> index of the field in the object mutated, relevant for the corresponding selector
+ value <Object> value that was attempted to be stored into the read-only object
+ selector <Symbol> selector that can be used to reproduce the mutation (#object:basicAt:put:, #object:instVarAt:put:, etc)!
- mirror <Context|Behavior> the Context or Behavior that will perform the modification if modificationRetried
- object <Object> read-only object that attempted to mutate
- index <SmallInteger | nil> index of the field in the object mutated, relevant for the corresponding selector
- value <Object> value that was attempted to be stored into the read-only object
- selector <Symbol> selector that can be used to reproduce the mutation (typically, #object:basicAt:put:, #object:instVarAt:put:, etc.)!

Item was changed:
  ----- Method: ModificationForbidden>>fieldIndex (in category 'accessing') -----
  fieldIndex
+ ^fieldIndex!
- ^ fieldIndex!

Item was added:
+ ----- Method: ModificationForbidden>>mirror:object:index:newValue:resumptionValue:retrySelector: (in category 'accessing') -----
+ mirror: aContext object: anObject index: index newValue: value resumptionValue: valueToResumeWith retrySelector: selector
+
+ mirror := aContext.
+ object := anObject.
+ fieldIndex := index.
+ newValue := value.
+ retrySelector := selector.
+ resumptionValue := valueToResumeWith!

Item was changed:
  ----- Method: ModificationForbidden>>mirror:object:index:newValue:retrySelector: (in category 'accessing') -----
  mirror: aContext object: anObject index: index newValue: value retrySelector: selector
 
  mirror := aContext.
  object := anObject.
  fieldIndex := index.
  newValue := value.
+ retrySelector := selector.
+ resumptionValue := value!
- retrySelector := selector!

Item was changed:
  ----- Method: ModificationForbidden>>newValue (in category 'accessing') -----
  newValue
+ ^newValue!
- ^ newValue!

Item was changed:
  ----- Method: ModificationForbidden>>object (in category 'accessing') -----
  object
+ ^object!
- ^ object!

Item was added:
+ ----- Method: ModificationForbidden>>resume (in category 'controlling') -----
+ resume
+ "Roll back thisContext to self and resume.  Execute unwind blocks when rolling back.  ASSUMES self is a sender of thisContext"
+
+ self resume: resumptionValue!

Item was added:
+ ----- Method: ModificationForbidden>>resumptionValue (in category 'accessing') -----
+ resumptionValue
+ ^resumptionValue!

Item was added:
+ ----- Method: ModificationForbidden>>resumptionValue: (in category 'accessing') -----
+ resumptionValue: anObject
+ resumptionValue := anObject!

Item was changed:
  ----- Method: ModificationForbidden>>retryModification (in category 'retrying') -----
  retryModification
  fieldIndex
  ifNotNil: [mirror perform: retrySelector with: object with: fieldIndex with: newValue]
  ifNil: [mirror perform: retrySelector with: object with: newValue].
+ self resume: resumptionValue!
- self resume: newValue!

Item was added:
+ ----- Method: ModificationForbidden>>retryModificationNoResume (in category 'retrying') -----
+ retryModificationNoResume
+ fieldIndex
+ ifNotNil: [mirror perform: retrySelector with: object with: fieldIndex with: newValue]
+ ifNil: [mirror perform: retrySelector with: object with: newValue]!

Item was changed:
  ----- Method: ModificationForbidden>>retrySelector (in category 'accessing') -----
  retrySelector
+ ^retrySelector!
- ^ retrySelector!

Item was added:
+ ----- Method: Object class>>releaseNotes (in category 'documentation') -----
+ releaseNotes
+ "This is a scratch pad of release3 notes for the 6.0 release this version is building towards.
+ Feel free to add to this comment mention of things that should appear in the release notes.
+
+ Read-only object support and read-only literals.
+ the current VM supports a per-object read-only bit and will fail to modify objects marked with this flag bit.
+ This affects assignments to inst vars, to indexed fields in at:put: primitives, attempts to become read-only
+ objects into non-read-only objects, and attempts to change the class of read-only objects.  All such attempts
+ raise a ModificationForbidden error.  The error may retry the modification once the object has been made
+ writable.  The compiler has been modified to make all literals read-only."
+
+ self error: 'comment only'!

Item was changed:
  ----- Method: Object>>attemptToAssign:withIndex: (in category 'write barrier') -----
  attemptToAssign: value withIndex: index
+ "Called by the VM when attempting to assign an instance variable of an read-only object.
+ Upon return, executing will resume *after* the inst var assignment. If the inst var
+ mutation has to be performed, do it manually here in the call back with instVarAt:put:.
+ This method has to return *no* value by jumping to the context's sender"
- "Called by the VM when assigning an instance variable of an immutable object.
- Upon return, executing will resume *after* the inst var assignment. If the inst var mutation has to be
- performed, do it manually here in the call back with instVarAt:put:.
- This method has to return *no* value by jumping to the context's sender"
 
  thisContext modificationForbiddenFor: self instVarAt: index put: value.
 
  thisContext sender jump
  "CAN'T REACH"!