Open timfel opened 8 years ago
Let's get this done next week, so we can start providing error codes in primfail errors...
It is possible to expose an error code via a primitive pragma, e.g. <primitive: 128 error: ec>
.
We need to find out how the OSVM fills the ec
temp var. However, PrimitiveFailedError
s used to contain error messages in RSqueak. But the generation of new strings turned out to be a performance overhead, especially in case of a frequently called primitive which is allowed to fail (these cases apparently exist). Postponing this again...
Well, ec
typically is a SmallInteger
or a Symbol
, so things that defy vm-level allocation.
But ec
could also be a ByteString
from the message defined in the PrimitiveFailedError("Some error message")
. This would be very helpful especially when developing plugins and such.
See
Smalltalk specialObjectsArray at: 52
and this from an old VMMaker:
ObjectMemory>>initializePrimitiveErrorCodes
"Define the VM's primitive error codes. N.B. these are
replicated in platforms/Cross/vm/sqVirtualMachine.h."
"ObjectMemory initializePrimitiveErrorCodes"
| pet |
PrimErrTableIndex := 51. "Zero-relative"
"See SmalltalkImage>>recreateSpecialObjectsArray for the table definition.
If the table exists and is large enough the corresponding entry is returned as
the primitive error, otherwise the error is answered numerically."
pet := Smalltalk specialObjectsArray at: PrimErrTableIndex + 1 ifAbsent: [#()].
pet isArray ifFalse: [pet := #()].
PrimNoErr := 0. "for helper methods that need to answer success or an error code."
PrimErrGenericFailure := pet indexOf: nil ifAbsent: 1.
PrimErrBadReceiver := pet indexOf: #'bad receiver' ifAbsent: 2.
PrimErrBadArgument := pet indexOf: #'bad argument' ifAbsent: 3.
PrimErrBadIndex := pet indexOf: #'bad index' ifAbsent: 4.
PrimErrBadNumArgs := pet indexOf: #'bad number of arguments' ifAbsent: 5.
PrimErrInappropriate := pet indexOf: #'inappropriate operation' ifAbsent: 6.
PrimErrUnsupported := pet indexOf: #'unsupported operation' ifAbsent: 7.
PrimErrNoModification := pet indexOf: #'no modification' ifAbsent: 8.
PrimErrNoMemory := pet indexOf: #'insufficient object memory' ifAbsent: 9.
PrimErrNoCMemory := pet indexOf: #'insufficient C memory' ifAbsent: 10.
PrimErrNotFound := pet indexOf: #'not found' ifAbsent: 11.
PrimErrBadMethod := pet indexOf: #'bad method' ifAbsent: 12.
PrimErrNamedInternal := pet indexOf: #'internal error in named primitive machinery' ifAbsent: 13.
PrimErrObjectMayMove := pet indexOf: #'object may move' ifAbsent: 14.
PrimErrLimitExceeded := pet indexOf: #'resource limit exceeded' ifAbsent: 15
Also all senders of InterpreterPrimitives>>primitiveFailFor:
have SmallInteger
s as argument,
Here's how StackInterpreter/Cog do it:
StackInterpreter>>justActivateNewMethod
"..."
"Pass primitive error code to last temp if method receives it (indicated by an
initial long store temp bytecode). We don't need to check that newMethod
actually has a primitive because the initial 129 only occurs if there is one."
primFailCode ~= 0 ifTrue:
[(objectMemory byteAtPointer: instructionPointer + 1) = 129 "long store temp" ifTrue:
[errorCode := self getErrorObjectFromPrimFailCode.
self stackTopPut: errorCode "nil if primFailCode == 1, or primFailCode"].
primFailCode := 0].
StackInterpreter>>getErrorObjectFromPrimFailCode
"Answer the errorCode object to supply to a failing primitive method that accepts one.
If there is a primitive error table and the primFailCode is a valid index there-in answer
the coprresponding entry in the table, otherwise simply answer the code as an integer."
| table |
primFailCode > 0 ifTrue:
[table := objectMemory splObj: PrimErrTableIndex.
primFailCode <= ((objectMemory lastPointerOf: table) // self bytesPerWord) ifTrue:
[^objectMemory fetchPointer: primFailCode - 1 ofObject: table]].
^objectMemory integerObjectOf: primFailCode
Basically, when a primitive fails there might be a "storeIntoTemp" bytecode directly after the primitive call, this will store an error code into the temp. We need to find a way to pass this error code into the method activation (or refactor how our primitive fails)