Hi Eliot.

2016-06-06 1:13 GMT+02:00 Eliot Miranda <[email protected]>:

> That's simply not true.  In fact the amount known of the VM in both the
> bytecode debugger and the AST debugger is the same; both use VM primitives
> that aren't specified at the image level.
>
> Both the AST interpreter and the bytecode interpreter include the
> interpreter in Smalltalk in the image.  Look at Context and
> InstructionStream to find the Smalktalk definitions of both the interpreter
> routines and the implementations of the bytecodes.
>
>
> So my question is why our debuggers are not based on AST interpreter? Why
> it is bad idea? (if it is bad).
>
>
> One area where you'll find the AST debugger  worse is in performance.  The
> bytecode debugger uses perform: to execute at full speed when possible (it
> does interpret when doing step into or through, but not when doing over).
> In fact this part of the system, because it has to catch no local returns
> and exceptions, is the most complex, but it's not because of VM details,
> it's because of the use of perform: to run code being debugged to run at
> full speed.
>
> Not to mention, if it isn't broke don't fix it.
>
> But seriously, the system is based on bytecode, and that bytecode is
> pretty straightforward and easy to learn.  Why not put in the effort of
> learning it?
>
> Criticizing something in ignorance is not wise IMO.
>

I just put this method here:

InstructionStream >>interpretNextV3PlusClosureInstructionFor: client
> "Send to the argument, client, a message that specifies the type of the
> next instruction."
> | byte type offset method |
> method := self method.
> byte := method at: pc.
> type := byte // 16.
> offset := byte \\ 16.
> pc := pc+1.
> "We do an inline binary search on each of the possible 16 values of type:
> The old, cleaner but slowe code is retained as a comment below"
> type < 8
> ifTrue: [type < 4
> ifTrue: [type < 2
> ifTrue: [type < 1
> ifTrue: ["type = 0"
> ^ client pushReceiverVariable: offset]
> ifFalse: ["type = 1"
> ^ client pushTemporaryVariable: offset]]
> ifFalse: [type < 3
> ifTrue: ["type = 2"
> ^ client
> pushConstant: (method literalAt: offset + 1)]
> ifFalse: ["type = 3"
> ^ client
> pushConstant: (method literalAt: offset + 17)]]]
> ifFalse: [type < 6
> ifTrue: [type < 5
> ifTrue: ["type = 4"
> ^ client
> pushLiteralVariable: (method literalAt: offset + 1)]
> ifFalse: ["type = 5"
> ^ client
> pushLiteralVariable: (method literalAt: offset + 17)]]
> ifFalse: [type < 7
> ifTrue: ["type = 6"
> offset < 8
> ifTrue: [^ client popIntoReceiverVariable: offset]
> ifFalse: [^ client popIntoTemporaryVariable: offset - 8]]
> ifFalse: ["type = 7"
> offset = 0
> ifTrue: [^ client pushReceiver].
> offset < 8
> ifTrue: [^ client
> pushConstant: (SpecialConstants at: offset)].
> offset = 8
> ifTrue: [^ client methodReturnReceiver].
> offset < 12
> ifTrue: [^ client
> methodReturnConstant: (SpecialConstants at: offset - 8)].
> offset = 12
> ifTrue: [^ client methodReturnTop].
> offset = 13
> ifTrue: [^ client blockReturnTop].
> offset > 13
> ifTrue: [^ self unusedBytecode: client at: pc - 1 ]]]]]
> ifFalse: [type < 12
> ifTrue: [type < 10
> ifTrue: [type < 9
> ifTrue: ["type = 8"
> ^ self
> interpretV3PlusClosureExtension: offset
> in: method
> for: client]
> ifFalse: ["type = 9 (short jumps)"
> offset < 8
> ifTrue: [^ client jump: offset + 1].
> ^ client jump: offset - 8 + 1 if: false]]
> ifFalse: [type < 11
> ifTrue: ["type = 10 (long jumps)"
> byte := method at: pc.
> pc := pc + 1.
> offset < 8
> ifTrue: [^ client jump: offset - 4 * 256 + byte].
> ^ client jump: (offset bitAnd: 3)
> * 256 + byte if: offset < 12]
> ifFalse: ["type = 11"
> ^ client
> send: (Smalltalk specialSelectorAt: offset + 1)
> super: false
> numArgs: (Smalltalk specialNargsAt: offset + 1)]]]
> ifFalse: [type = 12
> ifTrue: [^ client
> send: (Smalltalk specialSelectorAt: offset + 17)
> super: false
> numArgs: (Smalltalk specialNargsAt: offset + 17)]
> ifFalse: ["type = 13, 14 or 15"
> ^ client
> send: (method literalAt: offset + 1)
> super: false
> numArgs: type - 13]]].
>
> "    old code
> type=0 ifTrue: [^client pushReceiverVariable: offset].
> type=1 ifTrue: [^client pushTemporaryVariable: offset].
> type=2 ifTrue: [^client pushConstant: (method literalAt: offset+1)].
> type=3 ifTrue: [^client pushConstant: (method literalAt: offset+17)].
> type=4 ifTrue: [^client pushLiteralVariable: (method literalAt: offset+1)].
> type=5 ifTrue: [^client pushLiteralVariable: (method literalAt:
> offset+17)].
> type=6
> ifTrue: [offset<8
> ifTrue: [^client popIntoReceiverVariable: offset]
> ifFalse: [^client popIntoTemporaryVariable: offset-8]].
> type=7
> ifTrue: [offset=0 ifTrue: [^client pushReceiver].
> offset<8 ifTrue: [^client pushConstant: (SpecialConstants at: offset)].
> offset=8 ifTrue: [^client methodReturnReceiver].
> offset<12 ifTrue: [^client methodReturnConstant:
> (SpecialConstants at: offset-8)].
> offset=12 ifTrue: [^client methodReturnTop].
> offset=13 ifTrue: [^client blockReturnTop].
> offset>13 ifTrue: [^self error: 'unusedBytecode']].
> type=8 ifTrue: [^self interpretExtension: offset in: method for: client].
> type=9
> ifTrue:  short jumps
> [offset<8 ifTrue: [^client jump: offset+1].
> ^client jump: offset-8+1 if: false].
> type=10
> ifTrue:  long jumps
> [byte:= method at: pc.  pc:= pc+1.
> offset<8 ifTrue: [^client jump: offset-4*256 + byte].
> ^client jump: (offset bitAnd: 3)*256 + byte if: offset<12].
> type=11
> ifTrue:
> [^client
> send: (Smalltalk specialSelectorAt: offset+1)
> super: false
> numArgs: (Smalltalk specialNargsAt: offset+1)].
> type=12
> ifTrue:
> [^client
> send: (Smalltalk specialSelectorAt: offset+17)
> super: false
> numArgs: (Smalltalk specialNargsAt: offset+17)].
> type>12
> ifTrue:
> [^client send: (method literalAt: offset+1)
> super: false
> numArgs: type-13]"

Reply via email to