[Pkg] The Trunk: Kernel-ar.332.mcz

commits at source.squeak.org commits at source.squeak.org
Tue Dec 22 11:40:38 UTC 2009


Andreas Raab uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-ar.332.mcz

==================== Summary ====================

Name: Kernel-ar.332
Author: ar
Time: 22 December 2009, 12:39:41 pm
UUID: 417d4df8-ccf7-484a-8c19-63b0402d4921
Ancestors: Kernel-dtl.331

CompiledMethodTrailer phase 1: Main classes

=============== Diff against Kernel-dtl.331 ===============

Item was added:
+ ----- Method: CompiledMethodTrailer>>clear (in category 'initialize-release') -----
+ clear
+ 	kind := #NoTrailer.
+ 	size := 1.
+ 	data := encodedData := method := nil!

Item was added:
+ ----- Method: CompiledMethodTrailer>>tempNames: (in category 'accessing') -----
+ tempNames: aString
+ 	"Embed the temp names string into compiled method trailer, 
+ 	pick best compression method"
+ 	| temp |
+ 	self clear.
+ 	kind := #TempsNamesQCompress.
+ 	data := aString.
+ 	
+ 	self encode.
+ 	temp := encodedData.
+ 
+ 	kind := #TempsNamesZip.
+ 	self encode.
+ 	encodedData size > temp size ifTrue: [
+ 		encodedData := temp.
+ 		kind := #TempsNamesQCompress.
+ 		size := encodedData size.
+ 		]!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeTempsNamesZip (in category 'decoding') -----
+ encodeTempsNamesZip
+ 
+ 	"data is string with method's temporary names, encode it using zip compression"
+ 	self encodeUsingZip
+ 	
+ 	"data is string with method's source code, encoded using qCompress method"
+ 
+ 
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeLengthField (in category 'private') -----
+ decodeLengthField
+ 
+ 	"used in various encodings, where length field is preceeding the last trailer byte.
+ 	Two least significant bits in last byte denoting the number of bytes for length field"
+ 	
+ 	| numBytes pos length |
+ 
+ 	pos := method size.
+ 	numBytes := ((method at: pos) bitAnd: 3) + 1.
+ 	
+ 	length := 0.
+ 	1 to: numBytes do: [:i |
+ 		length := length << 8 + (method at: pos - i ).
+ 		].
+ 	size := 1 + numBytes + length.
+ 	
+ 	^ length!

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeEmbeddedSourceZip (in category 'decoding') -----
+ decodeEmbeddedSourceZip
+ 
+ 	"data is string with method's source code, compressed using zip compression"
+ 	self decodeZip.!

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeSourceBySelector (in category 'decoding') -----
+ decodeSourceBySelector
+ 
+ 	"no data, size = 1"
+ 	
+ 	size := 1.!

Item was added:
+ CompiledMethodTrailer subclass: #OldMethodTrailer
+ 	instanceVariableNames: ''
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'Kernel-Methods'!

Item was added:
+ ----- Method: CompiledMethodTrailer>>kind (in category 'accessing') -----
+ kind
+ 	"Answer a symbolic name of trailer kind.
+ 	See #trailerKinds on class side and class comment for details"
+ 	
+ 	^ kind!

Item was added:
+ ----- Method: CompiledMethodTrailer>>hasTempNames (in category 'testing') -----
+ hasTempNames
+ 	^ kind == #TempsNamesQCompress or: [ kind == #TempsNamesZip ]!

Item was added:
+ ----- Method: CompiledMethodTrailer>>qDecompress (in category 'decoding') -----
+ qDecompress 
+ 	"Trailer is compressed string using qCompress method + length field + 1 byte
+ 	
+ 	Decompress strings compressed by qCompress:.
+ 	Most common 11 chars get values 0-10 packed in one 4-bit nibble;
+ 	next most common 52 get values 12-15 (2 bits) * 16 plus next nibble;
+ 	escaped chars get three nibbles"
+ 	| len str input |
+ 	
+ 	len := self decodeLengthField.
+  	input := (ReadStream on: method from: method size - size+1 to: method size - size + len).
+ 	
+ 	str := String streamContents:
+ 		[:strm | | nextNibble nibble peek charTable |
+ 		charTable :=  "Character encoding table must match qCompress:"
+ 		'ear tonsilcmbdfghjkpquvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345[]()'.
+ 		peek := true.
+ 		nextNibble := [peek
+ 						ifTrue: [peek := false. input peek ifNil: [0] ifNotNil: [:b| b // 16]]
+ 						ifFalse: [peek := true. input next ifNil: [0] ifNotNil: [:b| b \\ 16]]].
+ 		[input atEnd] whileFalse:
+ 			[(nibble := nextNibble value) = 0
+ 				ifTrue: [input atEnd ifFalse:
+ 						[strm nextPut: (Character value: nextNibble value * 16 + nextNibble value)]]
+ 				ifFalse:
+ 					[nibble <= 11
+ 						ifTrue:
+ 							[strm nextPut: (charTable at: nibble)]
+ 						ifFalse:
+ 							[strm nextPut: (charTable at: nibble-12 * 16 + nextNibble value)]]]].
+ 			
+ 	data := str convertFromEncoding: 'utf8'!

Item was added:
+ ----- Method: OldMethodTrailer class>>testOldStuffIsFine (in category 'as yet unclassified') -----
+ testOldStuffIsFine
+ "OldMethodTrailer testOldStuffIsFine"
+ 	| meth |
+ 	CompiledMethod allInstancesDo: [:m |
+ 		| trailer |	
+ 		trailer := self new method: m.
+ 		self assert: (m endPC = trailer endPC).
+ 	].
+ 	meth := CompiledMethod toReturnSelf copyWithTempNames: #( a b c d e).
+ 	self assert: (self new method: meth) tempNames = meth tempNamesString.
+ 	self assert: (CompiledMethod toReturnSelfTrailerBytes: (self new tempNames: 'a b c d e ')) tempNamesString
+ 	 = meth tempNamesString.
+ 	!

Item was added:
+ ----- Method: CompiledMethodTrailer class>>empty (in category 'as yet unclassified') -----
+ empty
+ 	"answer the empty trailer"
+ 	^ self new!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeTempsNamesQCompress (in category 'encoding') -----
+ encodeTempsNamesQCompress
+ 
+ 	"data is string with method's temporary names, encode it using qCompress method"
+ 	self encodeUsingQCompress
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeUndefined (in category 'encoding') -----
+ encodeUndefined
+ 
+ 	self error: 'use of an undefined kind of trailer encoding'!

Item was added:
+ ----- Method: CompiledMethodTrailer>>testEncoding (in category 'testing') -----
+ testEncoding
+ 
+ 	"Since we are using basic protocol (#at:, #at:put: , #size) for accessing compiled method data,
+ 	we can pass the ByteArray instance into #method: accessor and check if encoding/decoding 
+ 	operations	is symmetrical.
+ 	Use this method only for unit-testing purposes"
+ 	
+ 	encodedData ifNil: [ self encode ].
+ 	^ CompiledMethodTrailer new method: encodedData!

Item was added:
+ ----- Method: CompiledMethodTrailer class>>new (in category 'as yet unclassified') -----
+ new
+ 	^ self trailerClass basicNew initialize!

Item was added:
+ ----- Method: CompiledMethodTrailer>>sourceCode (in category 'accessing') -----
+ sourceCode
+ 	"Answer the source code of compiled method.
+ 	Note: it does not attempts to read from source files using sourcePointer,
+ 	nor reconstruct the source code using temp names"
+ 	
+ 	(kind == #EmbeddedSourceQCompress or: [ kind == #EmbeddedSourceZip ]) ifTrue: [
+ 		^ data ].
+ 	
+ 	kind == #SourceBySelector ifTrue: [
+ 		^ method methodClass getSourceCodeBySelector: method selector ].
+ 	
+ 	kind == #SourceByStringIdentifier ifTrue: [
+ 		^ method methodClass getSourceCodeByIdentifier: data ].
+ 
+ 	^ nil!

Item was added:
+ ----- Method: CompiledMethodTrailer>>sourceCode: (in category 'accessing') -----
+ sourceCode: aString
+ 	"Embed the source code into compiled method trailer, 
+ 	pick best compression method"
+ 	| temp |
+ 	self clear.
+ 	kind := #EmbeddedSourceQCompress.
+ 	data := aString.
+ 	
+ 	self encode.
+ 	temp := encodedData.
+ 
+ 	kind := #EmbeddedSourceZip.
+ 	self encode.
+ 	encodedData size > temp size ifTrue: [
+ 		encodedData := temp.
+ 		kind := #EmbeddedSourceQCompress.
+ 		size := encodedData size.
+ 		]!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeClearedTrailer (in category 'encoding') -----
+ encodeClearedTrailer
+ 
+ 	"A cleared trailer is replaced by #NoTrailer, when used for encoding"
+ 	self clear.
+ 	kind := #NoTrailer.
+ 	
+ 	^ self encode!

Item was added:
+ ----- Method: CompiledMethodTrailer>>method: (in category 'initialize-release') -----
+ method: aMethod
+ 
+ 	| flagByte |
+ 
+ 	data := size := nil.
+ 	method := aMethod.
+ 	flagByte := method at: (method size).
+ 
+ 	"trailer kind encoded in 6 high bits of last byte"
+ 	kind := self class trailerKinds at: 1+(flagByte>>2).
+ 
+ 	"decode the trailer bytes"
+ 	self perform: ('decode' , kind) asSymbol.
+ 	
+ 	"after decoding the trailer, size must be set"
+ 	self assert: (size notNil).
+ 	
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer class>>trailerClass (in category 'as yet unclassified') -----
+ trailerClass
+ 	^ OldMethodTrailer!

Item was added:
+ ----- Method: CompiledMethodTrailer>>sourceIdentifier (in category 'accessing') -----
+ sourceIdentifier
+ 	"Trailer is used to indicate that method's source code can be retrieved by 
+ 	sending #getSourceCodeByIdentifier: message to method's class" 
+ 
+ 	^ (kind == #SourceByStringIdentifier) ifTrue: [ data ] ifFalse: [ nil ].
+ 
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeEmbeddedSourceQCompress (in category 'decoding') -----
+ decodeEmbeddedSourceQCompress
+ 
+ 	"data is string with method's source code, encoded using qCompress method"
+ 	self qDecompress.!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeEmbeddedSourceQCompress (in category 'encoding') -----
+ encodeEmbeddedSourceQCompress
+ 
+ 	"data is string with method's source code, encode it using qCompress method"
+ 	self encodeUsingQCompress
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer class>>usingNewFormat (in category 'as yet unclassified') -----
+ usingNewFormat
+ 	^ self trailerClass == CompiledMethodTrailer!

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeSourcePointer (in category 'decoding') -----
+ decodeSourcePointer
+ 
+ 	"Trailer is a source pointer"
+ 	| msz |
+ 	
+ 	size := 4.
+ 	msz := method size.
+ 	data := (method at: msz) - 251 << 8 + (method at: msz-1) << 8
+ 	 + (method at: msz-2) << 8 + (method at: msz-3).
+ 	
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer class>>convertTrailers (in category 'as yet unclassified') -----
+ convertTrailers
+ 	| toConvert converted |
+ 	"Protect against doing this in already converted image."
+ 	self assert: (self usingNewFormat not).
+ 	
+ 	toConvert := OrderedCollection new.
+ 	CompiledMethod allInstancesDo: [:m |
+ 		"we need to convert only methods which has no sourcePointer "
+ 		m sourcePointer = 0 ifTrue: [
+ 			toConvert add: m.
+ 			].
+ 		].
+ 
+ 	toConvert := toConvert asArray.
+ 	converted := toConvert collect: [:m |
+ 		m copyWithTrailerBytes: self basicNew initialize. "clear the trailers"
+ 	].
+ 
+ 	toConvert elementsExchangeIdentityWith: converted asArray.
+ 
+ 	"replace the #trailerClass method in CompiledMethodTrailer class"
+ 	
+ 	self class compile: 'trailerClass
+ 	^ CompiledMethodTrailer' 
+ 	
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeNoTrailer (in category 'decoding') -----
+ decodeNoTrailer
+ 	"Not much to decode here"
+ 	size := 1. !

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeSourceByStringIdentifier (in category 'encoding') -----
+ encodeSourceByStringIdentifier
+ 
+ 	"A method source is determined by a class + string identifier"
+ 	| utf8str len |
+ 	
+ 	self assert: (data isString).
+ 	
+ 	encodedData := ByteArray streamContents: [:str |
+ 		utf8str := (data convertToEncoding: 'utf8') asByteArray.
+ 		str nextPutAll: utf8str.
+ 		len := self encodeLengthField: utf8str size.
+ 		str nextPutAll: len.
+ 		str nextPut: self kindAsByte + (len size -1)
+ 	]!

Item was added:
+ ----- Method: CompiledMethodTrailer>>kindAsByte (in category 'private') -----
+ kindAsByte
+ 	| index |
+ 	index := self class trailerKinds indexOf: kind.
+ 	self assert: (index ~~ 0).
+ 
+ 	^ (index - 1) << 2!

Item was added:
+ ----- Method: OldMethodTrailer>>tempNames (in category 'as yet unclassified') -----
+ tempNames
+ 
+ 	"Answer the string, containing the temps names or nil "
+ 	^ (kind == #OldTempsNames) 
+ 		ifTrue: [ data ] ifFalse: [ nil ]!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeLengthField: (in category 'private') -----
+ encodeLengthField: integer
+ 
+ 	| bytes value |
+ 	self assert: (integer > 0).
+ 
+ 	value := integer.
+ 	
+ 	bytes := ByteArray streamContents: [:str |
+ 		[ value > 0 ] whileTrue: [
+ 			str nextPut: (value bitAnd: 255).
+ 			value := value >> 8 ]].
+ 
+ 	"no more than 4 bytes for length field"
+ 	self assert: (bytes size <=4).
+ 
+ 	^ bytes!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeSourcePointer (in category 'encoding') -----
+ encodeSourcePointer
+ 
+ 	encodedData := ByteArray new: 4.
+ 	encodedData at: 4 put: (data >> 24) + 251.
+ 
+ 	1 to: 3 do: [:i |
+ 		encodedData at: 4-i put: ((data bitShift: (i-3)*8) bitAnd: 16rFF)]!

Item was added:
+ ----- Method: OldMethodTrailer>>encodeNoTrailer (in category 'as yet unclassified') -----
+ encodeNoTrailer
+ 
+ 	encodedData := #(0 0 0 0)!

Item was added:
+ ----- Method: CompiledMethodTrailer>>sourcePointer: (in category 'accessing') -----
+ sourcePointer: ptr
+ 
+ 	self clear.
+ 	data := ptr.
+ 	"see if we can encode pointer using 4-byte trailer"
+ 	kind := (ptr between: 16r1000000 and: 16r4FFFFFF) 
+ 		ifTrue: [ #SourcePointer ] ifFalse: [ #VarLengthSourcePointer ].
+ 	!

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeSourceByStringIdentifier (in category 'decoding') -----
+ decodeSourceByStringIdentifier
+ 
+ 	"A method source is determined by a class + string identifier"
+ 	| len |
+ 	
+ 	len := self decodeLengthField.
+ 
+ 	data := (ReadStream on: method from: method size - size+1 to: method size - size + len) contents asString convertFromEncoding: 'utf8'!

Item was added:
+ ----- Method: CompiledMethodTrailer>>hasSourcePointer (in category 'testing') -----
+ hasSourcePointer
+ 	^  kind == #SourcePointer or: [ kind == #VarLengthSourcePointer ] !

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeVarLengthSourcePointer (in category 'decoding') -----
+ decodeVarLengthSourcePointer
+ 
+ 	| pos shift |
+ 	
+ 	pos := method size-1.
+ 	shift := data := 0.
+ 	
+ 	[ | value | 
+ 		value := method at: pos.
+ 		data := (value bitAnd: 16r7F) << shift + data.
+ 		pos := pos - 1.
+ 		shift := shift + 7.
+ 		value > 127 ] whileTrue.
+ 
+ 	size := method size - pos.!

Item was added:
+ ----- Method: OldMethodTrailer>>tempNames: (in category 'as yet unclassified') -----
+ tempNames: aString
+ 	"Embed the temp names string into compiled method trailer"
+ 
+ 	self clear.
+ 	kind := #OldTempsNames.
+ 	data := aString.
+ 	
+ 	self encode.
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer class>>trailerKinds (in category 'as yet unclassified') -----
+ trailerKinds
+ 	" see class comment for description"
+ ^#(
+ "000000" #NoTrailer
+ "000001" #ClearedTrailer
+ "000010" #TempsNamesQCompress
+ "000011" #TempsNamesZip
+ "000100" #SourceBySelector
+ "000101" #SourceByStringIdentifier
+ "000110" #EmbeddedSourceQCompress
+ "000111" #EmbeddedSourceZip
+ "001000" #VarLengthSourcePointer
+ "001001" #ExtendedKind
+ "001010" #Undefined
+ "001011" #Undefined
+ "001100" #Undefined
+ "001101" #Undefined
+ "001110" #Undefined
+ "001111" #Undefined
+ "010000" #Undefined
+ "010001" #Undefined
+ "010010" #Undefined
+ "010011" #Undefined
+ "010100" #Undefined
+ "010101" #Undefined
+ "010110" #Undefined
+ "010111" #Undefined
+ "011000" #Undefined
+ "011001" #Undefined
+ "011010" #Undefined
+ "011011" #Undefined
+ "011100" #Undefined
+ "011101" #Undefined
+ "011110" #Undefined
+ "011111" #Undefined
+ "100000" #Undefined
+ "100001" #Undefined
+ "100010" #Undefined
+ "100011" #Undefined
+ "100100" #Undefined
+ "100101" #Undefined
+ "100110" #Undefined
+ "100111" #Undefined
+ "101000" #Undefined
+ "101001" #Undefined
+ "101010" #Undefined
+ "101011" #Undefined
+ "101100" #Undefined
+ "101101" #Undefined
+ "101110" #Undefined
+ "101111" #Undefined
+ "110000" #Undefined
+ "110001" #Undefined
+ "110010" #Undefined
+ "110011" #Undefined
+ "110100" #Undefined
+ "110101" #Undefined
+ "110110" #Undefined
+ "110111" #Undefined
+ "111000" #Undefined
+ "111001" #Undefined
+ "111010" #Undefined
+ "111011" #Undefined
+ "111100" #Undefined
+ "111101" #Undefined
+ "111110" #Undefined
+ "111111" #SourcePointer
+ )!

Item was added:
+ ----- Method: OldMethodTrailer>>decodeOldEmptyTrailer (in category 'as yet unclassified') -----
+ decodeOldEmptyTrailer
+ 
+ 	"1 to 4 zero bytes"
+ 	size := 0.
+ 	[ (method at: (method size - size)) = 0 and: [size <4]] whileTrue: [ size := size + 1].
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeEmbeddedSourceZip (in category 'encoding') -----
+ encodeEmbeddedSourceZip
+ 
+ 	"data is string with method's source code, encode it using Zip compression method"
+ 	self encodeUsingZip
+ !

Item was added:
+ Object subclass: #CompiledMethodTrailer
+ 	instanceVariableNames: 'data encodedData kind size method'
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'Kernel-Methods'!
+ 
+ !CompiledMethodTrailer commentStamp: 'Igor.Stasenko 12/13/2009 12:53' prior: 0!
+ I am responsible for encoding and decoding various kinds of compiled method trailer data.
+ I should not expose any binary data outside of myself, so all tools which working with compiled methods
+ should ask me to encode the meta-data, they want to be added to the compiled method trailer, as well as retrieve it.
+ 
+ To add a new kind of trailer, you should give it a proper name and define it in the #trailerKinds method at my class side.
+ Then you need to implement a corresponding #encode<your name> and #decode<your name> methods at instance side. Then add any public accessor methods, which will use a newly introduced trailer kind for communicating with outer layer(s).
+ 
+ An encodeXXX methods should store result (byte array) into encodedData instance variable.
+ 
+ A decodeXXX methods should read the data from compiled method instance, held by 'method' ivar,
+ and always set 'size' ivar (denoting a total length of trailer in compiled method) and optionally 'data' ivar which should keep a decoded data, ready to be used by outer layer(s) using accessor method(s) you providing.
+ 
+ The kind of compiled method trailer is determined by the last byte of compiled method.
+ 
+ The byte format used is following: 
+ 	"2rkkkkkkdd"
+ 
+ where 'k' bits stands for 'kind' , allowing totally 64 different kinds of method trailer
+ and 'd' bits is data.
+ 
+ Following is the list of currently defined trailer kinds:
+ 
+ NoTrailer , k = 000000, dd unused
+ method has no trailer, and total trailer size bytes is always 1
+ 
+ ClearedTrailer, k = 000001, 
+ method has cleared trailer (it was set to something else, but then cleared) 
+ dd+1  determines the number of bytes for size field, and size is a total length of trailer bytes
+ So a total length of trailer is: 1 + (dd + 1) + size
+ 
+ TempsNamesQCompress, k = 000010
+ the trailer contains a list of method temp names,  compressed using qCompress: method. 
+ dd+1  determines the number of bytes for size field, and size is a number of bytes of compressed buffer.
+ So a total length of trailer is:  1 + (dd + 1) + size
+ 
+ TempsNamesZip, k = 000011
+ the trailer contains a list of method temp names,  compressed using GZIP compression method. 
+ dd+1  determines the number of bytes for size field, and size is a number of bytes of compressed buffer
+ So a total length of trailer is: 1 + (dd + 1) + size
+ 
+ SourceBySelector, k = 000100
+ the trailer indicates , that method source is determined by a class + selector where it is installed to. 
+ Trailer size = 1.
+ 
+ SourceByStringIdentifier, k = 000101
+ the trailer indicates , that method source is determined by a class + some ByteString identifier. 
+ dd+1  determines the number of bytes for size of ByteString identifier, and size is number of bytes of string.
+ A total length of trailer is:  1 + (dd + 1) + size
+ 
+ EmbeddedSourceQCompress, k = 000110
+ the trailer contains an utf-8 encoded method source code, compressed using qCompress method
+ dd+1  determines the number of bytes for size field, and size is a number of bytes of compressed source code
+ A total length of trailer is:  1 + (dd + 1) + size
+ 
+ EmbeddedSourceZip, k = 000111
+ the trailer contains an utf-8 encoded method source code, comressed using GZIP 
+ dd+1  determines the number of bytes for size field, and size is a number of bytes of compressed buffer
+ A total length of trailer is:  1 + (dd + 1) + size
+ 
+ VarLengthSourcePointer, k = 001000
+ the trailer is variable-length encoded source pointer. 
+ dd bits is unused.
+ 
+ ExtendedKind, k = 001001
+ the next byte of trailer (one that prepends the last byte of compiled method)
+ denotes an extended kind of trailer, allowing to use additional 256 kinds of encoding method's trailer in future. 
+ 
+ SourcePointer, k = 111111 
+ the trailer is encoded source pointer. Total trailer size is 4-bytes 
+ (this kind of encoding is backwards compatible with most of existing compiled methods)
+ 
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>createMethod:header: (in category 'creating a method') -----
+ createMethod: numberOfBytesForAllButTrailer header: headerWord 
+ 	| meth |
+ 	encodedData ifNil: [ self encode ].
+ 	
+ 	meth := CompiledMethod newMethod: numberOfBytesForAllButTrailer + size header: headerWord.
+ 	
+ 	"copy the encoded trailer data"
+ 	
+ 	1 to: size do:
+ 		[:i | meth at: meth size - size + i put: (encodedData at: i)].
+ 
+ 	^ meth!

Item was added:
+ ----- Method: OldMethodTrailer>>decodeOldTempsNames (in category 'as yet unclassified') -----
+ decodeOldTempsNames
+ 
+ 	| sz flagByte |
+ 	flagByte := method at: (sz := method size).
+ 	(flagByte = 0 or: [flagByte > 251]) ifTrue: [^self error: 'not yet implemented'].
+ 	(flagByte = 251
+ 	 and: [(1 to: 3) allSatisfy: [:i | (method at: method size - i) = 0]]) ifTrue:
+ 		[^self error: 'not yet implemented'].
+ 	
+ 	size := flagByte <= 127
+ 			ifTrue: [flagByte + 1]
+ 			ifFalse: [ (flagByte - 128 * 128) + (method at: sz - 1) + 2].
+ 				
+ 	data := self qDecompressFrom: (flagByte <= 127
+ 								ifTrue:
+ 									[ReadStream on: method from: sz - flagByte to: sz - 1]
+ 								ifFalse:
+ 									[ReadStream on: method from: sz - (flagByte - 128 * 128 + (method at: sz - 1)) - 1 to: sz - 2])	
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeSourceBySelector (in category 'encoding') -----
+ encodeSourceBySelector
+ 
+ 	"A method source is determined by a class + selector where it is installed to"
+ 	encodedData := ByteArray with: self kindAsByte!

Item was added:
+ ----- Method: CompiledMethodTrailer>>qCompress: (in category 'private') -----
+ qCompress: string
+ 	"A very simple text compression routine designed for method temp names.
+ 	 Most common 11 chars get values 1-11 packed in one 4-bit nibble;
+ 	 the next most common get values 12-15 (2 bits) * 16 plus next nibble;
+ 	 unusual ones get three nibbles, the first being the escape nibble 0.
+ 
+ 	Answer the write stream with compressed data inside"
+ 
+ 	| utf8str stream ix oddNibble |
+ 
+ 	string isEmpty ifTrue:
+ 		[^self qCompress: ' '].
+ 	utf8str := string convertToEncoding: 'utf8'.
+ 
+ 	stream := WriteStream on: (ByteArray new: utf8str size).
+ 	oddNibble := nil.
+ 
+ 	utf8str do:	[:char |
+ 		ix := 'ear tonsilcmbdfghjkpquvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345[]()'
+ 			indexOf: char ifAbsent: 0.
+ 		(ix = 0
+ 			ifTrue:
+ 				[{ 0. char asInteger // 16. char asInteger \\ 16 }]
+ 			ifFalse:
+ 				[ix <= 11
+ 					ifTrue: [{ ix }]
+ 					ifFalse: [{ ix//16+12. ix\\16 }]])
+ 				do: [:nibble |
+ 					oddNibble
+ 						ifNotNil: [stream nextPut: oddNibble*16 + nibble. oddNibble := nil]
+ 						ifNil: [oddNibble := nibble]]].
+ 	oddNibble ifNotNil: "4 = 'ear tonsil' indexOf: Character space"
+ 		[stream nextPut: oddNibble * 16 + 4].
+ 	^ stream
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeUndefined (in category 'decoding') -----
+ decodeUndefined
+ 	self error: 'undefined method encoding'!

Item was added:
+ ----- Method: CompiledMethodTrailer>>initialize (in category 'initialize-release') -----
+ initialize
+ 	self clear!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeVarLengthSourcePointer (in category 'encoding') -----
+ encodeVarLengthSourcePointer
+ 
+ 	| value |
+ 	"source pointer must be >=0"
+ 	(self assert: data >= 0).
+ 	
+ 	value := data.
+ 	encodedData := ByteArray streamContents: [:str |
+ 		[value > 0] whileTrue: [
+ 			value > 127 ifTrue: [ str nextPut: 128 + (value bitAnd: 16r7F) ]
+ 				ifFalse: [ str nextPut: value. ].
+ 			value := value >> 7.
+ 			].
+ 		].
+ 	encodedData := encodedData reversed copyWith: (self kindAsByte)!

Item was added:
+ ----- Method: OldMethodTrailer>>encodeOldEmptyTrailer (in category 'as yet unclassified') -----
+ encodeOldEmptyTrailer
+ 
+ 	encodedData := #(0 0 0 0).
+ 	!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeUsingQCompress (in category 'encoding') -----
+ encodeUsingQCompress
+ 
+ 	"data is string, encode it using qCompress method"
+ 	| str length encodedLength |
+ 
+ 	self assert: data isString.
+ 	str := self qCompress: data.
+ 	length := str position.
+ 	encodedLength := self encodeLengthField: length.
+ 
+ 	str nextPutAll: encodedLength.
+ 	"trailing byte"
+ 	str nextPut: (self kindAsByte + encodedLength size - 1).
+ 	
+ 	encodedData := str contents
+ 	!

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeClearedTrailer (in category 'decoding') -----
+ decodeClearedTrailer
+ 	"Size is set in #decodeLengthField"
+ 
+ 	self decodeLengthField.
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>sourceIdentifier: (in category 'accessing') -----
+ sourceIdentifier: aString
+ 
+ 	"Trailer is used to indicate that method's source code can be retrieved by 
+ 	sending #getSourceCodeByIdentifier: message to method's class" 
+ 	
+ 	self clear.
+ 	data := aString.
+ 	kind := #SourceByStringIdentifier.
+ 	self encode.
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>isEmpty (in category 'testing') -----
+ isEmpty
+ 	^ kind == #NoTrailer or: [ kind == #ClearedTrailer ]!

Item was added:
+ ----- Method: CompiledMethodTrailer>>sourcePointer (in category 'accessing') -----
+ sourcePointer
+ 
+ 	^ (kind == #SourcePointer or: [ kind == #VarLengthSourcePointer ] )
+ 		ifTrue: [ data ]
+ 		ifFalse: [ 0 ]
+ !

Item was added:
+ ----- Method: OldMethodTrailer>>encodeOldTempsNames (in category 'as yet unclassified') -----
+ encodeOldTempsNames
+ 
+ 	
+ 	"A very simple text compression routine designed for method temp names.
+ 	 Most common 11 chars get values 1-11 packed in one 4-bit nibble;
+ 	 the next most common get values 12-15 (2 bits) * 16 plus next nibble;
+ 	 unusual ones get three nibbles, the first being the escape nibble 0.
+ 	 CompiledMethod>>endPC determines the maximum length of encoded
+ 	 output, which means 1 to (251 - 128) * 128 + 127, or 15871 bytes"
+ 	data isEmpty ifTrue: [ data := ' '].
+ 	encodedData := ByteArray streamContents:
+ 		[:strm | | ix oddNibble sz |
+ 		oddNibble := nil.
+ 		data do:
+ 			[:char |
+ 			ix := 'ear tonsilcmbdfghjkpquvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345[]()'
+ 					indexOf: char ifAbsent: 0.
+ 			(ix = 0
+ 				ifTrue:
+ 					[char asInteger > 255 ifTrue: [^nil]. "Could use UTF8 here; too lazy right now"
+ 					{ 0. char asInteger // 16. char asInteger \\ 16 }]
+ 				ifFalse:
+ 					[ix <= 11
+ 						ifTrue: [{ ix }]
+ 						ifFalse: [{ ix//16+12. ix\\16 }]])
+ 					do: [:nibble |
+ 						oddNibble
+ 							ifNotNil: [strm nextPut: oddNibble*16 + nibble. oddNibble := nil]
+ 							ifNil: [oddNibble := nibble]]].
+ 		oddNibble ifNotNil: "4 = 'ear tonsil' indexOf: Character space"
+ 			[strm nextPut: oddNibble * 16 + 4].
+ 		(sz := strm position) > ((251 - 128) * 128 + 127) ifTrue:
+ 			[^nil].
+ 		sz <= 127
+ 			ifTrue: [strm nextPut: sz]
+ 			ifFalse:
+ 				[strm nextPut: sz \\ 128; nextPut: sz // 128 + 128]]!

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeExtendedKind (in category 'encoding') -----
+ decodeExtendedKind
+ 
+ 	"reserved for future use"
+ 	self shouldBeImplemented.
+ !

Item was added:
+ ----- Method: OldMethodTrailer>>qDecompressFrom: (in category 'as yet unclassified') -----
+ qDecompressFrom: input "<ReadStream on: ByteArray> ^<String>"
+ 	"Decompress strings compressed by qCompress:.
+ 	Most common 11 chars get values 0-10 packed in one 4-bit nibble;
+ 	next most common 52 get values 12-15 (2 bits) * 16 plus next nibble;
+ 	escaped chars get three nibbles"
+ 	^ String streamContents:
+ 		[:strm | | nextNibble nibble peek charTable char |
+ 		charTable :=  "Character encoding table must match qCompress:"
+ 		'ear tonsilcmbdfghjkpquvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345[]()'.
+ 		peek := true.
+ 		nextNibble := [peek
+ 						ifTrue: [peek := false. input peek ifNil: [0] ifNotNil: [:b| b // 16]]
+ 						ifFalse: [peek := true. input next ifNil: [0] ifNotNil: [:b| b \\ 16]]].
+ 		[input atEnd] whileFalse:
+ 			[(nibble := nextNibble value) = 0
+ 				ifTrue: [input atEnd ifFalse:
+ 						[strm nextPut: (Character value: nextNibble value * 16 + nextNibble value)]]
+ 				ifFalse:
+ 					[nibble <= 11
+ 						ifTrue:
+ 							[strm nextPut: (charTable at: nibble)]
+ 						ifFalse:
+ 							[strm nextPut: (charTable at: nibble-12 * 16 + nextNibble value)]]]]!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encode (in category 'encoding') -----
+ encode
+ 
+ 	encodedData := nil.
+ 	
+ 	"encode the trailer into byte array"
+ 	self perform: ('encode' , kind) asSymbol.
+ 
+ 	self assert: (encodedData notNil and: [encodedData size > 0 ]).
+ 	
+ 	"set the size"
+ 	size := encodedData size.!

Item was added:
+ ----- Method: CompiledMethodTrailer>>setSourceBySelector (in category 'accessing') -----
+ setSourceBySelector
+ 
+ 	"Trailer is used to indicate that method's source code can be retrieved by 
+ 	sending #getSourceCodeBySelector: message to method's class" 
+ 	
+ 	self clear.
+ 	kind := #SourceBySelector!

Item was added:
+ ----- Method: CompiledMethodTrailer>>endPC (in category 'accessing') -----
+ endPC
+ 	"Answer the index of the last bytecode."
+ 	
+ 	method ifNil: [ self error: 'Cannot determine the endPC without compiled method' ].
+ 	
+ 	"if method set, then size should be set as well"
+ 	^ method size - size!

Item was added:
+ ----- Method: CompiledMethodTrailer>>size (in category 'accessing') -----
+ size
+ 	"Answer the size of method's trailer , in bytes"
+ 	^ size!

Item was added:
+ ----- Method: CompiledMethodTrailer>>tempNames (in category 'accessing') -----
+ tempNames
+ 	"Answer the string, containing the temps names or nil "
+ 	^ (kind == #TempsNamesQCompress or: [ kind == #TempsNamesZip ]) 
+ 		ifTrue: [ data ] ifFalse: [ nil ]!

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeTempsNamesQCompress (in category 'decoding') -----
+ decodeTempsNamesQCompress
+ 
+ 	"data is string with method's temporary names, encoded using qCompress method"
+ 	self qDecompress.!

Item was added:
+ ----- Method: OldMethodTrailer>>method: (in category 'as yet unclassified') -----
+ method: aMethod
+ 	"old method trailer format has only 3 kinds:
+ 	 0 [ 0 0 0 ] - no trailer
+ 	 source pointer
+ 	 temps names
+ 	"
+ 	| flagByte |
+ 	data := size := nil.
+ 	method := aMethod.
+ 	flagByte := method at: (method size).
+ 
+ 	kind := (flagByte = 0) ifTrue: [ #OldEmptyTrailer ] 
+ 		ifFalse: [
+ 			(flagByte < 252) ifTrue: [ #OldTempsNames ]
+ 			ifFalse: [ #SourcePointer ]].
+ 		
+ 	"decode the trailer bytes"
+ 	self perform: ('decode' , kind) asSymbol.
+ 	
+ 	"after decoding the trailer, size must be set"
+ 	self assert: (size notNil).
+ 
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeNoTrailer (in category 'encoding') -----
+ encodeNoTrailer
+ 
+ 	encodedData := ByteArray with: self kindAsByte!

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeExtendedKind (in category 'encoding') -----
+ encodeExtendedKind
+ 
+ 	"reserved for future use"
+ 	self error: 'Not yet implemented'.
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeTempsNamesZip (in category 'decoding') -----
+ decodeTempsNamesZip
+ 
+ 	"data is string with method's temporary names, compressed using zip compression"
+ 	self decodeZip.!

Item was added:
+ ----- Method: CompiledMethodTrailer>>decodeZip (in category 'private') -----
+ decodeZip
+ 
+ 	"data := <trailer> unzip utf8ToSqueak"
+ 	| len |
+ 	len := self decodeLengthField.
+ 
+ 	data := (ZipReadStream on: method from: method size - size+1 to: method size - size + len) contents asString convertFromEncoding: 'utf8'.
+ 
+ !

Item was added:
+ ----- Method: CompiledMethodTrailer>>encodeUsingZip (in category 'private') -----
+ encodeUsingZip
+ 
+ 	"data is string, encode it using gzip compression"
+ 	| utf8str stream length encodedLength |
+ 
+ 	self assert: (data isString).
+ 	utf8str := data convertToEncoding: 'utf8'.
+ 	
+ 	stream := ((ZipWriteStream on: (ByteArray new: utf8str size))
+ 		nextPutAll: utf8str asByteArray;
+ 		close;
+ 		encodedStream).
+ 		
+ 	length := stream position.
+ 	encodedLength := self encodeLengthField: length.
+ 
+ 	stream nextPutAll: encodedLength.
+ 	"trailing byte"
+ 	stream nextPut: (self kindAsByte + encodedLength size - 1).
+ 	
+ 	encodedData := stream contents
+ 	!



More information about the Packages mailing list