Ghost

Preview:

DESCRIPTION

ESUG 2011, Edinburgh

Citation preview

RMod

1

Mariano Martinez Peckmarianopeck@gmail.com

http://marianopeck.wordpress.com/

Monday, August 22, 2011

What is a proxy?

2

A proxy object is a surrogate or placeholder that controls access to

another target object.

Monday, August 22, 2011

Glossary

Target: object to proxify.

Client: user of the proxy.

Interceptor: object that intercepts message sending.

Handler: object that performs a desired action as a consequence of an interception.

3

Monday, August 22, 2011

Forwarder and Logging example

4

Monday, August 22, 2011

With or without Object replacement?

In proxies with object replacement (#become:), the target object is replaced by a proxy.

Proxies without object replacement are a kind of factory.

5

Monday, August 22, 2011

With or without Object replacement?

In proxies with object replacement (#become:), the target object is replaced by a proxy.

Proxies without object replacement are a kind of factory.

5

Monday, August 22, 2011

Traditional proxy implementations

6

Usage of a minimal object together with an implementation of a custom #doesNotUnderstand

doesNotUnderstand:executeBeforeHandlingexecuteAfterHandling

targetProxy

identityHashpointersTonextObject...

ProtoObject

Monday, August 22, 2011

7

We are going to play a little game...

Monday, August 22, 2011

8

Are both prints in Transcript the same or not?

Monday, August 22, 2011

8

Are both prints in Transcript the same or not?

Conclusion: methods understood are NOT intercepted.Is that bad?

Monday, August 22, 2011

8

Are both prints in Transcript the same or not?

Conclusion: methods understood are NOT intercepted.Is that bad?

Different execution paths Errors difficult to findMonday, August 22, 2011

9

Do we want the regular #doesNotUnderstand or to intercept the message?

Monday, August 22, 2011

10

Do we want the regular #doesNotUnderstand or to intercept the message?

Monday, August 22, 2011

11

I wanted the normal #doesNotUnderstand!!!

Monday, August 22, 2011

12

I wanted the normal #doesNotUnderstand!!!

Monday, August 22, 2011

Problems #doesNotUnderstand: cannot be trapped like a regular message.

Mix of handling procedure and proxy interception.

Only methods that are not understood are intercepted.

No separation between proxies and handlers

13

This approach is not stratified

Monday, August 22, 2011

14

Subclassing from nil does not solve the problem.

Monday, August 22, 2011

15

VM CRASH

This solution is not uniform

Monday, August 22, 2011

16

A Uniform, Light-weight and Stratified Proxy Model and Implementation.

Monday, August 22, 2011

Used hooks

Object replacement (#become:)

Change an object’s class (#adoptInstance:)

Objects as methods (#run:with:in:)

Classes with no method dictionary (#cannotInterpret:)

17

Monday, August 22, 2011

Object replacement

18

AB

CD

AB

CD

c become: d

Monday, August 22, 2011

Objects as methods

19

The VM sends #run: aSelector with: anArray in: aReceiver

Monday, August 22, 2011

Objects as methods

19

The VM sends #run: aSelector with: anArray in: aReceiver

So.....We can implement in Proxy:

Monday, August 22, 2011

CLasses with no method dictionary

20

aProxy

aProxy username

1: #username send

methodDict := nilProxyTrap

cannotInterpret: aMessageProxy

Object

2: #aProxy lookup

3: Since the method dictionary was nil, the VM sends #cannotInterpret to

the receiver but starting the lookup in the superclass

4: #cannotInterpret: lookup

Referencesinstance ofmessage sendlookupsubclass

Monday, August 22, 2011

Ghost model

21

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

handleInterception: anInterceptionProxyHandler

handleInterception: anInterceptionSimpleForwarderHandler

messageproxyproxyState

Interception

Monday, August 22, 2011

How it works?

22

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

Monday, August 22, 2011

How it works?

22

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

Proxy class >>

Monday, August 22, 2011

How it works?

22

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

aProxy

‘Mariano’aHandler

instanceOf

Proxy class >>

Monday, August 22, 2011

How it works?

22

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

aProxy

‘Mariano’aHandler

instanceOf

Proxy class >>

ProxyTrap class >>

Monday, August 22, 2011

How it works?

22

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

aProxy

‘Mariano’aHandler

instanceOf

Proxy class >>

ProxyTrap class >>

Monday, August 22, 2011

How it works?

22

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

aProxy

‘Mariano’aHandler

instanceOf

Proxy class >>

Monday, August 22, 2011

aProxy

aProxy username

1: #username send

methodDict := nilProxyTrap

cannotInterpret: aMessageProxy

Object

2: #aProxy lookup

3: Since the method dictionary was nil, the VM sends #cannotInterpret to

the receiver but starting the lookup in the superclass

4: #cannotInterpret: lookup

Referencesinstance ofmessage sendlookupsubclass

How it works?

23

Monday, August 22, 2011

aProxy

aProxy username

1: #username send

methodDict := nilProxyTrap

cannotInterpret: aMessageProxy

Object

2: #aProxy lookup

3: Since the method dictionary was nil, the VM sends #cannotInterpret to

the receiver but starting the lookup in the superclass

4: #cannotInterpret: lookup

Referencesinstance ofmessage sendlookupsubclass

How it works?

23

Monday, August 22, 2011

aProxy

aProxy username

1: #username send

methodDict := nilProxyTrap

cannotInterpret: aMessageProxy

Object

2: #aProxy lookup

3: Since the method dictionary was nil, the VM sends #cannotInterpret to

the receiver but starting the lookup in the superclass

4: #cannotInterpret: lookup

Referencesinstance ofmessage sendlookupsubclass

How it works?

23

Monday, August 22, 2011

aProxy

aProxy username

1: #username send

methodDict := nilProxyTrap

cannotInterpret: aMessageProxy

Object

2: #aProxy lookup

3: Since the method dictionary was nil, the VM sends #cannotInterpret to

the receiver but starting the lookup in the superclass

4: #cannotInterpret: lookup

Referencesinstance ofmessage sendlookupsubclass

How it works?

23

Monday, August 22, 2011

aProxy

aProxy username

1: #username send

methodDict := nilProxyTrap

cannotInterpret: aMessageProxy

Object

2: #aProxy lookup

3: Since the method dictionary was nil, the VM sends #cannotInterpret to

the receiver but starting the lookup in the superclass

4: #cannotInterpret: lookup

Referencesinstance ofmessage sendlookupsubclass

How it works?

23

Monday, August 22, 2011

aProxy

aProxy username

1: #username send

methodDict := nilProxyTrap

cannotInterpret: aMessageProxy

Object

2: #aProxy lookup

3: Since the method dictionary was nil, the VM sends #cannotInterpret to

the receiver but starting the lookup in the superclass

4: #cannotInterpret: lookup

Referencesinstance ofmessage sendlookupsubclass

How it works?

23

Proxy >>

Monday, August 22, 2011

aProxy

aProxy username

1: #username send

methodDict := nilProxyTrap

cannotInterpret: aMessageProxy

Object

2: #aProxy lookup

3: Since the method dictionary was nil, the VM sends #cannotInterpret to

the receiver but starting the lookup in the superclass

4: #cannotInterpret: lookup

Referencesinstance ofmessage sendlookupsubclass

How it works?

23

Proxy >>

SimpleForwarderHandler >>

Monday, August 22, 2011

24

Traditional Ghost

#doesNotUnderstand: cannot be trapped like a regular message.

#cannotInterpret: is trapped like a regular message.

Mix of handling procedure and proxy interception.

No mix of handling procedure and proxy interception.

Only methods that are not understood are intercepted.

“All” methods are intercepted.

No separation between proxies and handlers.

Clear separation between proxies and handlers.

Monday, August 22, 2011

25

is stratified

Monday, August 22, 2011

Methods not intercepted

26

1) Optimizations done by the Compiler

2) Special shortcut bytecodes between Compiler and VM

2.1) Methods NEVER sent: #== and #class2.2) Methods that may or may not be executed depending

on the receiver and arguments: e.g. in ‘1+1’ #+ is not executed. But with ‘1+$C’ #+ is executed.

2.3)Always executed, they are just little optimizations. Examples #new, #next, #nextPut:, #size, etc.

Monday, August 22, 2011

Methods not intercepted

26

1) Optimizations done by the Compiler

2) Special shortcut bytecodes between Compiler and VM

2.1) Methods NEVER sent: #== and #class2.2) Methods that may or may not be executed depending

on the receiver and arguments: e.g. in ‘1+1’ #+ is not executed. But with ‘1+$C’ #+ is executed.

2.3)Always executed, they are just little optimizations. Examples #new, #next, #nextPut:, #size, etc.

Monday, August 22, 2011

Methods not intercepted

26

1) Optimizations done by the Compiler

2) Special shortcut bytecodes between Compiler and VM

2.1) Methods NEVER sent: #== and #class2.2) Methods that may or may not be executed depending

on the receiver and arguments: e.g. in ‘1+1’ #+ is not executed. But with ‘1+$C’ #+ is executed.

2.3)Always executed, they are just little optimizations. Examples #new, #next, #nextPut:, #size, etc.

Monday, August 22, 2011

Proxy for classes

27

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

cannotInterpret:proxyFor:

superclass methodDictformathandlertarget

ClassProxy

initializenilMethodDict

ClassProxyTrap

logIn:validate:

usernameage

User

Monday, August 22, 2011

Proxy for classes

27

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

cannotInterpret:proxyFor:

superclass methodDictformathandlertarget

ClassProxy

initializenilMethodDict

ClassProxyTrap

logIn:validate:

usernameage

User

Monday, August 22, 2011

Proxy for classes

27

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

cannotInterpret:proxyFor:

superclass methodDictformathandlertarget

ClassProxy

initializenilMethodDict

ClassProxyTrap

logIn:validate:

usernameage

User

Monday, August 22, 2011

Proxy for classes

27

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

cannotInterpret:proxyFor:

superclass methodDictformathandlertarget

ClassProxy

initializenilMethodDict

ClassProxyTrap

logIn:validate:

usernameage

User

Monday, August 22, 2011

Proxy for classes

27

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

cannotInterpret:proxyFor:

superclass methodDictformathandlertarget

ClassProxy

initializenilMethodDict

ClassProxyTrap

aUseraClassProxy

methodDict = nilsuperclass = ClassProxy

logIn:validate:

usernameage

User

instance of

Monday, August 22, 2011

Proxy for classes

27

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

cannotInterpret:proxyFor:

superclass methodDictformathandlertarget

ClassProxy

initializenilMethodDict

ClassProxyTrap

aUseraClassProxy

methodDict = nilsuperclass = ClassProxy

logIn:validate:

usernameage

User

instance of

User nameMonday, August 22, 2011

Proxy for classes

27

cannotInterpret:proxyFor:

handlertarget

Proxy

initializenilMethodDict

ProxyTrap

Object

cannotInterpret:proxyFor:

superclass methodDictformathandlertarget

ClassProxy

initializenilMethodDict

ClassProxyTrap

aUseraClassProxy

methodDict = nilsuperclass = ClassProxy

logIn:validate:

usernameage

User

instance of

aUser username

User nameMonday, August 22, 2011

Proxy for methods

28

Monday, August 22, 2011

Proxy for methods

28

Regular message

Monday, August 22, 2011

Proxy for methods

28

Regular messageMethod execution

Monday, August 22, 2011

Proxy for methods

28

Just handling #run:with:in correctly is enough to also intercept method execution.

Regular messageMethod execution

Monday, August 22, 2011

is

29

Uniform

Monday, August 22, 2011

is

29

moreUniform

Monday, August 22, 2011

More features

Low memory footprint.

Compact classes.

Store the minimal needed state.

Easy debugging.

Custom list of messages.

30

Monday, August 22, 2011

Conclusion

31

With a little bit of special support from the VM (#cannotInterpret hook), we can have an image-side proxy solution

much better than the classic #doesNotUnderstand:

Monday, August 22, 2011

Future work

Experiment with immediate proxies (memory address tag) in VM side.

Think how to correctly intercept non-executed methods.

32

Monday, August 22, 2011

Mariano Martinez Peckmarianopeck@gmail.com

http://marianopeck.wordpress.com/

RMod

A Uniform, Light-weight and Stratified Proxy Model and Implementation

Monday, August 22, 2011