[Vm-dev] VM Maker: VMMaker.oscog-eem.919.mcz

commits at source.squeak.org commits at source.squeak.org
Mon Nov 3 22:18:33 UTC 2014


Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.919.mcz

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

Name: VMMaker.oscog-eem.919
Author: eem
Time: 3 November 2014, 2:08:03.633 pm
UUID: f0f51db3-86d9-4c1f-bbf1-82e882d530eb
Ancestors: VMMaker.oscog-eem.918

Integrate Ryan's latest absent receiver sends.
Includes nice refactoring of absent send argument
marshalling into its own routine.

Eliminate some compiler warnings in the refactored
instVar:ofContext: changes.

=============== Diff against VMMaker.oscog-eem.918 ===============

Item was changed:
  ----- Method: CoInterpreter>>implicitReceiverFor:mixin:implementing: (in category 'newspeak bytecode support') -----
+ implicitReceiverFor: methodReceiver mixin: methodMixin implementing: selector
+ 	"This is used to implement implicit receiver sends in Newspeak. Find the nearest
+ 	 lexically-enclosing implementation of selector by searching up the static chain of the
+ 	 method's receiver, starting at mixin's application. This implementation is derived from
- implicitReceiverFor: rcvr mixin: mixin implementing: selector
- 	"This is used to implement the innards of the pushImplicitReceiverBytecode,
- 	 used for implicit receiver sends in NS2/NS3.  Find the nearest lexically-enclosing
- 	 implementation of selector by searching up the static chain of anObject,
- 	 starting at mixin's application.  This is an iterative implementation derived from
  
+ 	<ContextPart> implicitReceiverFor: methodReceiver <Object>
+ 					in: methodMixin <Mixin>
- 	<ContextPart> implicitReceiverFor: obj <Object>
- 					withMixin: mixin <Mixin>
  					implementing: selector <Symbol> ^<Object>"
  
  	<api>
  	<option: #NewspeakVM>
  	cogit breakOnImplicitReceiver ifTrue:
  		[self sendBreakpoint: selector receiver: nil].
+ 	^super implicitReceiverFor: methodReceiver mixin: methodMixin implementing: selector!
- 	^super implicitReceiverFor: rcvr mixin: mixin implementing: selector!

Item was changed:
  ----- Method: CoInterpreter>>instVar:ofContext: (in category 'frame access') -----
  instVar: offset ofContext: aContext
  	"Fetch an instance avriable from a maybe married context.
  	 If the context is still married compute the value of the
  	 relevant inst var from the spouse frame's state.
  
  	 If the context is single but has a negative instruction pointer
  	 recognise that the instruction pointer is actually into machine
  	 code and convert it to the corresponding bytecode pc."
  	| value spouseFP |
  	<var: #spouseFP type: #'char *'>
  	<inline: true>
  	self assert: offset < MethodIndex.
  	self assert: (objectMemory isContext: aContext).
  	self writeBackHeadFramePointers.
  	(self isMarriedOrWidowedContext: aContext) ifFalse:
  		[value := objectMemory fetchPointer: offset ofObject: aContext.
  		 (offset = InstructionPointerIndex
  		  and: [(objectMemory isIntegerObject: value)
  		  and: [value signedIntFromLong < 0]]) ifTrue:
  			[value := self internalMustMapMachineCodePC: (objectMemory integerValueOf: value)
  						context: aContext].
  		 ^value].
  
  	(self isWidowedContext: aContext) ifTrue:
  		[^objectMemory fetchPointer: offset ofObject: aContext].
  
  	spouseFP := self frameOfMarriedContext: aContext.
  	offset = SenderIndex ifTrue:
  		[^self ensureCallerContext: spouseFP].
  	offset = StackPointerIndex ifTrue:
  		[self assert: ReceiverIndex + (self stackPointerIndexForFrame: spouseFP) < (objectMemory lengthOf: aContext).
  		^objectMemory integerObjectOf: (self stackPointerIndexForFrame: spouseFP)].
  	offset = InstructionPointerIndex ifTrue:
+ 		[^self instructionPointerForFrame: spouseFP currentFP: localFP currentIP: (self oopForPointer: localIP)].
- 		[^self instructionPointerForFrame: spouseFP currentFP: localFP currentIP: localIP].
  	self error: 'bad index'.
  	^0!

Item was changed:
  ----- Method: CoInterpreter>>instructionPointerForFrame:currentFP:currentIP: (in category 'frame access') -----
  instructionPointerForFrame: spouseFP currentFP: currentFP currentIP: instrPtr
  	"Answer the bytecode pc object (i.e. SmallInteger) for an active frame.  The bytecode
  	 pc is derived from the frame's pc.  If the frame is the top frame on the current stack
  	 the frame pc is whatever the current instruction pointer is.  If the frame is the top
  	 frame on some other stack the frame pc is the value on top of stack.  Otherwise the
  	 frame pc is the saved pc of the frame above.  Once the frame pc is found it must be
  	 mapped to a bytecode pc."
+ 	<var: #spouseFP type: #'char *'>
+ 	<var: #currentFP type: #'char *'>
  	| value theIP thePage theFPAbove |
+ 	<var: #thePage type: #'StackPage *'>
+ 	<var: #theFPAbove type: #'char *'>
  	spouseFP = currentFP
  		ifTrue: [theIP := self oopForPointer: instrPtr]
  		ifFalse:
  			[thePage := stackPages stackPageFor: spouseFP.
  			 theFPAbove := self findFrameAbove: spouseFP inPage: thePage.
  			 theIP := theFPAbove == 0
  						ifTrue: [stackPages longAt: thePage headSP]
  						ifFalse:[self oopForPointer: (self frameCallerSavedIP: theFPAbove)]].
  	value := self contextInstructionPointer: theIP frame: spouseFP.
  	^value signedIntFromLong < 0
  		ifTrue: [self mustMapMachineCodePC: (objectMemory integerValueOf: value)
  					context: (self frameContext: spouseFP)]
  		ifFalse: [value]!

Item was changed:
  ----- Method: SimpleStackBasedCogit class>>initializeBytecodeTableForNewspeakV4 (in category 'class initialization') -----
  initializeBytecodeTableForNewspeakV4
  	"SimpleStackBasedCogit initializeBytecodeTableForNewspeakV4"
  
  	NSSendIsPCAnnotated := false. "IsNSSendCall used by SendAbsentImplicit"
  	FirstSpecialSelector := 80.
  	self flag:
  'Special selector send class must be inlined to agree with the interpreter, which
   inlines class.  If class is sent to e.g. a general instance of ProtoObject then unless
   class is inlined there will be an MNU.  It must be that the Cointerpreter and Cogit
   have identical semantics.  We get away with not hardwiring the other special
   selectors either because in the Cointerpreter they are not inlined or because they
   are inlined only to instances of classes for which there will always be a method.'.
  	self generatorTableFrom: #(
  		"1 byte bytecodes"
  		(1    0   15 genPushReceiverVariableBytecode)
  		(1  16   31 genPushLiteralVariable16CasesBytecode needsFrameNever: 1)
  		(1  32   63 genPushLiteralConstantBytecode needsFrameNever: 1)
  		(1  64   75 genPushTemporaryVariableBytecode)
  		(1  76   76 genPushReceiverBytecode)
  		(1  77   77 genExtPushPseudoVariableOrOuterBytecode)
  		(1  78   78 genPushConstantZeroBytecode)
  		(1  79   79 genPushConstantOneBytecode)
  
  		(1   80 101 genSpecialSelectorSend isMapped) "#+ #- #< #> #<= #>= #= #~= #* #/ #\\ #@ #bitShift: #// #bitAnd: #bitOr: #at: #at:put: #size #next #nextPut: #atEnd"
  		(1 102 102 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
  		(1 103 103 genSpecialSelectorClass needsFrameNever: notMapped 0) "not mapped because it is directly inlined (for now)"
  		(1 104 111 genSpecialSelectorSend isMapped) "#blockCopy: #value #value: #do: #new #new: #x #y"
  
  		(1 112 127 genSendLiteralSelector0ArgsBytecode isMapped)
  		(1 128 143 genSendLiteralSelector1ArgBytecode isMapped)
  		(1 144 159 genSendLiteralSelector2ArgsBytecode isMapped)
  		(1 160 175	genSendAbsentImplicit0ArgsBytecode isMapped hasIRC)
  
  		(1 176 183 genStoreAndPopReceiverVariableBytecode needsFrameNever: -1) "N.B. not frameless if immutability"
  		(1 184 191 genStoreAndPopTemporaryVariableBytecode)
  
  		(1 192 199 genShortUnconditionalJump	branch v3:ShortForward:Branch:Distance:)
  		(1 200 207 genShortJumpIfTrue			branch isBranchTrue isMapped "because of mustBeBoolean"
  													v3:ShortForward:Branch:Distance:)
  		(1 208 215 genShortJumpIfFalse			branch isBranchFalse isMapped "because of mustBeBoolean"
  													v3:ShortForward:Branch:Distance:)
  
  		(1 216 216 genReturnReceiver				return needsFrameIfInBlock: isMappedInBlock 0)
  		(1 217 217 genReturnTopFromMethod		return needsFrameIfInBlock: isMappedInBlock -1)
  		(1 218 218 genExtReturnTopFromBlock	return needsFrameNever: -1)
  
  		(1 219 219 duplicateTopBytecode			needsFrameNever: 1)
  		(1 220 220 genPopStackBytecode			needsFrameNever: -1)
  		(1 221 221 genExtNopBytecode			needsFrameNever: 0)
  		(1 222 223	unknownBytecode)
  
  		"2 byte bytecodes"
  		(2 224 224 extABytecode extension)
  		(2 225 225 extBBytecode extension)
  		(2 226 226 genExtPushReceiverVariableBytecode)
  		(2 227 227 genExtPushLiteralVariableBytecode		needsFrameNever: 1)
  		(2 228 228 genExtPushLiteralBytecode					needsFrameNever: 1)
  		(2 229 229 genExtPushIntegerBytecode				needsFrameNever: 1)
  		(2 230 230 genLongPushTemporaryVariableBytecode)
  		(2 231 231 genPushNewArrayBytecode)
  		(2 232 232 genExtStoreReceiverVariableBytecode)
  		(2 233 233 genExtStoreLiteralVariableBytecode)
  		(2 234 234 genLongStoreTemporaryVariableBytecode)
  		(2 235 235 genExtStoreAndPopReceiverVariableBytecode)
  		(2 236 236 genExtStoreAndPopLiteralVariableBytecode)
  		(2 237 237 genLongStoreAndPopTemporaryVariableBytecode)
  
  		(2 238 238 genExtSendBytecode isMapped)
  		(2 239 239 genExtSendSuperBytecode isMapped)
  		(2 240 240 genExtSendAbsentImplicitBytecode isMapped hasIRC)
  		(2 241 241 genExtSendAbsentDynamicSuperBytecode isMapped)
  
  		(2 242 242 genExtUnconditionalJump	branch isMapped "because of interrupt check" v4:Long:Branch:Distance:)
  		(2 243 243 genExtJumpIfTrue			branch isBranchTrue isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
  		(2 244 244 genExtJumpIfFalse			branch isBranchFalse isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
  
+ 		(2 245 245 genExtSendAbsentSelfBytecode isMapped)
- 		(2 245 248	unknownBytecode)
  
+ 		(2 246 248	unknownBytecode)
+ 
  		"3 byte bytecodes"
  		(3 249 249 callPrimitiveBytecode)
  		(3 250 250 genPushRemoteTempLongBytecode)
  		(3 251 251 genStoreRemoteTempLongBytecode)
  		(3 252 252 genStoreAndPopRemoteTempLongBytecode)
  		(3 253 253 genExtPushClosureBytecode block v4:Block:Code:Size:)
+ 		(3 254 254 genExtSendAbsentOuterBytecode isMapped)
  
+ 		(3 255 255	unknownBytecode))!
- 		(3 254 255	unknownBytecode))!

Item was added:
+ ----- Method: SimpleStackBasedCogit>>genExtSendAbsentOuterBytecode (in category 'bytecode generators') -----
+ genExtSendAbsentOuterBytecode
+ 	"254		 11111110	i i i i i j j j kkkkkkkk	Send To Absent Outer Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments at Depth kkkkkkkk "
+ 	| litIndex nArgs depth |
+ 	litIndex := (byte1 >> 3) + (extA << 5).
+ 	extA := 0.
+ 	nArgs := (byte1 bitAnd: 7) + (extB << 3).
+ 	extB := 0.
+ 	depth := byte2.
+ 	^self genSendAbsentOuter: (self getLiteral: litIndex) numArgs: nArgs depth: depth
+ !

Item was added:
+ ----- Method: SimpleStackBasedCogit>>genExtSendAbsentSelfBytecode (in category 'bytecode generators') -----
+ genExtSendAbsentSelfBytecode
+ 	"245		11110101	i i i i i j j j	Send To Absent Self Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"
+ 	| litIndex nArgs |
+ 	litIndex := (byte1 >> 3) + (extA << 5).
+ 	extA := 0.
+ 	nArgs := (byte1 bitAnd: 7) + (extB << 3).
+ 	extB := 0.
+ 	^self genSendAbsentSelf: (self getLiteral: litIndex) numArgs: nArgs!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genPushEnclosingObjectAt: (in category 'bytecode generators') -----
  genPushEnclosingObjectAt: level
  	"Uncached push enclosing object"
  	self MoveCq: level R: SendNumArgsReg.
  	self CallRT: ceEnclosingObjectTrampoline.
  	self PushR: ReceiverResultReg.
  	^0!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genSendAbsentDynamicSuper:numArgs: (in category 'bytecode generators') -----
  genSendAbsentDynamicSuper: selector numArgs: numArgs
  	"Shuffle arguments if necessary and push receiver.
  	 Then send."
  	<inline: false>
+ 	self marshallAbsentReceiverSendArguments: numArgs.
- 	numArgs = 0
- 		ifTrue:
- 			[self PushR: ReceiverResultReg]
- 		ifFalse:
- 			[self MoveMw: 0 r: SPReg R: TempReg.
- 			self PushR: TempReg.
- 			2 to: numArgs do:
- 				[:index|
- 				self MoveMw: index * BytesPerWord r: SPReg R: TempReg.
- 				self MoveR: TempReg Mw: index - 1 * BytesPerWord r: SPReg].
- 			"if we copied the code in genSendDynamicSuper: we could save an instruction.
- 			But we care not; the smarts are in StackToRegisterMappingCogit et al"
- 			self MoveR: ReceiverResultReg Mw: numArgs * BytesPerWord r: SPReg].
  	^self genSendDynamicSuper: selector numArgs: numArgs!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genSendAbsentImplicit:numArgs: (in category 'bytecode generators') -----
  genSendAbsentImplicit: selector numArgs: numArgs
  	"Get the implicit receiver and shuffle arguments if necessary.
  	 Then send."
  	<inline: false>
  	| result |
  	result := self genGetImplicitReceiverFor: selector forPush: false.
  	result ~= 0 ifTrue:
  		[^result].
+ 	self marshallAbsentReceiverSendArguments: numArgs.
- 	numArgs = 0
- 		ifTrue:
- 			[self PushR: ReceiverResultReg]
- 		ifFalse:
- 			[self MoveMw: 0 r: SPReg R: TempReg.
- 			self PushR: TempReg.
- 			2 to: numArgs do:
- 				[:index|
- 				self MoveMw: index * BytesPerWord r: SPReg R: TempReg.
- 				self MoveR: TempReg Mw: index - 1 * BytesPerWord r: SPReg].
- 			"if we copied the code in genSend:numArgs: we could save an instruction.
- 			But we care not; the smarts are in StackToRegisterMappingCogit et al"
- 			self MoveR: ReceiverResultReg Mw: numArgs * BytesPerWord r: SPReg].
  	^self genSend: selector numArgs: numArgs!

Item was added:
+ ----- Method: SimpleStackBasedCogit>>genSendAbsentOuter:numArgs:depth: (in category 'bytecode generators') -----
+ genSendAbsentOuter: selector numArgs: numArgs depth: depth
+ 	"Shuffle arguments if necessary and push receiver.
+ 	 Then send."
+ 	<inline: false>
+ 	self genPushEnclosingObjectAt: depth.
+ 	self PopR: ReceiverResultReg.
+ 	self marshallAbsentReceiverSendArguments: numArgs.
+ 	^self genSend: selector numArgs: numArgs!

Item was added:
+ ----- Method: SimpleStackBasedCogit>>genSendAbsentSelf:numArgs: (in category 'bytecode generators') -----
+ genSendAbsentSelf: selector numArgs: numArgs
+ 	"Shuffle arguments if necessary and push receiver.
+ 	 Then send."
+ 	<inline: false>
+ 	self marshallAbsentReceiverSendArguments: numArgs.
+ 	^self genSend: selector numArgs: numArgs!

Item was added:
+ ----- Method: SimpleStackBasedCogit>>marshallAbsentReceiverSendArguments: (in category 'bytecode generators') -----
+ marshallAbsentReceiverSendArguments: numArgs
+ 	"Shuffle arguments if necessary and push receiver."
+ 	numArgs = 0
+ 		ifTrue:
+ 			[self PushR: ReceiverResultReg]
+ 		ifFalse:
+ 			[self MoveMw: 0 r: SPReg R: TempReg.
+ 			self PushR: TempReg.
+ 			2 to: numArgs do:
+ 				[:index|
+ 				self MoveMw: index * BytesPerWord r: SPReg R: TempReg.
+ 				self MoveR: TempReg Mw: index - 1 * BytesPerWord r: SPReg].
+ 			self MoveR: ReceiverResultReg Mw: numArgs * BytesPerWord r: SPReg].!

Item was changed:
  ----- Method: StackInterpreter class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: aCCodeGenerator
  	| vmClass |
  	self class == thisContext methodClass ifFalse: [^self]. "Don't duplicate decls in subclasses"
  	vmClass := aCCodeGenerator vmClass. "Generate primitiveTable etc based on vmClass, not just StackInterpreter"
  	aCCodeGenerator
  		addHeaderFile:'<stddef.h> /* for e.g. alloca */';
+ 		addHeaderFile:'<wchar.h>';
  		addHeaderFile:'<setjmp.h>';
- 		addHeaderFile:'<wchar.h> /* for wint_t */';
  		addHeaderFile:'"vmCallback.h"';
  		addHeaderFile:'"sqMemoryFence.h"';
  		addHeaderFile:'"dispdbg.h"'.
  	vmClass declareInterpreterVersionIn: aCCodeGenerator defaultName: 'Stack'.
  	aCCodeGenerator
  		var: #interpreterProxy  type: #'struct VirtualMachine*'.
  	aCCodeGenerator
  		declareVar: #sendTrace type: 'volatile int';
  		declareVar: #byteCount type: 'unsigned long'.
  	"These need to be pointers or unsigned."
  	self declareC: #(instructionPointer method newMethod)
  		as: #usqInt
  		in: aCCodeGenerator.
  	"These are all pointers; char * because Slang has no support for C pointer arithmetic."
  	self declareC: #(localIP localSP localFP stackPointer framePointer stackLimit stackMemory)
  		as: #'char *'
  		in: aCCodeGenerator.
  	self declareC: #(stackPage overflowedPage)
  		as: #'StackPage *'
  		in: aCCodeGenerator.
  	aCCodeGenerator removeVariable: 'stackPages'.  "this is an implicit receiver in the translated code."
  	"This defines bytecodeSetSelector as 0 if MULTIPLEBYTECODESETS
  	 is not defined, for the benefit of the interpreter on slow machines."
  	aCCodeGenerator addConstantForBinding: (self bindingOf: #MULTIPLEBYTECODESETS).
  	MULTIPLEBYTECODESETS == false ifTrue:
  		[aCCodeGenerator
  			removeVariable: 'extA';
  			removeVariable: 'extB';
  			removeVariable: 'bytecodeSetSelector'].
  	aCCodeGenerator
  		var: #methodCache
  		declareC: 'long methodCache[MethodCacheSize + 1 /* ', (MethodCacheSize + 1) printString, ' */]'.
  	aCCodeGenerator
  		var: #atCache
  		declareC: 'sqInt atCache[AtCacheTotalSize + 1 /* ', (AtCacheTotalSize + 1) printString, ' */]'.
  	aCCodeGenerator
  		var: #primitiveTable
  		declareC: 'void (*primitiveTable[MaxPrimitiveIndex + 2 /* ', (MaxPrimitiveIndex + 2) printString, ' */])(void) = ', vmClass primitiveTableString.
  	vmClass primitiveTable do:
  		[:symbolOrNot|
  		(symbolOrNot isSymbol
  		 and: [symbolOrNot ~~ #primitiveFail]) ifTrue:
  			[(aCCodeGenerator methodNamed: symbolOrNot) ifNotNil:
  				[:tMethod| tMethod returnType: #void]]].
  	vmClass objectMemoryClass hasSpurMemoryManagerAPI
  		ifTrue:
  			[aCCodeGenerator
  				var: #primitiveAccessorDepthTable
  				type: 'signed char'
  				sizeString: 'MaxPrimitiveIndex + 2 /* ', (MaxPrimitiveIndex + 2) printString, ' */'
  				array: vmClass primitiveAccessorDepthTable]
  		ifFalse:
  			[aCCodeGenerator removeVariable: #primitiveAccessorDepthTable].
  	aCCodeGenerator
  		var: #primitiveFunctionPointer
  		declareC: 'void (*primitiveFunctionPointer)()'.
  	aCCodeGenerator
  		var: #externalPrimitiveTable
  		declareC: 'void (*externalPrimitiveTable[MaxExternalPrimitiveTableSize + 1 /* ', (MaxExternalPrimitiveTableSize + 1) printString, ' */])(void)'.
  	aCCodeGenerator var: #showSurfaceFn type: #'void *'.
  	aCCodeGenerator
  		var: #jmpBuf
  		declareC: 'jmp_buf jmpBuf[MaxJumpBuf + 1 /* ', (MaxJumpBuf + 1) printString, ' */]'.
  	aCCodeGenerator
  		var: #suspendedCallbacks
  		declareC: 'usqInt suspendedCallbacks[MaxJumpBuf + 1 /* ', (MaxJumpBuf + 1) printString, ' */]'.
  	aCCodeGenerator
  		var: #suspendedMethods
  		declareC: 'usqInt suspendedMethods[MaxJumpBuf + 1 /* ', (MaxJumpBuf + 1) printString, ' */]'.
  	aCCodeGenerator
  		var: #interruptCheckChain
  		declareC: 'void (*interruptCheckChain)(void) = 0'.
  	aCCodeGenerator
  		var: #breakSelector type: #'char *';
  		var: #breakSelectorLength
  		declareC: 'sqInt breakSelectorLength = -1'.
  
  	self declareCAsUSqLong: #(nextPollUsecs nextWakeupUsecs longRunningPrimitiveGCUsecs
  								longRunningPrimitiveStartUsecs longRunningPrimitiveStopUsecs
  								"these are high-frequency enough that they're overflowing quite quickly on modern hardware"
  								statProcessSwitch statIOProcessEvents statForceInterruptCheck
  								statCheckForEvents statStackOverflow statStackPageDivorce)
  		in: aCCodeGenerator.
  	aCCodeGenerator var: #nextProfileTick type: #sqLong!

Item was changed:
  ----- Method: StackInterpreter class>>initializeBytecodeTableForNewspeakV4 (in category 'initialization') -----
  initializeBytecodeTableForNewspeakV4
  	"StackInterpreter initializeBytecodeTableForNewspeakV4"
  	"Note: This table will be used to generate a C switch statement."
  
  	BytecodeTable := Array new: 256.
  	BytecodeEncoderClassName := #EncoderForNewsqueakV4.
  	LongStoreBytecode := 234.
  	self table: BytecodeTable from:
  	#(	"1 byte bytecodes"
  		(   0  15 pushReceiverVariableBytecode)
  		( 16  31 pushLiteralVariable16CasesBytecode)
  		( 32  63 pushLiteralConstantBytecode)
  		( 64  75 pushTemporaryVariableBytecode)
  		( 76	 pushReceiverBytecode)
  		( 77	 extPushPseudoVariableOrOuterBytecode)
  		( 78	 pushConstantZeroBytecode)
  		( 79	 pushConstantOneBytecode)
  
  		( 80	 bytecodePrimAdd)
  		( 81	 bytecodePrimSubtract)
  		( 82	 bytecodePrimLessThanV4) "for booleanCheatV4:"
  		( 83	 bytecodePrimGreaterThanV4) "for booleanCheatV4:"
  		( 84	 bytecodePrimLessOrEqualV4) "for booleanCheatV4:"
  		( 85	 bytecodePrimGreaterOrEqualV4) "for booleanCheatV4:"
  		( 86	 bytecodePrimEqualV4) "for booleanCheatV4:"
  		( 87	 bytecodePrimNotEqualV4) "for booleanCheatV4:"
  		( 88	 bytecodePrimMultiply)
  		( 89	 bytecodePrimDivide)
  		( 90	 bytecodePrimMod)
  		( 91	 bytecodePrimMakePoint)
  		( 92	 bytecodePrimBitShift)
  		( 93	 bytecodePrimDiv)
  		( 94	 bytecodePrimBitAnd)
  		( 95	 bytecodePrimBitOr)
  
  		( 96	 bytecodePrimAt)
  		( 97	 bytecodePrimAtPut)
  		( 98	 bytecodePrimSize)
  		( 99	 bytecodePrimNext)
  		(100	 bytecodePrimNextPut)
  		(101	 bytecodePrimAtEnd)
  		(102	 bytecodePrimIdenticalV4) "for booleanCheatV4:"
  		(103	 bytecodePrimClass)
  		(104	 bytecodePrimSpecialSelector24) "was blockCopy:"
  		(105	 bytecodePrimValue)
  		(106	 bytecodePrimValueWithArg)
  		(107	 bytecodePrimDo)
  		(108	 bytecodePrimNew)
  		(109	 bytecodePrimNewWithArg)
  		(110	 bytecodePrimPointX)
  		(111	 bytecodePrimPointY)
  
  		(112 127	sendLiteralSelector0ArgsBytecode)
  		(128 143	sendLiteralSelector1ArgBytecode)
  		(144 159	sendLiteralSelector2ArgsBytecode)
  		(160 175	sendAbsentImplicit0ArgsBytecode)
  
  		(176 183	storeAndPopReceiverVariableBytecode)
  		(184 191	storeAndPopTemporaryVariableBytecode)
  
  		(192 199	shortUnconditionalJump)
  		(200 207	shortConditionalJumpTrue)
  		(208 215	shortConditionalJumpFalse)
  
  		(216		returnReceiver)
  		(217		returnTopFromMethod)
  		(218		extReturnTopFromBlock)
  
  		(219		duplicateTopBytecode)
  		(220		popStackBytecode)
  		(221		extNopBytecode)
  		(222 223	unknownBytecode)
  
  		"2 byte bytecodes"
  		(224		extABytecode)
  		(225		extBBytecode)
  
  		(226		extPushReceiverVariableBytecode)
  		(227		extPushLiteralVariableBytecode)
  		(228		extPushLiteralBytecode)
  		(229		extPushIntegerBytecode)
  		(230		longPushTemporaryVariableBytecode)
  		(231		pushNewArrayBytecode)
  		(232		extStoreReceiverVariableBytecode)
  		(233		extStoreLiteralVariableBytecode)
  		(234		longStoreTemporaryVariableBytecode)
  		(235		extStoreAndPopReceiverVariableBytecode)
  		(236		extStoreAndPopLiteralVariableBytecode)
  		(237		longStoreAndPopTemporaryVariableBytecode)
  
  		(238		extSendBytecode)
  		(239		extSendSuperBytecode)
  		(240		extSendAbsentImplicitBytecode)
  		(241		extSendAbsentDynamicSuperBytecode)
  
  		(242		extUnconditionalJump)
  		(243		extJumpIfTrue)
  		(244		extJumpIfFalse)
  
+ 		(245		extSendAbsentSelfBytecode)
- 		(245 248	unknownBytecode)
  
+ 		(246 248	unknownBytecode)
+ 
  		"3 byte bytecodes"
  		(249		callPrimitiveBytecode)
  
  		(250		pushRemoteTempLongBytecode)
  		(251		storeRemoteTempLongBytecode)
  		(252		storeAndPopRemoteTempLongBytecode)
  		(253		extPushClosureBytecode)
+ 		(254		extSendAbsentOuterBytecode)
  
+ 		(255		unknownBytecode)
- 		(254 255	unknownBytecode)
  	)!

Item was changed:
  ----- Method: StackInterpreter>>enclosingObjectAt:withObject:withMixin: (in category 'newspeak bytecode support') -----
+ enclosingObjectAt: depth withObject: methodReceiver withMixin: methodMixin 
+ 	"This is used to implement outer sends and outer expressions in Newspeak."
- enclosingObjectAt: n withObject: anObject withMixin: mixin 
- 	"This is used to implement the innards of the pushEnclosingObjectBytecode,
- 	 used for explicit outer sends in NS2/NS3.  "
  	| enclosingObject mixinApplication targetMixin count |
  	
+ 	enclosingObject := methodReceiver.
+ 	targetMixin := methodMixin.
- 	enclosingObject := anObject.
- 	targetMixin := mixin.
  	count := 0.
+ 	[count < depth] whileTrue:
- 	[count < n] whileTrue:
  		[count := count + 1.
+ 		self deny: (targetMixin = objectMemory nilObject).
- 		(targetMixin = objectMemory nilObject
- 		 or: [enclosingObject = objectMemory nilObject]) ifTrue:
- 			[^objectMemory nilObject].
  		mixinApplication := self
+ 							findApplicationOfTargetMixin: targetMixin
+ 							startingAtBehavior: (self fetchClassOf: enclosingObject).
+ 		self deny: (mixinApplication = objectMemory nilObject).
+ 		enclosingObject := self followObjField: EnclosingObjectIndex ofObject: mixinApplication.	
+ 		targetMixin := self followObjField: EnclosingMixinIndex ofObject: targetMixin].
- 								findApplicationOfTargetMixin: targetMixin
- 								startingAtNonMetaClass: (objectMemory fetchClassOf: enclosingObject).
- 		mixinApplication = objectMemory nilObject ifTrue:
- 			[^objectMemory nilObject]. "should never happen!!"
- 		enclosingObject := objectMemory followObjField: EnclosingObjectIndex ofObject: mixinApplication.	
- 		targetMixin := objectMemory followObjField: EnclosingMixinIndex ofObject: targetMixin].
  	
  	^enclosingObject!

Item was added:
+ ----- Method: StackInterpreter>>extSendAbsentOuterBytecode (in category 'send bytecodes') -----
+ extSendAbsentOuterBytecode
+ 	"254		  11111110 	i i i i i j j j	kkkkkkkk Send To Enclosing Object at Depth kkkkkkkk Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"
+ 	| byte depth absentReceiver |
+ 	byte := self fetchByte.
+ 	messageSelector := self literal: (byte >> 3) + (extA << 5).
+ 	extA := 0.
+ 	argumentCount := (byte bitAnd: 7) + (extB << 3).
+ 	extB := 0.
+ 	depth := self fetchByte.
+ 	absentReceiver := self 
+ 							enclosingObjectAt: depth
+ 							withObject: self receiver 
+ 							withMixin: (self methodClassOf: method).
+ 	self shuffleArgumentsAndStoreAbsentReceiver: absentReceiver.
+ 	lkupClassTag := objectMemory classTagForClass: (objectMemory fetchClassOf: absentReceiver).
+ 	self commonSend!

Item was added:
+ ----- Method: StackInterpreter>>extSendAbsentSelfBytecode (in category 'send bytecodes') -----
+ extSendAbsentSelfBytecode
+ 	"245		 11110101 	i i i i i j j j	Send To Self Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"
+ 	| byte |
+ 	byte := self fetchByte.
+ 	messageSelector := self literal: (byte >> 3) + (extA << 5).
+ 	extA := 0.
+ 	argumentCount := (byte bitAnd: 7) + (extB << 3).
+ 	extB := 0.
+ 	self shuffleArgumentsAndStoreAbsentReceiver: self receiver.
+ 	lkupClassTag := objectMemory classTagForClass: (objectMemory fetchClassOf: self receiver).
+ 	self commonSend!

Item was changed:
  ----- Method: StackInterpreter>>findApplicationOfTargetMixin:startingAtBehavior: (in category 'newspeak bytecode support') -----
  findApplicationOfTargetMixin: targetMixin startingAtBehavior: aBehavior
+ 	"This is used to implement implicit receiver and enclosing object lookup
+ 	 for Newspeak. Find the mixin applcation of which aClass is a subclass that
+ 	 is an application of targetMixin. This is an implementation derived from
- 	"This is used to implement the innards of the pushImplicitReceiverBytecode,
- 	 used for outer sends in NS2/NS3.  Find the MixinApplcation of which aBehavior
- 	 is a subclass that is an application of targetMixin.  This is an implementation derived from
  
+ 	<ContextPart> findApplicationOf: targetMixin startingAt: aBehavior
- 	<ContextPart> findApplicationOfTargetMixin: targetMixin startingAtBehavior: aBehavior
  	"
+ 	| mixinApplication mixin |
+ 	mixinApplication := aBehavior.
+ 	[mixinApplication = objectMemory nilObject
+ 	 or: [mixinApplication = targetMixin
+ 	 or: [(mixin := objectMemory fetchPointer: MixinIndex ofObject: mixinApplication) = targetMixin]]] whileFalse:
+ 		[mixinApplication := objectMemory fetchPointer: SuperclassIndex ofObject: mixinApplication].
+ 	^mixinApplication!
- 	| mixinOrMixinApplication mixin |
- 	mixinOrMixinApplication := aBehavior.
- 	[mixinOrMixinApplication = objectMemory nilObject
- 	 or: [mixinOrMixinApplication = targetMixin
- 	 or: [(mixin := objectMemory fetchPointer: MixinIndex ofObject: mixinOrMixinApplication) = targetMixin
- 	 or: [(objectMemory fetchClassOfNonImm: mixin) = targetMixin]]]] whileFalse:
- 		[mixinOrMixinApplication := objectMemory fetchPointer: SuperclassIndex ofObject: mixinOrMixinApplication].
- 	^mixinOrMixinApplication!

Item was removed:
- ----- Method: StackInterpreter>>findApplicationOfTargetMixin:startingAtNonMetaClass: (in category 'newspeak bytecode support') -----
- findApplicationOfTargetMixin: targetMixin startingAtNonMetaClass: aClass
- 	"This is used to implement the innards of the pushImplicitReceiverBytecode,
- 	 used for outer sends in NS2/NS3.  Find the MixinApplcation of which aClass
- 	 is a subclass that is an application of targetMixin.  This is an implementation derived from
- 
- 	<ContextPart> findApplicationOfTargetMixin: targetMixin startingAtNonMetaClass: aClass
- 	"
- 	| mixinOrMixinApplication |
- 	self deny: (objectMemory isForwarded: targetMixin).
- 	self deny: (objectMemory isForwarded: aClass).
- 	mixinOrMixinApplication := aClass.
- 	[mixinOrMixinApplication = objectMemory nilObject
- 	 or: [mixinOrMixinApplication = targetMixin
- 	 or: [(objectMemory followObjField: MixinIndex ofObject: mixinOrMixinApplication) = targetMixin]]] whileFalse:
- 		[mixinOrMixinApplication := objectMemory followObjField: SuperclassIndex ofObject: mixinOrMixinApplication].
- 	^mixinOrMixinApplication!

Item was changed:
  ----- Method: StackInterpreter>>implicitReceiverFor:mixin:implementing: (in category 'newspeak bytecode support') -----
+ implicitReceiverFor: methodReceiver mixin: methodMixin implementing: selector
+ 	"This is used to implement implicit receiver sends in Newspeak. Find the nearest
+ 	 lexically-enclosing implementation of selector by searching up the static chain of the
+ 	 method's receiver, starting at mixin's application. This implementation is derived from
- implicitReceiverFor: rcvr mixin: mixin implementing: selector
- 	"This is used to implement the innards of the pushImplicitReceiverBytecode,
- 	 used for implicit receiver sends in NS2/NS3.  Find the nearest lexically-enclosing
- 	 implementation of selector by searching up the static chain of anObject,
- 	 starting at mixin's application.  This is an iterative implementation derived from
  
+ 	<ContextPart> implicitReceiverFor: methodReceiver <Object>
+ 					in: methodMixin <Mixin>
- 	<ContextPart> implicitReceiverFor: obj <Object>
- 					withMixin: mixin <Mixin>
  					implementing: selector <Symbol> ^<Object>"
  	<api>
  	<option: #NewspeakVM>
+ 	| candidateReceiver candidateMixin candidateMixinApplication dictionary found |
+ 	self deny: (objectMemory isOopForwarded: methodReceiver).
+ 	self deny: (objectMemory isForwarded: methodMixin).
- 	| mixinApplication dictionary found |
- 	self deny: (objectMemory isOopForwarded: rcvr).
- 	self deny: (objectMemory isForwarded: mixin).
  	"messageSelector is an implicit parameter of lookupMethodInDictionary:"
  	messageSelector := objectMemory followMaybeForwarded: selector.
+ 	candidateReceiver := methodReceiver.
+ 	candidateMixin := methodMixin.
+ 	[candidateMixinApplication := self
+ 		findApplicationOfTargetMixin: candidateMixin
+ 		startingAtBehavior: (objectMemory fetchClassOf: candidateReceiver).
+ 	 self deny: (candidateMixinApplication = objectMemory nilObject).
+ 	 dictionary := objectMemory followObjField: MethodDictionaryIndex ofObject: candidateMixinApplication.
- 	mixinApplication := self
- 							findApplicationOfTargetMixin: mixin
- 							startingAtBehavior: (objectMemory fetchClassOf: rcvr).
- 	 mixinApplication = objectMemory nilObject ifTrue:
- 		[^rcvr].
- 	 dictionary := objectMemory followObjField: MethodDictionaryIndex ofObject: mixinApplication.
  	 found := self lookupMethodInDictionary: dictionary.
+ 	 found ifTrue: [^candidateReceiver].
+ 	 candidateMixin := objectMemory followObjField: EnclosingMixinIndex ofObject: candidateMixin.
+ 	 candidateMixin = objectMemory nilObject]
+ 		whileFalse:
+ 			[candidateReceiver := objectMemory followObjField: EnclosingObjectIndex ofObject: candidateMixinApplication].
+ 	^methodReceiver!
- 	 found ifFalse:
- 		[| implicitReceiverOrNil theMixin |
- 		 theMixin := objectMemory followObjField: MixinIndex ofObject: mixinApplication.
- 		 implicitReceiverOrNil := self nextImplicitReceiverFor: (objectMemory
- 																followObjField: EnclosingObjectIndex
- 																ofObject: mixinApplication)
- 									withMixin: (objectMemory
- 													followObjField: EnclosingMixinIndex
- 													ofObject: theMixin).
- 		 implicitReceiverOrNil ~= objectMemory nilObject ifTrue:
- 			[^implicitReceiverOrNil]].
- 	^rcvr!

Item was changed:
  ----- Method: StackInterpreter>>instVar:ofContext: (in category 'frame access') -----
  instVar: offset ofContext: aContext
  	"Fetch an instance variable from a maybe married context.
  	 If the context is still married compute the value of the
  	 relevant inst var from the spouse frame's state."
  	| spouseFP |
  	<var: #spouseFP type: #'char *'>
  	<inline: true>
  	self assert: offset < MethodIndex.
  	self assert: (objectMemory isContext: aContext).
  	(self isMarriedOrWidowedContext: aContext) ifFalse:
  		[^objectMemory fetchPointer: offset ofObject: aContext].
  
  	self writeBackHeadFramePointers.
  	(self isWidowedContext: aContext) ifTrue:
  		[^objectMemory fetchPointer: offset ofObject: aContext].
  
  	spouseFP := self frameOfMarriedContext: aContext.
  	offset = SenderIndex ifTrue:
  		[^self ensureCallerContext: spouseFP].
  	offset = StackPointerIndex ifTrue:
  		[self assert: ReceiverIndex + (self stackPointerIndexForFrame: spouseFP) < (objectMemory lengthOf: aContext).
  		^objectMemory integerObjectOf: (self stackPointerIndexForFrame: spouseFP)].
  	offset = InstructionPointerIndex ifTrue:
+ 		[^self instructionPointerForFrame: spouseFP currentFP: localFP currentIP: (self oopForPointer: localIP)].
- 		[^self instructionPointerForFrame: spouseFP currentFP: localFP currentIP: localIP].
  	self error: 'bad index'.
  	^0!

Item was changed:
  ----- Method: StackInterpreter>>instructionPointerForFrame:currentFP:currentIP: (in category 'frame access') -----
  instructionPointerForFrame: spouseFP currentFP: currentFP currentIP: instrPtr
  	"Answer the bytecode pc object (i.e. SmallInteger) for an active frame.  The bytecode
  	 pc is derived from the frame's pc.  If the frame is the top frame on the current stack
  	 the frame pc is whatever the current instruction pointer is.  If the frame is the top
  	 frame on some other stack the frame pc is the value on top of stack.  Otherwise the
  	 frame pc is the saved pc of the frame above.  Once the frame pc is found it must be
  	 mapped to a bytecode pc."
+ 	<var: #spouseFP type: #'char *'>
+ 	<var: #currentFP type: #'char *'>
  	| theIP thePage theFPAbove |
+ 	<var: #thePage type: #'StackPage *'>
+ 	<var: #theFPAbove type: #'char *'>
  	spouseFP = currentFP
  		ifTrue: [theIP := self oopForPointer: instrPtr]
  		ifFalse:
  			[thePage := stackPages stackPageFor: spouseFP.
  			 theFPAbove := self findFrameAbove: spouseFP inPage: thePage.
  			 theIP := theFPAbove == 0
  						ifTrue: [stackPages longAt: thePage headSP]
  						ifFalse:[self oopForPointer: (self frameCallerSavedIP: theFPAbove)]].
  	^self contextInstructionPointer: theIP frame: spouseFP!

Item was removed:
- ----- Method: StackInterpreter>>nextImplicitReceiverFor:withMixin: (in category 'newspeak bytecode support') -----
- nextImplicitReceiverFor: anObject withMixin: mixin
- 	"This is used to implement the innards of the pushImplicitReceiverBytecode,
- 	 used for implicit receiver sends in NS2/NS3.  Find the nearest lexically-enclosing
- 	 implementation of selector by searching up the static chain of anObject,
- 	 starting at mixin's application.  This is an iterative implementation derived from
- 
- 	<ContextPart> nextImplicitReceiverFor: obj <Object>
- 					withMixin: mixin <Mixin>
- 					implementing: selector <Symbol> ^<Object>"
- 	| implicitReceiver mixinApplication theMixin targetMixin dictionary found |
- 	self deny: (objectMemory isOopForwarded: anObject).
- 	self deny: (objectMemory isForwarded: mixin).
- 	implicitReceiver := anObject.
- 	targetMixin := mixin.
- 	[(targetMixin = objectMemory nilObject "or: [implicitReceiver = objectMemory nilObject]") ifTrue:
- 		[^objectMemory nilObject].
- 	mixinApplication := self findApplicationOfTargetMixin: targetMixin
- 							startingAtNonMetaClass: (objectMemory fetchClassOf: implicitReceiver).
- 	 mixinApplication = objectMemory nilObject ifTrue:
- 		[^objectMemory nilObject].
- 	 dictionary := objectMemory followObjField: MethodDictionaryIndex ofObject: mixinApplication.
- 	 found := self lookupMethodInDictionary: dictionary.
- 	 found]
- 		whileFalse:
- 			[implicitReceiver := objectMemory followObjField: EnclosingObjectIndex ofObject: mixinApplication.
- 			 theMixin := objectMemory followObjField: MixinIndex ofObject: mixinApplication.
- 			 theMixin = objectMemory nilObject ifTrue:
- 				[^objectMemory nilObject].
- 			 targetMixin := objectMemory followObjField: EnclosingMixinIndex ofObject: theMixin].
- 	^implicitReceiver!

Item was changed:
  ----- Method: StackInterpreterPrimitives>>pathTo:using:followWeak: (in category 'object access primitives') -----
  pathTo: goal using: stack followWeak: followWeak
  	"Trace objects and frames from the root, marking visited objects, pushing the current path on stack, until goal is found.
  	 If found, unmark, leaving path in stack, and answer 0.  Otherwise answer an error:
  		PrimErrBadArgument if stack is not an Array
  		PrimErrBadIndex if search overflows stack
  		PrimErrNotFound if goal cannot be found"
  	| current index next stackSize stackp freeStartAtStart |
  	(objectMemory isArray: stack) ifFalse:
  		[^PrimErrBadArgument].
  	self assert: objectMemory allObjectsUnmarked.
  	freeStartAtStart := objectMemory freeStart. "check no allocations during search"
  	objectMemory beRootIfOld: stack. "so no store checks are necessary on stack"
  	stackSize := objectMemory lengthOf: stack.
  	objectMemory mark: stack.
  	"no need. the current context is not reachable from the active process (suspendedContext is nil)"
  	"objectMemory mark: self activeProcess."
  	current := objectMemory specialObjectsOop.
  	objectMemory mark: current.
  	index := objectMemory lengthOf: current.
  	stackp := 0.
  	[[(index := index - 1) >= -1] whileTrue:
  		[(stackPages couldBeFramePointer: current)
  			ifTrue:
  				[next := index >= 0
  							ifTrue: [self field: index ofFrame: (self cCoerceSimple: current to: #'char *')]
  							ifFalse: [objectMemory nilObject]]
  			ifFalse:
  				[index >= 0
  					ifTrue:
  						[next := (objectMemory isContextNonImm: current)
  									ifTrue: [self fieldOrSenderFP: index ofContext: current]
  									ifFalse: [objectMemory fetchPointer: index ofObject: current]]
  					ifFalse:
  						[next := objectMemory fetchClassOfNonImm: current]].
  		 (stackPages couldBeFramePointer: next)
+ 			ifTrue: [self assert: (self isFrame: (self cCoerceSimple: next to: #'char *')
+ 									onPage: (stackPages stackPageFor: (self cCoerceSimple: next to: #'char *')))]
- 			ifTrue: [self assert: (self isFrame: next onPage: (stackPages stackPageFor: next))]
  			ifFalse: [self assert: (self checkOkayOop: next)].
  		 next = goal ifTrue:
  			[self assert: freeStartAtStart = objectMemory freeStart.
  			 self unmarkAfterPathTo.
  			 objectMemory storePointer: stackp ofObject: stack withValue: current.
  			 self pruneStack: stack stackp: stackp.
  			 ^0].
  		 ((objectMemory isNonIntegerObject: next)
  		  and: [(stackPages couldBeFramePointer: next)
  				ifTrue: [(self frameIsMarked: next) not]
  				ifFalse:
  					[(objectMemory isMarked: next) not
  					  and: [((objectMemory isPointers: next) or: [objectMemory isCompiledMethod: next])
  					  and: [followWeak or: [(objectMemory isWeakNonImm: next) not]]]]])
  			ifTrue:
  				[stackp + 2 > stackSize ifTrue:
  					[self assert: freeStartAtStart = objectMemory freeStart.
  					 self unmarkAfterPathTo.
  					 objectMemory nilFieldsOf: stack.
  					 ^PrimErrBadIndex]. "PrimErrNoMemory ?"
  				 objectMemory
  					storePointerUnchecked: stackp ofObject: stack withValue: current;
  					storePointerUnchecked: stackp + 1 ofObject: stack withValue: (objectMemory integerObjectOf: index).
  				 stackp := stackp + 2.
  				 (stackPages couldBeFramePointer: (self cCoerceSimple: next to: #'char *'))
  					ifTrue:
  						[self markFrame: next.
  						index := self fieldsInFrame: (self cCoerceSimple: next to: #'char *')]
  					ifFalse:
  						[objectMemory mark: next.
  						 (objectMemory isCompiledMethod: next)
  							ifTrue: [index := (objectMemory literalCountOf: next) + LiteralStart]
  							ifFalse: [index := objectMemory lengthOf: next]].
  				 current := next]].
  		 current = objectMemory specialObjectsOop ifTrue:
  			[self assert: freeStartAtStart = objectMemory freeStart.
  			 self unmarkAfterPathTo.
  			 objectMemory nilFieldsOf: stack.
  			^PrimErrNotFound].
  		 index := objectMemory integerValueOf: (objectMemory fetchPointer: stackp - 1 ofObject: stack).
  		 current := objectMemory fetchPointer: stackp - 2 ofObject: stack.
  		 stackp := stackp - 2] repeat!

Item was removed:
- ----- Method: StackInterpreterSimulator>>nextImplicitReceiverFor:withMixin: (in category 'newspeak bytecode support') -----
- nextImplicitReceiverFor: anObject withMixin: mixin
- 	lookupCount := lookupCount + 1.
- 	^super nextImplicitReceiverFor: anObject withMixin: mixin!

Item was changed:
  ----- Method: StackToRegisterMappingCogit class>>initializeBytecodeTableForNewspeakV4 (in category 'class initialization') -----
  initializeBytecodeTableForNewspeakV4
  	"StackToRegisterMappingCogit initializeBytecodeTableForNewspeakV4"
  
  	numPushNilsFunction := #v4:Num:Push:Nils:.
  	pushNilSizeFunction := #v4PushNilSize:.
  	NSSendIsPCAnnotated := false. "IsNSSendCall used by SendAbsentImplicit"
  	FirstSpecialSelector := 80.
  	self flag:
  'Special selector send class must be inlined to agree with the interpreter, which
   inlines class.  If class is sent to e.g. a general instance of ProtoObject then unless
   class is inlined there will be an MNU.  It must be that the Cointerpreter and Cogit
   have identical semantics.  We get away with not hardwiring the other special
   selectors either because in the Cointerpreter they are not inlined or because they
   are inlined only to instances of classes for which there will always be a method.'.
  	self generatorTableFrom: #(
  		"1 byte bytecodes"
  		(1    0   15 genPushReceiverVariableBytecode needsFrameNever: 1)
  		(1  16   31 genPushLiteralVariable16CasesBytecode needsFrameNever: 1)
  		(1  32   63 genPushLiteralConstantBytecode needsFrameNever: 1)
  		(1  64   75 genPushTemporaryVariableBytecode needsFrameIfMod16GENumArgs: 1)
  		(1  76   76 genPushReceiverBytecode needsFrameNever: 1)
  		(1  77   77 genExtPushPseudoVariableOrOuterBytecode needsFrameIfExtBGT2: 1)
  		(1  78   78 genPushConstantZeroBytecode needsFrameNever: 1)
  		(1  79   79 genPushConstantOneBytecode needsFrameNever: 1)
  
  		(1   80   80 genSpecialSelectorArithmetic isMapped AddRR)
  		(1   81   81 genSpecialSelectorArithmetic isMapped SubRR)
  		(1   82   82 genSpecialSelectorComparison isMapped JumpLess)
  		(1   83   83 genSpecialSelectorComparison isMapped JumpGreater)
  		(1   84   84 genSpecialSelectorComparison isMapped JumpLessOrEqual)
  		(1   85   85 genSpecialSelectorComparison isMapped JumpGreaterOrEqual)
  		(1   86   86 genSpecialSelectorComparison isMapped JumpZero)
  		(1   87   87 genSpecialSelectorComparison isMapped JumpNonZero)
  		(1   88   93 genSpecialSelectorSend isMapped)	 " #* #/ #\\ #@ #bitShift: //"
  		(1   94   94 genSpecialSelectorArithmetic isMapped AndRR)
  		(1   95   95 genSpecialSelectorArithmetic isMapped OrRR)
  		(1   96 101 genSpecialSelectorSend isMapped) "#at: #at:put: #size #next #nextPut: #atEnd"
  		(1 102 102 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
  		(1 103 103 genSpecialSelectorClass needsFrameIfStackGreaterThanOne: notMapped 0) "not mapped because it is directly inlined (for now)"
  		(1 104 111 genSpecialSelectorSend isMapped) "#blockCopy: #value #value: #do: #new #new: #x #y"
  
  		(1 112 127 genSendLiteralSelector0ArgsBytecode isMapped)
  		(1 128 143 genSendLiteralSelector1ArgBytecode isMapped)
  		(1 144 159 genSendLiteralSelector2ArgsBytecode isMapped)
  		(1 160 175	genSendAbsentImplicit0ArgsBytecode isMapped hasIRC)
  
  		(1 176 183 genStoreAndPopReceiverVariableBytecode needsFrameNever: -1) "N.B. not frameless if immutability"
  		(1 184 191 genStoreAndPopTemporaryVariableBytecode)
  
  		(1 192 199 genShortUnconditionalJump	branch v3:ShortForward:Branch:Distance:)
  		(1 200 207 genShortJumpIfTrue			branch isBranchTrue isMapped "because of mustBeBoolean"
  													v3:ShortForward:Branch:Distance:)
  		(1 208 215 genShortJumpIfFalse			branch isBranchFalse isMapped "because of mustBeBoolean"
  													v3:ShortForward:Branch:Distance:)
  
  		(1 216 216 genReturnReceiver				return needsFrameIfInBlock: isMappedInBlock 0)
  		(1 217 217 genReturnTopFromMethod		return needsFrameIfInBlock: isMappedInBlock -1)
  		(1 218 218 genExtReturnTopFromBlock	return needsFrameNever: -1)
  
  		(1 219 219 duplicateTopBytecode			needsFrameNever: 1)
  		(1 220 220 genPopStackBytecode			needsFrameNever: -1)
  		(1 221 221 genExtNopBytecode			needsFrameNever: 0)
  		(1 222 223	unknownBytecode)
  
  		"2 byte bytecodes"
  		(2 224 224 extABytecode extension					needsFrameNever: 0)
  		(2 225 225 extBBytecode extension					needsFrameNever: 0)
  		(2 226 226 genExtPushReceiverVariableBytecode)
  		(2 227 227 genExtPushLiteralVariableBytecode		needsFrameNever: 1)
  		(2 228 228 genExtPushLiteralBytecode					needsFrameNever: 1)
  		(2 229 229 genExtPushIntegerBytecode				needsFrameNever: 1)
  		(2 230 230 genLongPushTemporaryVariableBytecode)
  		(2 231 231 genPushNewArrayBytecode)
  		(2 232 232 genExtStoreReceiverVariableBytecode)
  		(2 233 233 genExtStoreLiteralVariableBytecode)
  		(2 234 234 genLongStoreTemporaryVariableBytecode)
  		(2 235 235 genExtStoreAndPopReceiverVariableBytecode)
  		(2 236 236 genExtStoreAndPopLiteralVariableBytecode)
  		(2 237 237 genLongStoreAndPopTemporaryVariableBytecode)
  
  		(2 238 238 genExtSendBytecode isMapped)
  		(2 239 239 genExtSendSuperBytecode isMapped)
  		(2 240 240 genExtSendAbsentImplicitBytecode isMapped hasIRC)
  		(2 241 241 genExtSendAbsentDynamicSuperBytecode isMapped)
  
  		(2 242 242 genExtUnconditionalJump	branch isMapped "because of interrupt check" v4:Long:Branch:Distance:)
  		(2 243 243 genExtJumpIfTrue			branch isBranchTrue isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
  		(2 244 244 genExtJumpIfFalse			branch isBranchFalse isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
  
+ 		(2 245 245	genExtSendAbsentSelfBytecode isMapped)
- 		(2 245 248	unknownBytecode)
  
+ 		(2 246 248	unknownBytecode)
+ 
  		"3 byte bytecodes"
  		(3 249 249 callPrimitiveBytecode)
  		(3 250 250 genPushRemoteTempLongBytecode)
  		(3 251 251 genStoreRemoteTempLongBytecode)
  		(3 252 252 genStoreAndPopRemoteTempLongBytecode)
  		(3 253 253 genExtPushClosureBytecode block v4:Block:Code:Size:)
+ 		(3 254 254	genExtSendAbsentOuterBytecode isMapped)
  
+ 		(3 255 255	unknownBytecode))!
- 		(3 254 255	unknownBytecode))!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genSendAbsentDynamicSuper:numArgs: (in category 'bytecode generators') -----
  genSendAbsentDynamicSuper: selector numArgs: numArgs
  	"OK, we could do better and avoid spilling ReceiverResultReg if we refactored
  	 marshallImplicitReceiverSendArguments: to take a flag saying whether the
  	 receiver was in ReceiverResultReg (absent receiver send) or on the stack
  	 (absent dynamic super send) and in the latter case loading ReceiverResultReg
  	 from the stack after marshalling.  But this is a rare bytecode so for the moment
  	 don't bother."
  	self ssAllocateCallReg: ReceiverResultReg.
  	self MoveMw: FoxMFReceiver r: FPReg R: ReceiverResultReg.
+ 	self marshallAbsentReceiverSendArguments: numArgs.
- 	self marshallImplicitReceiverSendArguments: numArgs.
  	^self genMarshalledSendDynamicSuper: selector numArgs: numArgs!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genSendAbsentImplicit:numArgs: (in category 'bytecode generators') -----
  genSendAbsentImplicit: selector numArgs: numArgs
  	"Get the implicit receiver and marshall arguments, shuffling the
  	 stack to push the implicit receiver if necessary. Then send."
  	<inline: false>
  	| result |
  	"This must not be PC-mapped"
  	result := self genGetImplicitReceiverFor: selector forPush: false.
  	result ~= 0 ifTrue:
  		[^result].
+ 	self marshallAbsentReceiverSendArguments: numArgs.
- 	self marshallImplicitReceiverSendArguments: numArgs.
  	^self genMarshalledSend: selector numArgs: numArgs!

Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genSendAbsentOuter:numArgs:depth: (in category 'bytecode generators') -----
+ genSendAbsentOuter: selector numArgs: numArgs depth: depth
+ 	"OK, we could do better and avoid spilling ReceiverResultReg if we refactored
+ 	 marshallAbsentReceiverSendArguments: to take a flag saying whether the
+ 	 receiver was in ReceiverResultReg (absent receiver send) or on the stack
+ 	 (absent dynamic super send) and in the latter case loading ReceiverResultReg
+ 	 from the stack after marshalling.  But this is a rare bytecode so for the moment
+ 	 don't bother."
+ 	optStatus isReceiverResultRegLive: false.
+ 	self ssAllocateCallReg: SendNumArgsReg.
+ 	self MoveCq: depth R: SendNumArgsReg.
+ 	self CallRT: ceEnclosingObjectTrampoline.
+ 	self marshallAbsentReceiverSendArguments: numArgs.
+ 	^self genMarshalledSend: selector numArgs: numArgs!

Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genSendAbsentSelf:numArgs: (in category 'bytecode generators') -----
+ genSendAbsentSelf: selector numArgs: numArgs
+ 	"OK, we could do better and avoid spilling ReceiverResultReg if we refactored
+ 	 marshallAbsentReceiverSendArguments: to take a flag saying whether the
+ 	 receiver was in ReceiverResultReg (absent receiver send) or on the stack
+ 	 (absent dynamic super send) and in the latter case loading ReceiverResultReg
+ 	 from the stack after marshalling.  But this is a rare bytecode so for the moment
+ 	 don't bother."
+ 	self ssAllocateCallReg: ReceiverResultReg.
+ 	self MoveMw: FoxMFReceiver r: FPReg R: ReceiverResultReg.
+ 	self marshallAbsentReceiverSendArguments: numArgs.
+ 	^self genMarshalledSend: selector numArgs: numArgs!

Item was added:
+ ----- Method: StackToRegisterMappingCogit>>marshallAbsentReceiverSendArguments: (in category 'simulation stack') -----
+ marshallAbsentReceiverSendArguments: numArgs
+ 	"Spill everything on the simulated stack that needs spilling (that below arguments).
+ 	 Marshall arguments to stack and/or registers depending on arg count.
+ 	 If the args don't fit in registers push receiver and args (spill everything).  Assume
+ 	 receiver already in ResultReceiverReg so shuffle args and push it if necessary."
+ 	self ssFlushTo: simStackPtr - numArgs.
+ 	numArgs > self numRegArgs
+ 		ifTrue:
+ 			["The arguments must be pushed to the stack, and hence the receiver
+ 			   must be inserted beneath the args.  Reduce or eliminate the argument
+ 			   shuffle by only moving already spilled items."
+ 			| numSpilled |
+ 			numSpilled := self numberOfSpillsInTopNItems: numArgs.
+ 			numSpilled > 0
+ 				ifTrue:
+ 					[self MoveMw: 0 r: SPReg R: TempReg.
+ 					 self PushR: TempReg.
+ 					 2 to: numSpilled do:
+ 						[:index|
+ 						self MoveMw: index * BytesPerWord r: SPReg R: TempReg.
+ 						self MoveR: TempReg Mw: index - 1 * BytesPerWord r: SPReg].
+ 					 self MoveR: ReceiverResultReg Mw: numSpilled * BytesPerWord r: SPReg]
+ 				ifFalse:
+ 					[self PushR: ReceiverResultReg].
+ 			self ssFlushTo: simStackPtr]
+ 		"Move the args to the register arguments, being careful to do
+ 		 so last to first so e.g. previous contents don't get overwritten.
+ 		 Also check for any arg registers in use by other args."
+ 		ifFalse:
+ 			[numArgs > 0 ifTrue:
+ 				[(self numRegArgs > 1 and: [numArgs > 1])
+ 					ifTrue:
+ 						[self ssAllocateRequiredReg: Arg0Reg upThrough: simStackPtr - 2.
+ 						 self ssAllocateRequiredReg: Arg1Reg upThrough: simStackPtr - 1]
+ 					ifFalse:
+ 						[self ssAllocateRequiredReg: Arg0Reg upThrough: simStackPtr - 1]].
+ 			 (self numRegArgs > 1 and: [numArgs > 1]) ifTrue:
+ 				[(self simStackAt: simStackPtr) popToReg: Arg1Reg].
+ 			 numArgs > 0 ifTrue:
+ 				[(self simStackAt: simStackPtr - numArgs + 1)
+ 					popToReg: Arg0Reg]].
+ 	self ssPop: numArgs!

Item was removed:
- ----- Method: StackToRegisterMappingCogit>>marshallImplicitReceiverSendArguments: (in category 'simulation stack') -----
- marshallImplicitReceiverSendArguments: numArgs
- 	"Spill everything on the simulated stack that needs spilling (that below arguments).
- 	 Marshall arguments to stack and/or registers depending on arg count.
- 	 If the args don't fit in registers push receiver and args (spill everything).  Assume
- 	 receiver already in ResultReceiverReg so shuffle args and push it if necessary."
- 	self ssFlushTo: simStackPtr - numArgs.
- 	numArgs > self numRegArgs
- 		ifTrue:
- 			["The arguments must be pushed to the stack, and hence the receiver
- 			   must be inserted beneath the args.  Reduce or eliminate the argument
- 			   shuffle by only moving already spilled items."
- 			| numSpilled |
- 			numSpilled := self numberOfSpillsInTopNItems: numArgs.
- 			numSpilled > 0
- 				ifTrue:
- 					[self MoveMw: 0 r: SPReg R: TempReg.
- 					 self PushR: TempReg.
- 					 2 to: numSpilled do:
- 						[:index|
- 						self MoveMw: index * BytesPerWord r: SPReg R: TempReg.
- 						self MoveR: TempReg Mw: index - 1 * BytesPerWord r: SPReg].
- 					 self MoveR: ReceiverResultReg Mw: numSpilled * BytesPerWord r: SPReg]
- 				ifFalse:
- 					[self PushR: ReceiverResultReg].
- 			self ssFlushTo: simStackPtr]
- 		"Move the args to the register arguments, being careful to do
- 		 so last to first so e.g. previous contents don't get overwritten.
- 		 Also check for any arg registers in use by other args."
- 		ifFalse:
- 			[numArgs > 0 ifTrue:
- 				[(self numRegArgs > 1 and: [numArgs > 1])
- 					ifTrue:
- 						[self ssAllocateRequiredReg: Arg0Reg upThrough: simStackPtr - 2.
- 						 self ssAllocateRequiredReg: Arg1Reg upThrough: simStackPtr - 1]
- 					ifFalse:
- 						[self ssAllocateRequiredReg: Arg0Reg upThrough: simStackPtr - 1]].
- 			 (self numRegArgs > 1 and: [numArgs > 1]) ifTrue:
- 				[(self simStackAt: simStackPtr) popToReg: Arg1Reg].
- 			 numArgs > 0 ifTrue:
- 				[(self simStackAt: simStackPtr - numArgs + 1)
- 					popToReg: Arg0Reg]].
- 	self ssPop: numArgs!

Item was changed:
  ----- Method: VMMaker class>>generateAllNewspeakConfigurationsUnderVersionControl (in category 'configurations') -----
  generateAllNewspeakConfigurationsUnderVersionControl
  	self generateNewspeakCogVM;
+ 		generateNewspeakSpurStackVM;
  		generateNewspeakSpurCogVM!



More information about the Vm-dev mailing list