"======================================================================
|
|   CompiledMethod Method Definitions
|
|   $Revision: 1.7.5$
|   $Date: 2000/05/28 16:56:52$
|   $Author: pb$
|
 ======================================================================"


"======================================================================
|
| Copyright 1988-92, 1994-95, 1999, 2000 Free Software Foundation, Inc.
| Written by Steve Byrne.
|
| This file is part of the GNU Smalltalk class library.
|
| The GNU Smalltalk class library is free software; you can redistribute it
| and/or modify it under the terms of the GNU Lesser General Public License
| as published by the Free Software Foundation; either version 2.1, or (at
| your option) any later version.
| 
| The GNU Smalltalk class library is distributed in the hope that it will be
| useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
| General Public License for more details.
| 
| You should have received a copy of the GNU Lesser General Public License
| along with the GNU Smalltalk class library; see the file COPYING.LESSER.
| If not, write to the Free Software Foundation, 59 Temple Place - Suite
| 330, Boston, MA 02111-1307, USA.  
|
 ======================================================================"



CompiledCode variableByteSubclass: #CompiledMethod
       instanceVariableNames: 'descriptor '
       classVariableNames: ''
       poolDictionaries: ''
       category: 'Language-Implementation'
!

CompiledMethod comment:
'I represent methods that have been compiled.  I can recompile
methods from their source code, I can invoke Emacs to edit the source code
for one of my instances, and I know how to access components of my
instances.' !


!CompiledMethod class methodsFor: 'lean images'!

stripSourceCode
    "Remove all the references to method source code from the system"
    self allInstancesDo: [ :each | each stripSourceCode ]
! !


!CompiledMethod methodsFor: 'basic'!

methodCategory
    "Answer the method category"
    ^descriptor category
!

methodCategory: aCategory
    "Set the method category to the given string"
    descriptor category: aCategory
!

methodSourceCode
    "Answer the method source code (a FileSegment or String or nil)"
    ^descriptor sourceFile = 'stdin'
	ifTrue: [ nil]
	ifFalse: [ descriptor sourceCode ]
!

methodSourceString
    "Answer the method source code as a string"
    ^descriptor sourceFile = 'stdin'
	ifTrue: [ nil]
	ifFalse: [ descriptor sourceString ]
!

methodSourceFile
    "Answer the file where the method source code is stored"
    ^descriptor sourceFile = 'stdin'
	ifTrue: [ nil]
	ifFalse: [ descriptor sourceFile ]
!

methodSourcePos
    "Answer the location where the method source code is stored in
     the methodSourceFile"
    ^descriptor  sourceFile = 'stdin'
	ifTrue: [ nil]
	ifFalse: [ descriptor sourcePos ]
!

= aMethod
    "Answer whether the receiver and aMethod are equal"

    self == aMethod ifTrue: [ ^true ].
    ^super = aMethod and: [
	descriptor = aMethod getDescriptor ]
!

hash
    "Answer an hash value for the receiver"

    ^super hash + (descriptor hash bitAnd: 16r1FFFFFFF)
! !



!CompiledMethod methodsFor: 'accessing'!

methodClass
    "Answer the class in which the receiver is installed."
    ^descriptor methodClass
!

methodClass: methodClass
    "Set the receiver's class instance variable"
    descriptor methodClass: methodClass
!

withNewMethodClass: class
    "Answer either the receiver or a copy of it, with the method class set
     to class"
    ^self methodClass isNil
	ifTrue: [ self methodClass: class; yourself ]
	ifFalse: [ self deepCopy methodClass: class; yourself ]
!

withNewMethodClass: class selector: selector
    "Answer either the receiver or a copy of it, with the method class set
     to class"
    ^(self withNewMethodClass: class) selector: selector; yourself
!

selector: aSymbol
    "Set the selector through which the method is called"
    descriptor selector: aSymbol.
!

selector
    "Answer the selector through which the method is called"
    ^descriptor selector
!

flags
    "Private - Answer the optimization flags for the receiver"
    ^((header bitShift: -27) bitAnd: 16r7)
!

primitive
    "Answer the primitive called by the receiver"
    ^(header bitShift: -17) bitAnd: 16r3FF
!

numArgs
    "Answer the number of arguments for the receiver"
    ^header bitAnd: 16r1F
!

numTemps
    "Answer the number of temporaries for the receiver"
    ^(header bitShift: -11) bitAnd: 16r3F
!

stackDepth
    "Answer the number of stack slots needed for the receiver"
    ^((header bitShift: -5) bitAnd: 16r3F) * 4
! !



!CompiledMethod methodsFor: 'printing'!

storeOn: aStream
    "Print code to create the receiver on aStream"
    aStream
	nextPutAll: '((';
	print: self class;
	nextPutAll: ' literals: ';
	store: ((1 to: self numLiterals) collect: [ :i | self literalAt: i ]);
	nextPutAll: ' numArgs: ';
	store: self numArgs;
	nextPutAll: ' numTemps: ';
	store: self numTemps;
	nextPutAll: ' primitive: ';
	store: self primitive;
	nextPutAll: ' bytecodes: ';
	store: self asByteArray;
	nextPutAll: ' source: ';
	store: self methodSourceCode;
	nextPutAll: ') makeLiteralsReadOnly; setDescriptor: ';
	store: self getDescriptor;
	nextPutAll: '; yourself)'
! !


!CompiledMethod methodsFor: 'private-printing'!

printHeaderOn: aStream
    "Private - Disassemble the method header to aStream"

    aStream
	nextPutAll: '  Header Flags: ';
	nl;
	nextPutAll: '    flags: ';
	print:      self flags;
	nl;
	nextPutAll: '    primitive index: ';
	print:      self primitive;
	nl;
	nextPutAll: '    number of arguments: ';
	print:      self numArgs;
	nl;
	nextPutAll: '    number of temporaries: ';
	print:      self numTemps;
	nl;
	nextPutAll: '    number of literals: ';
	print:      self numLiterals;
	nl;
	nextPutAll: '    needed stack slots: ';
	print:      self stackDepth;
	nl
! !


!CompiledCode methodsFor: 'printing'!

printOn: aStream
    "Print the receiver's class and selector on aStream"

    aStream
	nextPutAll: (self methodClass nameIn: Namespace current);
	nextPutAll: '>>#';
	nextPutAll: self selector
! !


!CompiledMethod methodsFor: 'private'!

postCopy
    "Private - Make a deep copy of the descriptor and literals.
     Don't need to replace the method header and bytecodes, since they
     are integers."

    super postCopy.
    descriptor := descriptor copy.
    literals := literals deepCopy.
    self makeLiteralsReadOnly
!

makeLiteralsReadOnly
    ^self makeLiteralsReadOnly: literals
!

makeLiteralsReadOnly: array
    array do: [ :each |
	each class == Array ifTrue: [ self makeLiteralsReadOnly: each ].
	each makeReadOnly: true
    ]
!

initialize
    descriptor := MethodInfo new
!

getDescriptor
    ^descriptor
!

stripSourceCode
    descriptor stripSourceCode
!

header: hdr literals: lits
     "The structure of a method header is as follows (from interp.h)

	3                   2                   1 
      1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |.|.|flg| prim index        | #temps    | depth / 4 | #args   |1|
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

     stackdepth 6 bits 6..11
     temporarycount 6 bits 12..17
     argscount 5 bits 1..5
     primitiveIndex 10 bits 18..27
     flags 2 bits 29..28
     flags 0 -- call the primitive indexed by primIndex or do nothing
     flags 1 -- return self
     flags 2 -- return instance variable in primIndex
     flags 3 -- return first literal"
    header := hdr.
    literals := lits.
    Behavior flushCache
!

numBytecodes
    "Answer the number of bytecodes in the receiver"
    ^(self basicSize) - (self bytecodeStart)
!

bytecodeStart
    "Answer the index where the bytecodes start - 1"
    ^0
! !
