Skip to content

Commit

Permalink
First implementation of the primitiveNewOldSpace and primitiveNewWith…
Browse files Browse the repository at this point in the history
…ArgOldSpace
  • Loading branch information
jordanmontt committed Oct 5, 2023
1 parent 2fd313f commit b335adf
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 0 deletions.
29 changes: 29 additions & 0 deletions smalltalksrc/VMMaker/InterpreterPrimitives.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -2770,6 +2770,20 @@ InterpreterPrimitives >> primitiveNewMethod [
self pop: 3 thenPush: theMethod
]

{ #category : #'object access primitives' }
InterpreterPrimitives >> primitiveNewOldSpace [
"Allocate a new pinned fixed-size instance. Fail if the allocation would leave
less than lowSpaceThreshold bytes free. This *will not* cause a GC :-)"

(objectMemory instantiateClassInOldSpace: self stackTop)
ifNotNil: [ :obj | self pop: argumentCount + 1 thenPush: obj ]
ifNil: [
self primitiveFailFor:
((objectMemory isFixedSizePointerFormat: (objectMemory instSpecOfClass: self stackTop))
ifTrue: [ PrimErrNoMemory ]
ifFalse: [ PrimErrBadReceiver ]) ]
]

{ #category : #'object access primitives' }
InterpreterPrimitives >> primitiveNewPinned [

Expand Down Expand Up @@ -2798,6 +2812,21 @@ InterpreterPrimitives >> primitiveNewWithArg [
ifNotNil: [ :obj | self pop: argumentCount + 1 thenPush: obj ]
]

{ #category : #'object access primitives' }
InterpreterPrimitives >> primitiveNewWithArgOldSpace [

| size instSpec |
size := self positiveMachineIntegerValueOf: self stackTop.

(objectMemory instantiateClassInOldSpace: (self stackValue: 1) indexableSize: size)
ifNotNil: [ :obj | self pop: argumentCount + 1 thenPush: obj ]
ifNil: [
instSpec := objectMemory instSpecOfClass: (self stackValue: 1).
self primitiveFailFor: (((objectMemory isIndexableFormat: instSpec) and: [
(objectMemory isCompiledMethodFormat: instSpec) not ]) ifTrue: [ PrimErrNoMemory ]
ifFalse: [ PrimErrBadReceiver ]) ]
]

{ #category : #'object access primitives' }
InterpreterPrimitives >> primitiveNewWithArgPinned [
| size instSpec |
Expand Down
70 changes: 70 additions & 0 deletions smalltalksrc/VMMaker/Spur32BitMemoryManager.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,76 @@ Spur32BitMemoryManager >> instantiateClass: classObj indexableSize: nElements is
^newObj
]

{ #category : #instantiation }
Spur32BitMemoryManager >> instantiateClassInOldSpace: classObj indexableSize: nElements [
<api>
<var: #nElements type: #usqInt>
"Allocate an instance of a variable class, excepting CompiledMethod."
| instSpec classFormat numSlots classIndex newObj fillValue |
classFormat := self formatOfClassSafe: classObj.
classFormat == -1 ifTrue:
[self primitiveFailFor: PrimErrBadReceiver. "no format"
^nil].
instSpec := self instSpecOfClassFormat: classFormat.
classIndex := self rawHashBitsOf: classObj.
fillValue := 0.
instSpec caseOf: {
[self arrayFormat] ->
[numSlots := nElements.
fillValue := nilObj].
[self indexablePointersFormat] ->
[numSlots := (self fixedFieldsOfClassFormat: classFormat) + nElements.
fillValue := nilObj].
[self weakArrayFormat] ->
[numSlots := (self fixedFieldsOfClassFormat: classFormat) + nElements.
fillValue := nilObj].
[self sixtyFourBitIndexableFormat] ->
[nElements > (self maxSlotsForAlloc / 2) ifTrue:
[coInterpreter primitiveFailFor: PrimErrUnsupported.
^nil].
numSlots := nElements * 2].
[self firstLongFormat] ->
[(classIndex = ClassFloatCompactIndex and: [nElements ~= 2]) ifTrue:
[coInterpreter primitiveFailFor: PrimErrBadReceiver.
^nil].
numSlots := nElements].
[self firstShortFormat] ->
[numSlots := nElements + 1 // 2.
instSpec := instSpec + (nElements bitAnd: 1)].
[self firstByteFormat] ->
[numSlots := nElements + 3 // 4.
instSpec := instSpec + (4 - nElements bitAnd: 3)] }
otherwise: "non-indexable"
["Some Squeak images include funky fixed subclasses of abstract variable
superclasses. e.g. DirectoryEntry as a subclass of ArrayedCollection.
The (Threaded)FFIPlugin expects to be able to instantiate ExternalData via
this method.
Hence allow fixed classes to be instantiated here iff nElements = 0."
(nElements ~= 0 or: [instSpec > self lastPointerFormat]) ifTrue:
[coInterpreter primitiveFailFor: PrimErrBadReceiver.
^nil].
numSlots := self fixedFieldsOfClassFormat: classFormat.
fillValue := nilObj].
classIndex = 0 ifTrue:
[classIndex := self ensureBehaviorHash: classObj.
classIndex < 0 ifTrue:
[coInterpreter primitiveFailFor: classIndex negated.
^nil]].

numSlots > self maxSlotsForAlloc ifTrue:
[coInterpreter primitiveFailFor: PrimErrUnsupported.
^ nil].
newObj := self
allocateSlotsInOldSpace: numSlots
format: instSpec
classIndex: classIndex.

newObj ifNotNil:
[self fillObj: newObj numSlots: numSlots with: fillValue]
ifNil: [ self primitiveFailFor: PrimErrNoMemory ].
^newObj
]

{ #category : #instantiation }
Spur32BitMemoryManager >> instantiateCompiledMethodClass: classObj indexableSize: nElements [
<var: #nElements type: #usqInt>
Expand Down
69 changes: 69 additions & 0 deletions smalltalksrc/VMMaker/Spur64BitMemoryManager.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,75 @@ Spur64BitMemoryManager >> instantiateClass: classObj indexableSize: nElements is
^newObj
]

{ #category : #instantiation }
Spur64BitMemoryManager >> instantiateClassInOldSpace: classObj indexableSize: nElements [
<api>
<var: #nElements type: #usqInt>
"Allocate an instance of a variable class, excepting CompiledMethod."
| instSpec classFormat numSlots classIndex newObj fillValue |
classFormat := self formatOfClassSafe: classObj.
classFormat == -1 ifTrue:
[self primitiveFailFor: PrimErrBadReceiver. "no format"
^nil].
instSpec := self instSpecOfClassFormat: classFormat.
classIndex := self rawHashBitsOf: classObj.
fillValue := 0.
instSpec caseOf: {
[self arrayFormat] ->
[numSlots := nElements.
fillValue := nilObj].
[self indexablePointersFormat] ->
[numSlots := (self fixedFieldsOfClassFormat: classFormat) + nElements.
fillValue := nilObj].
[self weakArrayFormat] ->
[numSlots := (self fixedFieldsOfClassFormat: classFormat) + nElements.
fillValue := nilObj].
[self sixtyFourBitIndexableFormat] ->
[numSlots := nElements].
[self firstLongFormat] ->
[(classIndex = ClassFloatCompactIndex and: [nElements ~= 2]) ifTrue:
[coInterpreter primitiveFailFor: PrimErrBadReceiver.
^nil].
numSlots := nElements + 1 // 2.
instSpec := instSpec + (nElements bitAnd: 1)].
[self firstShortFormat] ->
[numSlots := nElements + 3 // 4.
instSpec := instSpec + (4 - nElements bitAnd: 3)].
[self firstByteFormat] ->
[numSlots := nElements + 7 // 8.
instSpec := instSpec + (8 - nElements bitAnd: 7)] }
otherwise: "non-indexable"
["Some Squeak images include funky fixed subclasses of abstract variable
superclasses. e.g. DirectoryEntry as a subclass of ArrayedCollection.
The (Threaded)FFIPlugin expects to be able to instantiate ExternalData via
this method.
Hence allow fixed classes to be instantiated here iff nElements = 0."
(nElements ~= 0 or: [instSpec > self lastPointerFormat]) ifTrue:
[coInterpreter primitiveFailFor: PrimErrBadReceiver.
^nil].
numSlots := self fixedFieldsOfClassFormat: classFormat.
fillValue := nilObj].

classIndex = 0 ifTrue:
[classIndex := self ensureBehaviorHash: classObj.
classIndex < 0 ifTrue:
[coInterpreter primitiveFailFor: classIndex negated.
^nil]].

numSlots > self maxSlotsForAlloc ifTrue:
[coInterpreter primitiveFailFor: PrimErrUnsupported.
^ nil].
newObj := self
allocateSlotsInOldSpace: numSlots
format: instSpec
classIndex: classIndex .

newObj ifNotNil:
[self fillObj: newObj numSlots: numSlots with: fillValue]
ifNil: [ self primitiveFailFor: PrimErrNoMemory ].
^newObj
]

{ #category : #instantiation }
Spur64BitMemoryManager >> instantiateCompiledMethodClass: classObj indexableSize: nElements [
<var: #nElements type: #usqInt>
Expand Down
30 changes: 30 additions & 0 deletions smalltalksrc/VMMaker/SpurMemoryManager.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -6981,6 +6981,36 @@ SpurMemoryManager >> instantiateClass: classObj isPinned: isPinned [
^newObj
]

{ #category : #instantiation }
SpurMemoryManager >> instantiateClassInOldSpace: classObj [
| instSpec classFormat numSlots classIndex newObj |
classFormat := self formatOfClassSafe: classObj.
classFormat == -1 ifTrue:
[self primitiveFailFor: PrimErrBadReceiver. "no format"
^nil].
instSpec := self instSpecOfClassFormat: classFormat.
(self isFixedSizePointerFormat: instSpec) ifFalse:
[self primitiveFailFor: PrimErrBadReceiver. "bad format"
^nil].
classIndex := self ensureBehaviorHash: classObj.
classIndex < 0 ifTrue:
[coInterpreter primitiveFailFor: classIndex negated.
^nil].
numSlots := self fixedFieldsOfClassFormat: classFormat.
newObj := self allocateSlotsInOldSpace: numSlots format: instSpec classIndex: classIndex.
newObj ifNotNil:
[self fillObj: newObj numSlots: numSlots with: nilObj]
ifNil: [ self primitiveFailFor: PrimErrNoMemory ].
^newObj
]

{ #category : #instantiation }
SpurMemoryManager >> instantiateClassInOldSpace: classObj indexableSize: nElements [
<api>

^ self subclassResponsibility
]

{ #category : #instantiation }
SpurMemoryManager >> instantiateCompiledMethodClass: classObj indexableSize: nElements [
<var: #nElements type: #usqInt>
Expand Down

0 comments on commit b335adf

Please sign in to comment.