JavaContext.st
author Claus Gittinger <cg@exept.de>
Wed, 10 Dec 2003 11:06:45 +0100
changeset 2114 cbdc4c02a8e2
parent 2108 ca8c4e7db2e8
child 2150 3dbc038c151a
permissions -rw-r--r--
ExecutionErrorSignal -> ExecutionError

"
 COPYRIGHT (c) 1997 by eXept Software AG
	      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.
"



"{ Package: 'stx:libjava' }"

Context variableSubclass:#JavaContext
	instanceVariableNames:'exArg exPC byteCode constPool method'
	classVariableNames:''
	poolDictionaries:''
	category:'Languages-Java-Support'
!

!JavaContext class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1997 by eXept Software AG
	      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.
"


! !

!JavaContext methodsFor:'ST context mimicri'!

arg1Index
    "the java stack contains the receiver in a non-static
     method, as slot 0. Therefore, the first arg is found at slot2
     if this is for a non-static method"

    self method isStatic ifTrue:[
	^ 1
    ].
    ^ 2
!

argAt:n
    "return the i'th argument (1..nArgs)"

    ^ self at:(self arg1Index - 1 + n)

    "Created: / 2.1.1998 / 17:54:13 / cg"
    "Modified: / 2.1.1998 / 21:39:30 / cg"
!

argAt:n put:value
    "change the i'th argument (1..nArgs)"

    ^ super argAt:(self arg1Index - 1 + n) put:value

    "Created: / 2.1.1998 / 17:54:34 / cg"
    "Modified: / 2.1.1998 / 21:35:19 / cg"
!

args
    "return an array filled with the arguments of this context"

    |n|

    n := self numArgs.
    n == 0 ifTrue:[
	"/ little optimization here - avoid creating empty containers
	^ #()
    ].

    ^ (Array new:n) replaceFrom:1 to:n with:self startingAt:(self arg1Index).

    "Created: / 2.1.1998 / 17:54:57 / cg"
    "Modified: / 2.1.1998 / 21:34:44 / cg"
!

argsAndVars
    "return an array filled with the arguments and variables of this context"

    |n|

    n := self numArgs + self numVars.
    n == 0 ifTrue:[
	"/ little optimization here - avoid creating empty containers
	^ #()
    ].
    ^ (Array new:n) replaceFrom:1 to:n with:self startingAt:(self arg1Index).

    "Created: / 2.1.1998 / 17:55:14 / cg"
    "Modified: / 13.1.1998 / 15:44:56 / cg"
!

lineNumber
    |nr pc|

    pc := self pc.

"/ 'ask line for pc:' print. pc printCR.
    pc isNil ifTrue:[
	nr := self lineNumberFromMethod.
	nr notNil ifTrue:[
	    ^ nr
	].
	" '-> 0 [a]' printCR. " 
	^0
    ].

    nr := self method lineNumberForPC:pc.
    nr isNil ifTrue:[
	nr := self lineNumberFromMethod.
	nr notNil ifTrue:[
	    ^ nr
	].
	" '-> 0 [b]' printCR. " 
	^ 0
    ].
"/ '-> ' print. nr printCR.
     ^ nr.

    "Created: / 1.5.1996 / 15:05:47 / cg"
    "Modified: / 15.1.1998 / 15:25:29 / cg"
!

lineNumberFromMethod
    |m|

    m := self method.
    m notNil ifTrue:[
	^ m lineNumber
    ].
    ^ nil

    "Created: / 4.1.1998 / 23:34:45 / cg"
    "Modified: / 4.1.1998 / 23:35:55 / cg"
!

method
    "the method may be found in the interpreter temps ..."

    method isJavaMethod ifTrue:[^ method].
    ^ super method

    "Created: / 1.5.1996 / 15:03:43 / cg"
    "Modified: / 25.9.1999 / 23:26:40 / cg"
!

numArgs
    "return the number of args.
     Redefined since Java keeps the receiver of a non-static method
     at local slot 1."

    |n|

    n := super numArgs.
    self method isStatic ifFalse:[
	n := n - 1
    ].
    ^ n

    "Created: / 2.1.1998 / 22:21:24 / cg"
!

numTemps
    "return the number of temporary variables of the Method.
     Redefined since Java keeps the receiver of a non-static method
     at local slot 1."

    |n|

    n := self size - super numVars - super numArgs.
    ^ n

    "Created: / 13.1.1998 / 16:52:32 / cg"
    "Modified: / 13.1.1998 / 17:23:27 / cg"
!

numVars
    "return the number of locals.
     Redefined since Java keeps the receiver of a non-static method
     at local slot 0 and holds the args as locals."

    |n|

    n := super numVars.
    ^ (n - self numArgs) max:0

    "Created: / 13.1.1998 / 17:03:08 / cg"
    "Modified: / 13.1.1998 / 17:25:16 / cg"
!

pc
    lineNr isNil ifTrue:[^ nil].
    ^ lineNr bitAnd:16rFFFF

    "Created: / 4.1.1998 / 23:33:48 / cg"
    "Modified: / 10.11.1998 / 13:20:12 / cg"
!

quickLineNumber
    "the lineNumber - without decompiling"

    ^ self method quickLineNumberForPC:self pc

    "Created: / 10.11.1998 / 14:20:30 / cg"
!

selector
    "the selector can be extracted from the method.
     the method may be found in the interpreter temps ..."

    |s m|

    selector isNil ifTrue:[
	m := self method.
	m notNil ifTrue:[
	    ^ m name
	]
    ].
    ^ super selector

    "Modified: / 30.12.1997 / 17:22:06 / cg"
    "Created: / 30.12.1997 / 17:23:47 / cg"
!

setPC:newPC
    lineNr := newPC

    "Created: / 5.1.1998 / 00:09:02 / cg"
!

temporaries
    "return an array filled with the arguments and variables of this context"

    |n nSkipped|

    "/ the flas-numVars includes the receiver and args
    nSkipped := super numVars "self numArgs + self numVars".
    "/ but my context setup is args+numvars.
    nSkipped := super numArgs + super numVars.

    n := self size - nSkipped.
    n == 0 ifTrue:[
	"/ little optimization here - avaoid creating empty containers
	^ #()
    ].

    ^ (Array new:n) replaceFrom:1 to:n with:self startingAt:nSkipped+1.

    "Created: / 13.1.1998 / 15:44:12 / cg"
    "Modified: / 13.1.1998 / 17:22:54 / cg"
!

vars 
    "return an array filled with the local variables of this context"

    |nonVars mySize|

    mySize := self numVars.
    mySize == 0 ifTrue:[
	"/ little optimization here - avaoid creating empty containers
	^ #()
    ].
    nonVars := (self arg1Index-1) + self numArgs.
    ^ (Array new:mySize) replaceFrom:1 to:mySize with:self startingAt:nonVars+1

    "Created: / 13.1.1998 / 16:48:16 / cg"
! !

!JavaContext methodsFor:'exception handler support'!

exceptionArg:aJavaException
    exArg := aJavaException.

    "Created: / 7.1.1998 / 21:36:56 / cg"
!

exceptionArg:aJavaException pc:newPc
    exArg := aJavaException.
    exPC := newPc.

    "Created: / 7.1.1998 / 21:36:56 / cg"
!

markForException
    "set the exception handler flag in the receiver.
     The JVM needs this to enter an exception handler instead of restarting
     from the beginning (when the context is restarted).
     - a highly internal mechanism and not for public use."

    flags := flags bitOr:16r08000000.

"/ %{  /* NOCONTEXT */
"/      __INST(flags) = (OBJ)((INT)__INST(flags) | __MASKSMALLINT(__JAVA_EX_PEND));
"/ %}

    "Modified: 13.12.1995 / 19:05:22 / cg"
! !

!JavaContext methodsFor:'printing & storing'!

receiverPrintString
    "return a string describing the receiver of the context" 

    |receiverClass receiverClassName newString implementorClass searchClass|

"/ %{
"/     /*
"/      * special handling for (invalid) free objects.
"/      * these only appear if some primitiveCode does not correctly use SEND macros,
"/      * which may lead to sends to free objects. In normal operation, this 'cannot' happen.
"/      */ 
"/     if (__isNonNilObject(__INST(receiver)) && (__qClass(__INST(receiver))==nil)) {
"/         receiverClassName = __MKSTRING("FreeObject");
"/     }
"/ %}.
"/    receiverClassName notNil ifTrue:[^ receiverClassName].

    receiverClass := receiver class.
    "/ java has no class-methods ...
    receiverClass := receiverClass theNonMetaclass.

    receiverClassName := receiverClass nameInBrowser.
    (receiverClass == SmallInteger) ifTrue:[
        newString := '(' , receiver printString , ') ' , receiverClassName
    ] ifFalse:[
        newString := receiverClassName
    ].

    "
     kludge to avoid slow search for containing class
    "
    (selector ~~ #doIt and:[selector ~~ #doIt:]) ifTrue:[
        implementorClass := self methodClass. 
    ].
    implementorClass notNil ifTrue: [
        (implementorClass ~~ receiverClass) ifTrue: [
            newString := newString , '>>>',
                         implementorClass nameInBrowser printString
        ]
    ] ifFalse:[
        searchClass := self searchClass.
        searchClass ~~ receiverClass ifTrue:[
            newString := newString , '>>>' , searchClass nameInBrowser
        ].
"/        "
"/         kludge for doIt - these unbound methods are not
"/         found in the classes methodDictionary
"/        "
"/        (selector ~~ #doIt and:[selector ~~ #doIt:]) ifTrue:[
"/            newString := newString , '>>>**NONE**'
"/        ]
    ].

    ^ newString
! !

!JavaContext methodsFor:'queries'!

hasStackToShow
    "private interface to the debugger.
     Smalltalk contexts return false here - other language frames
     (i.e. Java frames) may want to show the evaluation stack"

    ^ true

    "Modified: / 13.5.1997 / 16:31:12 / cg"
    "Created: / 7.5.1998 / 01:23:57 / cg"
!

isJavaContext
    "return true, if this is a javaContext."

    ^ true

    "Created: / 8.5.1998 / 21:23:47 / cg"
!

stackFrame
    "private interface to the debugger."

    ^ (1 to:self size) collect:[:i | self at:i]

    "Created: / 7.5.1998 / 01:26:19 / cg"
! !

!JavaContext class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libjava/JavaContext.st,v 1.34 2002-11-22 20:12:40 cg Exp $'
! !