ExecutableFunction.st
author Claus Gittinger <cg@exept.de>
Thu, 23 Nov 1995 12:17:00 +0100
changeset 623 6795a71e39d1
parent 530 07d0bce293c9
child 829 fc386319f41c
permissions -rw-r--r--
checkin from browser

"
 COPYRIGHT (c) 1994 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

Object subclass:#ExecutableFunction
	 instanceVariableNames:'code*'
	 classVariableNames:'ExecutionErrorSignal InvalidCodeSignal'
	 poolDictionaries:''
	 category:'Kernel-Methods'
!

!ExecutableFunction class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1994 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    This is an abstract class, to merge common attributes of all kinds of
    executable code objects; i.e. non-ST functions, Blocks and Methods
    and whatever there might be in the future.

    Instance variables:

      code        <not_an_object>   the function pointer to the machine code.
				    Not accessable from smalltalk code.
				    (notice the '*' in the instVarNames definition)



    Class variables:

      ExecutionErrorSignal          parent of all execution errors
				    (not raised itself)

      InvalidCodeSignal             codeObject is not executable

    NOTICE: layout known by runtime system and compiler - do not change
"
!

version
    ^ '$Header: /cvs/stx/stx/libbasic/ExecutableFunction.st,v 1.18 1995-11-23 11:17:00 cg Exp $'
! !

!ExecutableFunction class methodsFor:'initialization'!

initialize
    InvalidCodeSignal isNil ifTrue:[
	ExecutionErrorSignal := ErrorSignal newSignalMayProceed:true.
	ExecutionErrorSignal nameClass:self message:#executionErrorSignal.
	ExecutionErrorSignal notifierString:'execution error'.

	InvalidCodeSignal := ExecutionErrorSignal newSignalMayProceed:true.
	InvalidCodeSignal nameClass:self message:#invalidCodeSignal.
	InvalidCodeSignal notifierString:'invalid code-object - not executable'.
    ]
! !

!ExecutableFunction class methodsFor:'Signal constants'!

executionErrorSignal
    "return the parent-signal of all execution errors"

    ^ ExecutionErrorSignal
! !

!ExecutableFunction class methodsFor:'queries'!

isBuiltInClass
    "this class is known by the run-time-system"

    ^ true
! !

!ExecutableFunction methodsFor:'accessing'!

code
    "return the code field. This is not an object but the address of the machine instructions. 
     Therefore an integer representing the code-address is returned"

%{  /* NOCONTEXT */
    extern OBJ __MKUINT();
    unsigned addr;

    if (_INST(code_) != nil) {
	addr = (int)_INST(code_);
	if (addr <= _MAX_INT) {
	    RETURN ( __MKSMALLINT(addr) );
	}
	RETURN ( __MKUINT(addr));
    }
%}.
    ^ nil
!

instVarAt:index
    "have to catch instVar access to code - since its no object"

    (index == 1) ifTrue:[^ self code].
    ^ super instVarAt:index
!

instVarAt:index put:value
    "have to catch instVar access to code - since its no object"

    (index == 1) ifTrue:[^ self code:value].
    ^ super instVarAt:index put:value
! !

!ExecutableFunction methodsFor:'binary storage'!

readBinaryContentsFrom: stream manager: manager
    "make certain, that no invalid function addresses are created."

    super readBinaryContentsFrom: stream manager: manager.
    self code:nil.
! !

!ExecutableFunction methodsFor:'error handling'!

invalidCode
    "this error is triggered by the interpreter when something is wrong
     with the code object (any error not handled by Method-signals).
     In this case, the VM sends this to the bad method/block (the receiver).
     Can only happen when the Compiler/runtime system is broken or
     someone played around."

    ^ InvalidCodeSignal raise.
! !

!ExecutableFunction methodsFor:'printing & storing'!

printOn:aStream
    |addr|

    addr := self code.
    addr isNil ifTrue:[^ super printOn:aStream].

    aStream nextPutAll:self class name; nextPutAll:'(address: 0x';
	    nextPutAll:(addr printStringRadix:16); nextPutAll:')'
! !

!ExecutableFunction methodsFor:'private accessing'!

code:anAddress
    "set the code field - DANGER ALERT. 
     This is not an object but the address of the machine instructions.
     Therefore the argument must be an integer representing this address.
     You can crash Smalltalk very badly when playing around here ...
     This method is for compiler support and very special cases (debugging) only
     - do not use"

%{  /* NOCONTEXT */

    if (__isSmallInteger(anAddress))
	_INST(code_) = (OBJ)(_intVal(anAddress));
    else {
	_INST(code_) = (OBJ)(__longIntVal(anAddress));
    }
%}
! !

ExecutableFunction initialize!