Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generically allow primitives to return an error code #130

Open
timfel opened this issue Jul 18, 2016 · 8 comments
Open

Generically allow primitives to return an error code #130

timfel opened this issue Jul 18, 2016 · 8 comments

Comments

@timfel
Copy link
Member

timfel commented Jul 18, 2016

No description provided.

@timfel
Copy link
Member Author

timfel commented Feb 22, 2017

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)

@fniephaus fniephaus self-assigned this Apr 6, 2017
@fniephaus
Copy link
Member

Let's get this done next week, so we can start providing error codes in primfail errors...

@fniephaus
Copy link
Member

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, PrimitiveFailedErrors 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...

@fniephaus fniephaus removed their assignment Apr 10, 2017
@krono
Copy link
Member

krono commented Apr 10, 2017

Well, ec typically is a SmallInteger or a Symbol, so things that defy vm-level allocation.

@fniephaus
Copy link
Member

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.

@krono
Copy link
Member

krono commented Apr 10, 2017

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

@krono
Copy link
Member

krono commented Apr 10, 2017

Also all senders of InterpreterPrimitives>>primitiveFailFor: have SmallIntegers as argument,

  • positive means index into the Primitive error table
  • negative means application defined error code

@krono
Copy link
Member

krono commented Apr 10, 2017

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants