[Vm-dev] About Cog on linux

Igor Stasenko siguctua at gmail.com
Fri Feb 11 19:53:57 UTC 2011


Ok, i traced the interpret loop up to the point execution takes
different(wrong) route.

Given the method:


snapshot: save andQuit: quit embedded: embeddedFlag
	"Mark the changes file and close all files as part of #processShutdownList.
	If save is true, save the current state of this Smalltalk in the image file.
	If quit is true, then exit to the outer OS shell.
	The latter part of this method runs when resuming a previously saved
image. This resume logic checks for a document file to process when
starting up."

	| snapshotResult resuming msg |
	Object flushDependents.
	Object flushEvents.
	(SourceFiles at: 2)
		ifNotNil: [
			msg := String
				streamContents: [ :s |
					s
						nextPutAll: '----';
						nextPutAll:
								(save
										ifTrue: [
											quit
												ifTrue: [ 'QUIT' ]
												ifFalse: [ 'SNAPSHOT' ] ]
										ifFalse: [
											quit
												ifTrue: [ 'QUIT/NOSAVE' ]
												ifFalse: [ 'NOP' ] ]);
						nextPutAll: '----';
						print: Date dateAndTimeNow;
						space;
						nextPutAll: (FileDirectory default localNameFor: self imageName);
						nextPutAll: ' priorSource: ';
						print: LastQuitLogPosition ].
			self assureStartupStampLogged.
			save
				ifTrue: [
					LastQuitLogPosition := (SourceFiles at: 2)
						setToEnd;
						position ].
			self logChange: msg.
			Transcript
				cr;
				show: msg ].
	self processShutDownList: quit.
	Cursor write show.
	save
		ifTrue: [
			snapshotResult := embeddedFlag
				ifTrue: [ self snapshotEmbeddedPrimitive ]
				ifFalse: [ self snapshotPrimitive ].	"<-- PC frozen here on image file"
			resuming := snapshotResult == true.
			snapshotResult == false
				ifTrue: [
					"Time to reclaim segment files is immediately after a save"
					Smalltalk globals at: #ImageSegment ifPresent: [ :theClass |
theClass reclaimObsoleteSegmentFiles ] ]	"guard against failure" ]
		ifFalse: [ resuming := false ].
	(quit and: [ resuming not ])
		ifTrue: [ self quitPrimitive ].
	Cursor normal show.
	self setGCParameters.
	resuming
		ifTrue: [ Smalltalk clearExternalObjects ].
	self processStartUpList: resuming.
	resuming
		ifTrue: [ self recordStartupStamp ].
	UIManager default onSnapshot: resuming.	"Now it's time to raise an error"
	snapshotResult == nil
		ifTrue: [ self error: 'Failed to write image file (disk full?)' ].
		
	^ resuming
------------

And its bytecode:

-------------

217 <41> pushLit: Object
218 <D0> send: flushDependents
219 <87> pop
220 <41> pushLit: Object
221 <D2> send: flushEvents
222 <87> pop
223 <56> pushLit: SourceFiles
224 <77> pushConstant: 2
225 <C0> send: at:
226 <73> pushConstant: nil
227 <C6> send: ==
228 <A8 5B> jumpTrue: 321
230 <44> pushLit: String
231 <10> pushTemp: 0
232 <11> pushTemp: 1
233 <8F 21 00 32> closureNumCopied: 2 numArgs: 1 bytes 237 to 286
237 	<10> pushTemp: 0
238 	<88> dup
239 	<26> pushConstant: '----'
240 	<E5> send: nextPutAll:
241 	<87> pop
242 	<88> dup
243 	<11> pushTemp: 1
244 	<9D> jumpFalse: 251
245 	<12> pushTemp: 2
246 	<99> jumpFalse: 249
247 	<2A> pushConstant: 'QUIT'
248 	<90> jumpTo: 250
249 	<29> pushConstant: 'SNAPSHOT'
250 	<94> jumpTo: 256
251 	<12> pushTemp: 2
252 	<99> jumpFalse: 255
253 	<28> pushConstant: 'QUIT/NOSAVE'
254 	<90> jumpTo: 256
255 	<27> pushConstant: 'NOP'
256 	<E5> send: nextPutAll:
257 	<87> pop
258 	<88> dup
259 	<26> pushConstant: '----'
260 	<E5> send: nextPutAll:
261 	<87> pop
262 	<88> dup
263 	<4D> pushLit: Date
264 	<DC> send: dateAndTimeNow
265 	<EB> send: print:
266 	<87> pop
267 	<88> dup
268 	<DE> send: space
269 	<87> pop
270 	<88> dup
271 	<51> pushLit: FileDirectory
272 	<83 10> send: default
274 	<70> self
275 	<83 12> send: imageName
277 	<EF> send: localNameFor:
278 	<E5> send: nextPutAll:
279 	<87> pop
280 	<88> dup
281 	<33> pushConstant: ' priorSource: '
282 	<E5> send: nextPutAll:
283 	<87> pop
284 	<54> pushLit: LastQuitLogPosition
285 	<EB> send: print:
286 	<7D> blockReturn
287 <E3> send: streamContents:
288 <6D> popIntoTemp: 5
289 <70> self
290 <83 15> send: assureStartupStampLogged
292 <87> pop
293 <10> pushTemp: 0
294 <AC 0B> jumpFalse: 307
296 <56> pushLit: SourceFiles
297 <77> pushConstant: 2
298 <C0> send: at:
299 <88> dup
300 <83 17> send: setToEnd
302 <87> pop
303 <83 18> send: position
305 <82 D4> popIntoLit: LastQuitLogPosition
307 <70> self
308 <15> pushTemp: 5
309 <83 39> send: logChange:
311 <87> pop
312 <5A> pushLit: Transcript
313 <88> dup
314 <83 1B> send: cr
316 <87> pop
317 <15> pushTemp: 5
318 <83 3C> send: show:
320 <87> pop
321 <70> self
322 <11> pushTemp: 1
323 <83 3D> send: processShutDownList:
325 <87> pop
326 <80 E0> pushLit: Cursor
328 <83 1F> send: write
330 <83 1E> send: show
332 <87> pop
333 <10> pushTemp: 0
334 <AC 26> jumpFalse: 374
336 <12> pushTemp: 2
337 <9B> jumpFalse: 342
338 <70> self
339 <86 22> send: snapshotEmbeddedPrimitive
341 <92> jumpTo: 345
342 <70> self
343 <86 21> send: snapshotPrimitive
345 <6B> popIntoTemp: 3
346 <13> pushTemp: 3
347 <71> pushConstant: true
348 <C6> send: ==
349 <6C> popIntoTemp: 4
350 <13> pushTemp: 3
351 <72> pushConstant: false
352 <C6> send: ==
353 <AC 11> jumpFalse: 372
355 <80 E5> pushLit: Smalltalk
357 <86 24> send: globals
359 <80 A6> pushConstant: #ImageSegment
361 <8F 01 00 04> closureNumCopied: 0 numArgs: 1 bytes 365 to 368
365 	<10> pushTemp: 0
366 	<86 27> send: reclaimObsoleteSegmentFiles
368 	<7D> blockReturn
369 <86 A3> send: at:ifPresent:
371 <90> jumpTo: 373
372 <73> pushConstant: nil
373 <92> jumpTo: 377
374 <72> pushConstant: false
375 <81 44> storeIntoTemp: 4
377 <87> pop
378 <11> pushTemp: 1
379 <9B> jumpFalse: 384
380 <14> pushTemp: 4
381 <86 29> send: not
383 <90> jumpTo: 385
384 <72> pushConstant: false
385 <9B> jumpFalse: 390
386 <70> self
387 <86 28> send: quitPrimitive
389 <87> pop
390 <80 E0> pushLit: Cursor
392 <86 2A> send: normal
394 <83 1E> send: show
396 <87> pop
397 <70> self
398 <86 2B> send: setGCParameters
400 <87> pop
401 <14> pushTemp: 4
402 <9C> jumpFalse: 408
403 <80 E5> pushLit: Smalltalk
405 <86 2C> send: clearExternalObjects
407 <87> pop
408 <70> self
409 <14> pushTemp: 4
410 <86 6D> send: processStartUpList:
412 <87> pop
413 <14> pushTemp: 4
414 <9B> jumpFalse: 419
415 <70> self
416 <86 2E> send: recordStartupStamp
418 <87> pop
419 <80 F0> pushLit: UIManager
421 <83 10> send: default
423 <14> pushTemp: 4
424 <86 6F> send: onSnapshot:
426 <87> pop
427 <13> pushTemp: 3
428 <73> pushConstant: nil
429 <C6> send: ==
430 <9D> jumpFalse: 437
431 <70> self
432 <80 B2> pushConstant: 'Failed to write image file (disk full?)'
434 <86 71> send: error:
436 <87> pop
437 <14> pushTemp: 4
438 <7C> returnTop

-----

it is diverging from simulator at bytecode
378 <11> pushTemp: 1

which is instead of pushing quit = true, pushes nil.
Then of course next bytecode (jumpFalse:) fails and it sends
#mustBeBoolean: to nil object.

Apparently either stack is imbalanced (so it points to wrong stack
frame which has nil at temp=1 offset),
or something overwrites this argument by nil, for some unknown reason.

Now the question is where this nil came from and who wrote it there. :)


Here the stack frame when loading this image in simulator and before
starting any interpretation:


  -16r27C14 SmalltalkImage>snapshot:andQuit:embedded: 2268340: a(n)
SmalltalkImage
  -16r27C00/512:   rcvr/clsr:   16r229CB4	a SmalltalkImage
  -16r27C04/511:         arg:       16r14	true
  -16r27C08/510:         arg:       16r14	true
  -16r27C0C/509:         arg:        16rC	false
  -16r27C10/508:cllr ip/ctxt:  16r1A8F5E0=27850208
  -16r27C14/507:    saved fp:        16r0
  -16r27C18/506:      method:   16r918D24	a CompiledMethod
  -16r27C1C/505:       flags:    16r10301=66305  numArgs: 3
hasContext: true  isBlock: false
  -16r27C20/504:     context:  16r1A8F63C=27850300
  -16r27C24/503:    receiver:   16r229CB4	a SmalltalkImage
  -16r27C28/502:   temp/stck:        16r4	nil
  -16r27C2C/501:   temp/stck:        16r4	nil
  -16r27C30/500:   temp/stck:  16r1A8FEF8	'----QUIT----an Array(10
February 2011 7:56:30 pm) generator.image priorSource: 24702567'
  -16r27C34/499:   temp/stck:       16r14	true

And evaluating:

(self temporary: 1 in: localFP) == objectMemory  trueObject

in simulator yields true, which seems correct.

Here the stack at the point of pushing quit flag (temp1):

  -16r27C14 SmalltalkImage>snapshot:andQuit:embedded: 2268340: a(n)
SmalltalkImage
  -16r27C00/512:   rcvr/clsr:   16r229CB4	a SmalltalkImage
  -16r27C04/511:         arg:       16r14	true
  -16r27C08/510:         arg:       16r14	true
  -16r27C0C/509:         arg:        16rC	false
  -16r27C10/508:cllr ip/ctxt:  16r1A8F5E0=27850208
  -16r27C14/507:    saved fp:        16r0
  -16r27C18/506:      method:   16r918D24	a CompiledMethod
  -16r27C1C/505:       flags:    16r10301=66305  numArgs: 3
hasContext: true  isBlock: false
  -16r27C20/504:     context:  16r1A8F63C=27850300
  -16r27C24/503:    receiver:   16r229CB4	a SmalltalkImage
  -16r27C28/502:   temp/stck:       16r14	true
  -16r27C2C/501:   temp/stck:       16r14	true
  -16r27C30/500:   temp/stck:  16r1A8FEF8	'----QUIT----an Array(10
February 2011 7:56:30 pm) generator.image priorSource: 24702567'
378	11 pushTemporaryVariableBytecode (12)

and it reads value from
 -16r27C08/510:         arg:       16r14	true
when performing #pushTemporaryVariableBytecode

So, in simulator it looks fine :)


-- 
Best regards,
Igor Stasenko AKA sig.


More information about the Vm-dev mailing list