Advertisement
Guest User

StackEvtInterpreter.st

a guest
Jul 17th, 2011
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 'From Pharo1.3 of 16 June 2011 [Latest update: #13281] on 17 July 2011 at 10:44:32 pm'!
  2. StackInterpreterPrimitives subclass: #StackEvtInterpreter
  3.     instanceVariableNames: 'jmpBufExit'
  4.     classVariableNames: ''
  5.     poolDictionaries: ''
  6.     category: 'VMMaker-Interpreter'!
  7. !StackEvtInterpreter commentStamp: 'golubovsky 7/9/2011 21:24' prior: 0!
  8. This is a subclass of the StackInterpreter which implements the specifics of the Event-driven Cog Stack VM!
  9.  
  10.  
  11. !StackEvtInterpreter methodsFor: 'callback support' stamp: 'golubovsky 7/12/2011 22:45'!
  12. callbackEnter: callbackID
  13.     "Callbacks are disabled in Event VM"
  14.     <export: true>
  15.     <var: #callbackID type: #'sqInt *'>
  16.         [^false].! !
  17.  
  18.  
  19. !StackEvtInterpreter methodsFor: 'initialization' stamp: 'golubovsky 7/11/2011 06:45'!
  20. initStackPagesAndInterpret
  21.     "Initialize the stack pages and enter interpret. Use alloca'ed memory so that when
  22.      we have a JIT its stack pointer will be on the native stack since alloca allocates
  23.      memory on the stack. Certain thread systems use the native stack pointer as the
  24.      frame ID so putting the stack anywhere else can confuse the thread system."
  25.    
  26.     "This method overrides its parent so that heartbeat is not initialized: EventVM does not
  27.     have hartbeat."
  28.  
  29.     "This should be in its own initStackPages method but Slang can't inline
  30.      C code strings."
  31.     | stackPageBytes stackPagesBytes theStackMemory |
  32.     <var: #theStackMemory type: #'void *'>
  33.     stackPageBytes := self stackPageByteSize.
  34.     stackPagesBytes := self computeStackZoneSize.
  35.     theStackMemory := self
  36.                         cCode: 'alloca(stackPagesBytes)'
  37.                         inSmalltalk:
  38.                             [stackPages := self stackPagesClass new.
  39.                              stackPages initializeWithByteSize: stackPagesBytes for: self].
  40.     stackPages
  41.         initializeStack: theStackMemory
  42.         numSlots: stackPagesBytes / BytesPerWord
  43.         pageSize: stackPageBytes / BytesPerWord
  44.         stackLimitOffset: self stackLimitOffset
  45.         stackPageHeadroom: self stackPageHeadroom.
  46.  
  47.     "Once the stack pages are initialized we can continue to bootstrap the system."
  48.     self loadInitialContext.
  49.     self interpret.
  50.     ^nil! !
  51.  
  52.  
  53.  
  54. !StackEvtInterpreter methodsFor: 'interpreter shell' stamp: 'golubovsky 7/13/2011 22:32'!
  55. interpret
  56.     "This is the main interpreter loop. It normally loops forever, fetching and executing bytecodes. When running in the context of a browser plugin VM, however, it must return control to the browser periodically. This should done only when the state of the currently running Squeak thread is safely stored in the object heap. Since this is the case at the moment that a check for interrupts is performed, that is when we return to the browser if it is time to do so. Interrupt checks happen quite frequently. The EventVM version of interpreter also has a special jmp_buf used to bail out of the interpreter once no processes are ready to run. If returned for no events available, return value is 0, and if returned as normal VM termination, return value is 1. The host program may use this information to determine when to loop"
  57.  
  58.     | result |
  59.     <inline: false>
  60.     "If stacklimit is zero then the stack pages have not been initialized."
  61.     stackLimit = 0 ifTrue:
  62.         [^self initStackPagesAndInterpret].
  63.     "record entry time when running as a browser plug-in"
  64.     self browserPluginInitialiseIfNeeded.
  65.     "set up a jmp_buf to bail out when no processes are ready to run"
  66.     result := self cCode: 'setjmp(jmpBufExit)'
  67.                 inSmalltalk:[jmpBufExit := [^self]. 0].
  68.     result = 0 ifFalse:[^0].    "return 0 when suspended for an event"
  69.     self internalizeIPandSP.
  70.     self fetchNextBytecode.
  71.     [true] whileTrue: [self dispatchOn: currentBytecode in: BytecodeTable].
  72.     localIP := localIP - 1.  "undo the pre-increment of IP before returning"
  73.     self externalizeIPandSP.
  74.     ^1  "return 1 if normal VM termination"
  75. ! !
  76.  
  77.  
  78. !StackEvtInterpreter methodsFor: 'process primitive support' stamp: 'golubovsky 7/17/2011 00:10'!
  79. transferTo: newProc
  80.     "Record a process to be awoken on the next interpreter cycle."
  81.     "If such process is nil bail out of the interpreter"
  82.     | activeContext sched oldProc |
  83.     <inline: false>
  84.     statProcessSwitch := statProcessSwitch + 1.
  85.     self push: instructionPointer.
  86.     self externalWriteBackHeadFramePointers.
  87.     sched := self schedulerPointer.
  88.     oldProc := objectMemory fetchPointer: ActiveProcessIndex ofObject: sched.
  89.     activeContext := self ensureFrameIsMarried: framePointer SP: stackPointer.
  90.     objectMemory storePointer: SuspendedContextIndex ofObject: oldProc withValue: activeContext.
  91.     newProc == nil ifTrue:[
  92.         self cCode:'longjmp(jmpBufExit, 1)'
  93.                 inSmalltalk:[jmpBufExit value].
  94.     ].
  95.     objectMemory storePointer: ActiveProcessIndex ofObject: sched withValue: newProc.
  96.     objectMemory storePointerUnchecked: MyListIndex ofObject: newProc withValue: objectMemory nilObject.
  97.     self externalSetStackPageAndPointersForSuspendedContextOfProcess: newProc.
  98.     instructionPointer := self popStack
  99. ! !
  100.  
  101. !StackEvtInterpreter methodsFor: 'process primitive support' stamp: 'golubovsky 7/16/2011 21:54'!
  102. wakeHighestPriority
  103.     "Return the highest priority process that is ready to run.
  104.      To save time looking at many empty lists before finding a
  105.      runnable process the VM maintains a variable holding the
  106.      highest priority runnable process.  If this variable is 0 then the
  107.      VM does not know the highest priority and must search all lists."
  108.     | schedLists p processList |
  109.     schedLists := objectMemory fetchPointer: ProcessListsIndex ofObject: self schedulerPointer.
  110.     p := highestRunnableProcessPriority = 0
  111.             ifTrue: [objectMemory fetchWordLengthOf: schedLists]
  112.             ifFalse: [highestRunnableProcessPriority].
  113.     p := p - 1.
  114.     "index of last indexable field"
  115.     [processList := objectMemory fetchPointer: p ofObject: schedLists.
  116.      self isEmptyList: processList] whileTrue:
  117.         [(p := p - 1) < 0 ifTrue:
  118.             [^nil]
  119.         ].
  120.     highestRunnableProcessPriority := p + 1.
  121.     ^self removeFirstLinkOfList: processList! !
  122.  
  123. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  124.  
  125. StackEvtInterpreter class
  126.     instanceVariableNames: ''!
  127.  
  128. !StackEvtInterpreter class methodsFor: 'translation' stamp: 'golubovsky 7/13/2011 06:19'!
  129. declareCVarsIn: aCCodeGenerator
  130.     "define the jmpbuf for bailing out of the interpreter: its definition will be added
  131.     to the definitions made by the parent classes - no super call is necessary"
  132.     aCCodeGenerator var: #jmpBufExit declareC: 'jmp_buf jmpBufExit'.! !
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement