SlideShare a Scribd company logo
1 of 47
Download to read offline
Working with
 Bytecodes:

IRBuilder and
 ByteSurgeon

Marcus Denker
Reasons for working with Bytecode


 •   Generating Bytecode
     – Implementing compilers for other languages
     – Experimentation with new language features


 •   Bytecode Transformation
     – Adaptation of running Systems
     – Tracing / Debugging
     – New language features




Marcus Denker
Overview

 1. Introduction to Squeak Bytecodes
 2. Generating Bytecode with IRBuilder
 3. Introduction to ByteSurgeon




Marcus Denker
The Squeak Virtual Machine

 •   From last lecture:
     – Virtual machine provides a virtual processor
     – Bytecode: The ‘machine-code’ of the virtual machine
     – Smalltalk (like Java): Stack machine

 •   Today:
     – Closer look at Squeak bytecode




Marcus Denker
Bytecode in the CompiledMethod

 •   CompiledMethods format:

                                        (Number>>#asInteger)inspect
        Header     Number of
                   temps, literals...

                   Array of all
        Literals   Literal Objects




      Bytecode

                   Pointer to
        Trailer    Source




Marcus Denker
Example: Number>>asInteger

 •   Smalltalk code:
      Number>>asInteger
      	

 "Answer an Integer nearest the receiver toward zero."

      	

 ^self truncated


 •   Symbolic Bytecode
      9 <70> self
      10 <D0> send: truncated
      11 <7C> returnTop




Marcus Denker
Example: Step by Step

 •   9 <70> self
     – The receiver (self) is pushed on the stack
 •   10 <D0> send: truncated
     – Bytecode 208: send literal selector 1
     – Get the selector from the first literal
     – start message lookup in the class of the object
       that is top of the stack
     – result is pushed on the stack
 •   11 <7C> returnTop
     – return the object on top of the stack to the
       calling method

Marcus Denker
Squeak Bytecodes

 •   256 Bytecodes, four groups:

     – Stack Bytecodes
         • Stack manipulation: push / pop / dup

     – Send Bytecodes
         • Invoke Methods

     – Return Bytecodes
         • Return to caller

     – Jump Bytecodes
         • Control flow inside a method


Marcus Denker
Stack Bytecodes

 •   Push values on the stack, e.g., temps, instVars, literals
     – e.g: 16 - 31: push instance variable
 •   Push Constants (False/True/Nil/1/0/2/-1)
 •   Push self, thisContext
 •   Duplicate top of stack
 •   Pop




Marcus Denker
Sends and Returns

 •   Sends: receiver is on top of stack
     – Normal send
     – Super Sends
     – Hard-coded sends for efficiency, e.g. +, -

 •   Returns
      – Return top of stack to the sender
      – Return from a block
      – Special bytecodes for return self, nil, true, false
        (for efficiency)



Marcus Denker
Jump Bytecodes

 •   Control Flow inside one method
 •   Used to implement control-flow efficiently
 •   Example:
                    	

 ^ 1<2 ifTrue: ['true']



                9 <76> pushConstant: 1
                10 <77> pushConstant: 2
                11 <B2> send: <
                12 <99> jumpFalse: 15
                13 <20> pushConstant: 'true'
                14 <90> jumpTo: 16
                15 <73> pushConstant: nil
                16 <7C> returnTop


Marcus Denker
What you should have learned...

•   ... dealing with bytecodes directly is possible, but
    very boring.
•   We want reusable abstractions that hide the details
    (e.g. the different send bytecodes)


•   We would like to have frameworks for
    – Generating bytecode easily
    – Transforming bytecode
Generating Bytecodes


 •   IRBuilder: A tool for generating bytecode
 •   Part of the new compiler for Squeak 3.9

 •   Idea: a symbolic Assembler for Squeak




Marcus Denker
IRBuilder: Simple Example

 •   Number>>asInteger
     
     iRMethod := IRBuilder new
     	

   	

 numRargs: 1;
     	

   	

 addTemps: #(self); "receiver"
     	

   	

 pushTemp: #self;	

     	

   	

 send: #truncated;
     	

   	

 returnTop;
     	

   	

 ir.

     	

 aCompiledMethod := iRMethod compiledMethod.

     	

 aCompiledMethod valueWithReceiver:3.5
     	

 	

 	

 	

 	

 	

 	

 arguments: #()




Marcus Denker
IRBuilder: Step by Step

 •   Number>>asInteger
     
   iRMethod := IRBuilder new
     	

 	

     – Make a instance of IRBuilder




Marcus Denker
IRBuilder: Step by Step

 •   Number>>asInteger
     
   iRMethod := IRBuilder new
     	

 	

 numRargs: 1;
     	

 	


     – Define arguments. Note: “self” is default argument




Marcus Denker
IRBuilder: Step by Step

 •   Number>>asInteger
     
   iRMethod := IRBuilder new
     	

 	

 numRargs: 1;
     	

 	

 addTemps: #(self); "receiver"
     	

 	

     – define temporary variables. Note: arguments are temps




Marcus Denker
IRBuilder: Step by Step

 •   Number>>asInteger
     
   iRMethod := IRBuilder new
     	

 	

 numRargs: 1;
     	

 	

 addTemps: #(self); "receiver"
     	

 	

 pushTemp: #self

     – push “self” on the stack




Marcus Denker
IRBuilder: Step by Step

 •   Number>>asInteger
     
      iRMethod := IRBuilder new
     	

    	

 numRargs: 1;
     	

    	

 addTemps: #(self); "receiver"
                pushTemp: #self
     	

    	

 send: #truncated;
      –
     	

   call method truncated on “self”
            	





Marcus Denker
IRBuilder: Step by Step

 •   Number>>asInteger
     
     iRMethod := IRBuilder new
     	

   	

 numRargs: 1;
     	

   	

 addTemps: #(self); "receiver"
               pushTemp: #self
     	

   	

 send: #truncated;
     	

   	

 returnTop;
     	


     – return Top of Stack




Marcus Denker
IRBuilder: Step by Step

 •   Number>>asInteger
     
     iRMethod := IRBuilder new
     	

   	

 numRargs: 1;
     	

   	

 addTemps: #(self); "receiver"
     	

   	

 pushTemp: #self
     	

   	

 send: #truncated;
     	

   	

 returnTop;
     	

   	

 ir.

     – tell IRBuilder to generate Intermediate Representation
       (IR)




Marcus Denker
IRBuilder: Step by Step

 •   Number>>asInteger
     
     iRMethod := IRBuilder new
     	

   	

 numRargs: 1;
     	

   	

 addTemps: #(self); "receiver"
               pushTemp: #self
     	

   	

 send: #truncated;
     	

   	

 returnTop;
     	

   	

 ir.

     	

 aCompiledMethod := iRMethod compiledMethod.

     – Generate method from IR




Marcus Denker
IRBuilder: Step by Step

 •   Number>>asInteger
     
     iRMethod := IRBuilder new
     	

   	

 numRargs: 1;
     	

   	

 addTemps: #(self); "receiver"
     	

   	

 pushTemp: #self
     	

   	

 send: #truncated;
     	

   	

 returnTop;
     	

   	

 ir.

     	

 aCompiledMethod := iRMethod compiledMethod.

     	

 aCompiledMethod valueWithReceiver:3.5
     	

 	

 	

 	

 	

 	

 	

 arguments: #()
     – Execute the method with reveiver 3.5 and no arguments.
     – “3.5 truncated”
Marcus Denker
IRBuilder: Stack Manipulation

 •   popTop - remove the top of stack
 •   pushDup - push top of stack on the stack
 •   pushLiteral:
 •   pushReceiver - push self
 •   pushThisContext




Marcus Denker
IRBuilder: Symbolic Jumps

 •   Jump targets are resolved:
 •   Example: false ifTrue: [’true’] ifFalse: [’false’]
 iRMethod := IRBuilder new
 	

 numRargs: 1;
 	

 addTemps: #(self); "receiver"
 	

 pushLiteral: false;
 	

 jumpAheadTo: #false if: false;
 	

 pushLiteral: 'true';	

	

 	

 	

 "ifTrue: ['true']"
 	

 jumpAheadTo: #end;
 	

 jumpAheadTarget: #false;
 	

 pushLiteral: 'false';	

 	

 	

 "ifFalse: ['false']"
 	

 jumpAheadTarget: #end;
 	

 returnTop;
 	

 ir.


Marcus Denker
IRBuiler: Instance Variables

 •   Access by offset
 •   Read: getField:
      – receiver on top of stack
 •   Write: setField:
      – receiver and value on stack
 •   Example: set the first instance variable to 2
     iRMethod := IRBuilder new
     	

 	

 numRargs: 1;
     	

 	

 addTemps: #(self); "receiver"
     	

 	

 pushLiteral: 2;
     	

 	

 pushTemp: #self;
     	

 	

 setField: 1;
     	

 	

 pushTemp: #self;
     	

 	

 returnTop;
     	

 	

 ir.
     	

 	

     	

 aCompiledMethod := iRMethod compiledMethod.
     	

 aCompiledMethod valueWithReceiver: 1@2 arguments: #()
Marcus Denker
IRBuilder: Temporary Variables

 •   Accessed by name
 •   Define with addTemp: / addTemps:
 •   Read with pushTemp:
 •   Write with storeTemp:
 •   Examle: set variables a and b, return value of a
     iRMethod := IRBuilder new
     	

 	

 numRargs: 1;
     	

 	

 addTemps: #(self); "receiver"
     	

 	

 addTemps: #(a b);
     	

 	

 pushLiteral: 1;	

     	

 	

 storeTemp: #a;
     	

 	

 pushLiteral: 2;	

     	

 	

 storeTemp: #b;
     	

 	

 pushTemp: #a;
     	

 	

 returnTop;
     	

 	

 ir.

Marcus Denker
IRBuilder: Sends

 •   normal send
            builder pushLiteral: ‘hello’
            builder send: #size;


 •   super send
      ....
      builder send: #selector toSuperOf: aClass;

     – The second parameter specifies the class were the lookup
       starts.



Marcus Denker
IRBuilder: Lessons learned
•   IRBuilder: Easy bytecode generation
    –   Jumps
    –   Instance variable
    –   Temporary variables
    –   Sends

•   Next: Manipulating bytecode
ByteSurgeon

 •   Library for bytecode transformation in Smalltalk
 •   Full flexibility of Smalltalk Runtime
 •   Provides high-level API
 •   For Squeak, but portable


 •   Runtime transformation needed for
     •   Adaptation of running systems
     •   Tracing / debugging
     •   New language features (MOP, AOP)



Marcus Denker
Example: Logging

 •   Goal: logging message send.
 •   First way: Just edit the text:

example
	

 self test.
	

	



                 example
                 	

 Transcript show: ‘sending #test’.
                 	

 self test.




Marcus Denker
Logging with Bytesurgen

 •   Goal: Change the method without changing program
     text
 •   Example:

     (Example>>#example)instrumentSend: [:send |
     	

 send insertBefore:
     	

 	

 ‘Transcript show: ‘’sending #test’’ ‘.
     ]	





Marcus Denker
Logging: Step by Step

      (Example>>#example)instrumentSend: [:send |
      	

 send insertBefore:
      	

 	

 ‘Transcript show: ‘’sending #test’’ ‘.
      ]	



                        Example >> #example


                Class                           Name of Method



                   >>: - takes a name of a method
                   
 - returns the CompiledMethod object


Marcus Denker
Logging: Step by Step

        (Example>>#example)instrumentSend: [:send |
        	

 send insertBefore:
        	

 	

 ‘Transcript show: ‘’sending #test’’ ‘.
        ]	





 •   instrumentSend:
     – takes a block as an argument
     – evaluates it for all send bytecodes




Marcus Denker
Logging: Step by Step

        (Example>>#example)instrumentSend: [:send |
        	

 send insertBefore:
        	

 	

 ‘Transcript show: ‘’sending #test’’ ‘.
        ]	



 •   The block has one parameter: send
 •   It is executed for each send bytecode in the method




Marcus Denker
Logging: Step by Step

        (Example>>#example)instrumentSend: [:send |
        	

 send insertBefore:
        	

 	

 ‘Transcript show: ‘’sending #test’’ ‘.
        ]	



 •   Objects describing bytecode understand how to
     insert code
     – insertBefor
     – insertAfter
     – replace




Marcus Denker
Logging: Step by Step

        (Example>>#example)instrumentSend: [:send |
        	

 send insertBefore:
        	

 	

 ‘Transcript show: ‘’sending #test’’ ‘.
        ]	



 •   The code to be inserted.
 •   Double quoting for string inside string
     –Transcript show: ’sending #test’




Marcus Denker
Inside ByteSurgeon

 •   Uses IRBuilder internally


                 Decompile        Compile



     Bytecode                IR             Bytecode



 •   Transformation (Code inlining) done on IR



Marcus Denker
ByteSurgeon Usage

 •   On Methods or Classes:
         MyClass instrument: [.... ].	

         (MyClass>>#myMethod) instrument: [.... ].


 •   Different instrument methods:
     –   instrument:
     –   instrumentSend:
     –   instrumentTempVarRead:
     –   instrumentTempVarStore:
     –   instrumentTempVarAccess:
     –   same for InstVar


Marcus Denker
ByteSurgeon: Lessons learned
•   ByteSurgeon: Tool for editing bytecode
    – Simple example
    – Based on IRBuilder


•   Next: Advanced ByteSurgeon
Advanced ByteSurgeon:

 •   Goal: extend a send with after logging


example
	

 self test.
	

	



                 example
                 	

 	

 self test.
                 	

 	

 Logger logSendTo: self.




Marcus Denker
Advanced ByteSurgeon

 •   With Bytesurgeon, something like:


        (Example>>#example)instrumentSend: [:send |
        	

 send insertAfter:
        	

 	

 ‘Logger logSendTo: ?’ .
        ]	




 •   How can we access the receiver of the send?
 •   Solution: Metavariable


Marcus Denker
Advanced ByteSurgeon

 •   With Bytesurgeon, something like:


        (Example>>#example)instrumentSend: [:send |
        	

 send insertAfter:
        	

 	

 ‘Logger logSendTo: <meta: #receiver>’ .
        ]	




 •   How can we access the receiver of the send?
 •   Solution: Metavariable


Marcus Denker
Implementation Metavariables

 •   Stack during send:

           receiver

           arg1

           arg2                        result



                before                     after


 •   Problem 1: After send, receiver is not available
 •   Problem II: Before send, receiver is deep in the stack

Marcus Denker
Metavariables: Implementation


 •   Solution: ByteSurgeon generates preamble

     –   Pop the arguments into temps
     –   Pop the receiver into temps
     –   Rebuild the stack
     –   Do the send
     –   Now we can acces the receiver even after the send




Marcus Denker
Metavariables: Implementation



         25 <70> self
         26 <81 40> storeIntoTemp: 0   Preamble
         28 <D0> send: test
         29 <41> pushLit: Transcript
         30 <10> pushTemp: 0
                                       Inlined Code
         31 <E2> send: show:
         32 <87> pop
         33 <87> pop
         34 <78> returnSelf



Marcus Denker
End


•   Short overview of Squeak bytecode
•   Introduction to bytecode generation with IRBuilder
•   Manipulating bytecode with ByteSurgeon


•   Questions?

More Related Content

What's hot

Grand Central Dispatch
Grand Central DispatchGrand Central Dispatch
Grand Central Dispatch
cqtt191
 
Other Approaches (Concurrency)
Other Approaches (Concurrency)Other Approaches (Concurrency)
Other Approaches (Concurrency)
Sri Prasanna
 
2008 07-24 kwpm-threads_and_synchronization
2008 07-24 kwpm-threads_and_synchronization2008 07-24 kwpm-threads_and_synchronization
2008 07-24 kwpm-threads_and_synchronization
fangjiafu
 

What's hot (20)

EKON 25 Python4Delphi_mX4
EKON 25 Python4Delphi_mX4EKON 25 Python4Delphi_mX4
EKON 25 Python4Delphi_mX4
 
Grand Central Dispatch
Grand Central DispatchGrand Central Dispatch
Grand Central Dispatch
 
WTF is Twisted?
WTF is Twisted?WTF is Twisted?
WTF is Twisted?
 
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
 
Java Performance Tuning
Java Performance TuningJava Performance Tuning
Java Performance Tuning
 
Twisted: a quick introduction
Twisted: a quick introductionTwisted: a quick introduction
Twisted: a quick introduction
 
Node.js System: The Approach
Node.js System: The ApproachNode.js System: The Approach
Node.js System: The Approach
 
Dennis Benkert & Matthias Lübken - Patterns in a containerized world? - code....
Dennis Benkert & Matthias Lübken - Patterns in a containerized world? - code....Dennis Benkert & Matthias Lübken - Patterns in a containerized world? - code....
Dennis Benkert & Matthias Lübken - Patterns in a containerized world? - code....
 
Runtime
RuntimeRuntime
Runtime
 
NodeJS: an Introduction
NodeJS: an IntroductionNodeJS: an Introduction
NodeJS: an Introduction
 
8 - OOP - Syntax & Messages
8 - OOP - Syntax & Messages8 - OOP - Syntax & Messages
8 - OOP - Syntax & Messages
 
Ekon 25 Python4Delphi_MX475
Ekon 25 Python4Delphi_MX475Ekon 25 Python4Delphi_MX475
Ekon 25 Python4Delphi_MX475
 
Cp7 rpc
Cp7 rpcCp7 rpc
Cp7 rpc
 
What Makes Objective C Dynamic?
What Makes Objective C Dynamic?What Makes Objective C Dynamic?
What Makes Objective C Dynamic?
 
Asynchronous Python with Twisted
Asynchronous Python with TwistedAsynchronous Python with Twisted
Asynchronous Python with Twisted
 
Other Approaches (Concurrency)
Other Approaches (Concurrency)Other Approaches (Concurrency)
Other Approaches (Concurrency)
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
Network programming in java - PPT
Network programming in java - PPTNetwork programming in java - PPT
Network programming in java - PPT
 
Patterns for JVM languages JokerConf
Patterns for JVM languages JokerConfPatterns for JVM languages JokerConf
Patterns for JVM languages JokerConf
 
2008 07-24 kwpm-threads_and_synchronization
2008 07-24 kwpm-threads_and_synchronization2008 07-24 kwpm-threads_and_synchronization
2008 07-24 kwpm-threads_and_synchronization
 

Similar to RBuilder and ByteSurgeon

Automated Slow Query Analysis: Dex the Index Robot
Automated Slow Query Analysis: Dex the Index RobotAutomated Slow Query Analysis: Dex the Index Robot
Automated Slow Query Analysis: Dex the Index Robot
MongoDB
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
Kerry Buckley
 

Similar to RBuilder and ByteSurgeon (20)

VMs, Interpreters, JIT
VMs, Interpreters, JITVMs, Interpreters, JIT
VMs, Interpreters, JIT
 
Working with Bytecode
Working with BytecodeWorking with Bytecode
Working with Bytecode
 
Refactoring
RefactoringRefactoring
Refactoring
 
C++ basic.ppt
C++ basic.pptC++ basic.ppt
C++ basic.ppt
 
Constant Blocks in Pharo11
Constant Blocks in Pharo11 Constant Blocks in Pharo11
Constant Blocks in Pharo11
 
ConstantBlocks in Pharo11
ConstantBlocks in Pharo11ConstantBlocks in Pharo11
ConstantBlocks in Pharo11
 
Runtime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for SmalltalkRuntime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for Smalltalk
 
Lecture: MetaLinks
Lecture: MetaLinksLecture: MetaLinks
Lecture: MetaLinks
 
Lecture: "Advanced Reflection: MetaLinks"
Lecture: "Advanced Reflection: MetaLinks"Lecture: "Advanced Reflection: MetaLinks"
Lecture: "Advanced Reflection: MetaLinks"
 
Lecture. Advanced Reflection: MetaLinks
Lecture. Advanced Reflection: MetaLinksLecture. Advanced Reflection: MetaLinks
Lecture. Advanced Reflection: MetaLinks
 
Runtime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for SmalltalkRuntime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for Smalltalk
 
Begin with c++ Fekra Course #1
Begin with c++ Fekra Course #1Begin with c++ Fekra Course #1
Begin with c++ Fekra Course #1
 
C# 101: Intro to Programming with C#
C# 101: Intro to Programming with C#C# 101: Intro to Programming with C#
C# 101: Intro to Programming with C#
 
2 BytesC++ course_2014_c1_basicsc++
2 BytesC++ course_2014_c1_basicsc++2 BytesC++ course_2014_c1_basicsc++
2 BytesC++ course_2014_c1_basicsc++
 
Automated Slow Query Analysis: Dex the Index Robot
Automated Slow Query Analysis: Dex the Index RobotAutomated Slow Query Analysis: Dex the Index Robot
Automated Slow Query Analysis: Dex the Index Robot
 
Introduction to C ++.pptx
Introduction to C ++.pptxIntroduction to C ++.pptx
Introduction to C ++.pptx
 
VUB Brussels Lecture 2019: Advanced Reflection: MetaLinks
VUB Brussels Lecture 2019: Advanced Reflection: MetaLinksVUB Brussels Lecture 2019: Advanced Reflection: MetaLinks
VUB Brussels Lecture 2019: Advanced Reflection: MetaLinks
 
Sista: Improving Cog’s JIT performance
Sista: Improving Cog’s JIT performanceSista: Improving Cog’s JIT performance
Sista: Improving Cog’s JIT performance
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
 
JVM Memory Model - Yoav Abrahami, Wix
JVM Memory Model - Yoav Abrahami, WixJVM Memory Model - Yoav Abrahami, Wix
JVM Memory Model - Yoav Abrahami, Wix
 

More from Marcus Denker

More from Marcus Denker (20)

Soil And Pharo
Soil And PharoSoil And Pharo
Soil And Pharo
 
Demo: Improved DoIt
Demo: Improved DoItDemo: Improved DoIt
Demo: Improved DoIt
 
First Class Variables as AST Annotations
First Class Variables as AST AnnotationsFirst Class Variables as AST Annotations
First Class Variables as AST Annotations
 
Supporting Pharo / Getting Pharo Support
Supporting Pharo / Getting Pharo SupportSupporting Pharo / Getting Pharo Support
Supporting Pharo / Getting Pharo Support
 
thisContext in the Debugger
thisContext in the DebuggerthisContext in the Debugger
thisContext in the Debugger
 
Variables in Pharo
Variables in PharoVariables in Pharo
Variables in Pharo
 
Improving code completion for Pharo
Improving code completion for PharoImproving code completion for Pharo
Improving code completion for Pharo
 
Slot Composition
Slot CompositionSlot Composition
Slot Composition
 
Lecture: Advanced Reflection. MetaLinks
Lecture: Advanced Reflection. MetaLinksLecture: Advanced Reflection. MetaLinks
Lecture: Advanced Reflection. MetaLinks
 
PHARO IOT
PHARO IOTPHARO IOT
PHARO IOT
 
Open-Source: An Infinite Game
Open-Source: An Infinite GameOpen-Source: An Infinite Game
Open-Source: An Infinite Game
 
PharoTechTalk: Contributing to Pharo
PharoTechTalk: Contributing to PharoPharoTechTalk: Contributing to Pharo
PharoTechTalk: Contributing to Pharo
 
Feedback Loops in Practice
Feedback Loops in PracticeFeedback Loops in Practice
Feedback Loops in Practice
 
Pharo6 - ESUG17
Pharo6 - ESUG17Pharo6 - ESUG17
Pharo6 - ESUG17
 
Pharo6
Pharo6Pharo6
Pharo6
 
Reflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond SmalltakReflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond Smalltak
 
Reflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond SmalltakReflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond Smalltak
 
Perfection & Feedback Loops or: why worse is better
Perfection & Feedback Loops or: why worse is betterPerfection & Feedback Loops or: why worse is better
Perfection & Feedback Loops or: why worse is better
 
Dynamically Composing Collection Operations through Collection Promises
Dynamically Composing Collection Operations through Collection PromisesDynamically Composing Collection Operations through Collection Promises
Dynamically Composing Collection Operations through Collection Promises
 
Variables in Pharo5
Variables in Pharo5Variables in Pharo5
Variables in Pharo5
 

Recently uploaded

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Recently uploaded (20)

08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 

RBuilder and ByteSurgeon

  • 1. Working with Bytecodes: IRBuilder and ByteSurgeon Marcus Denker
  • 2. Reasons for working with Bytecode • Generating Bytecode – Implementing compilers for other languages – Experimentation with new language features • Bytecode Transformation – Adaptation of running Systems – Tracing / Debugging – New language features Marcus Denker
  • 3. Overview 1. Introduction to Squeak Bytecodes 2. Generating Bytecode with IRBuilder 3. Introduction to ByteSurgeon Marcus Denker
  • 4. The Squeak Virtual Machine • From last lecture: – Virtual machine provides a virtual processor – Bytecode: The ‘machine-code’ of the virtual machine – Smalltalk (like Java): Stack machine • Today: – Closer look at Squeak bytecode Marcus Denker
  • 5. Bytecode in the CompiledMethod • CompiledMethods format: (Number>>#asInteger)inspect Header Number of temps, literals... Array of all Literals Literal Objects Bytecode Pointer to Trailer Source Marcus Denker
  • 6. Example: Number>>asInteger • Smalltalk code: Number>>asInteger "Answer an Integer nearest the receiver toward zero." ^self truncated • Symbolic Bytecode 9 <70> self 10 <D0> send: truncated 11 <7C> returnTop Marcus Denker
  • 7. Example: Step by Step • 9 <70> self – The receiver (self) is pushed on the stack • 10 <D0> send: truncated – Bytecode 208: send literal selector 1 – Get the selector from the first literal – start message lookup in the class of the object that is top of the stack – result is pushed on the stack • 11 <7C> returnTop – return the object on top of the stack to the calling method Marcus Denker
  • 8. Squeak Bytecodes • 256 Bytecodes, four groups: – Stack Bytecodes • Stack manipulation: push / pop / dup – Send Bytecodes • Invoke Methods – Return Bytecodes • Return to caller – Jump Bytecodes • Control flow inside a method Marcus Denker
  • 9. Stack Bytecodes • Push values on the stack, e.g., temps, instVars, literals – e.g: 16 - 31: push instance variable • Push Constants (False/True/Nil/1/0/2/-1) • Push self, thisContext • Duplicate top of stack • Pop Marcus Denker
  • 10. Sends and Returns • Sends: receiver is on top of stack – Normal send – Super Sends – Hard-coded sends for efficiency, e.g. +, - • Returns – Return top of stack to the sender – Return from a block – Special bytecodes for return self, nil, true, false (for efficiency) Marcus Denker
  • 11. Jump Bytecodes • Control Flow inside one method • Used to implement control-flow efficiently • Example: ^ 1<2 ifTrue: ['true'] 9 <76> pushConstant: 1 10 <77> pushConstant: 2 11 <B2> send: < 12 <99> jumpFalse: 15 13 <20> pushConstant: 'true' 14 <90> jumpTo: 16 15 <73> pushConstant: nil 16 <7C> returnTop Marcus Denker
  • 12. What you should have learned... • ... dealing with bytecodes directly is possible, but very boring. • We want reusable abstractions that hide the details (e.g. the different send bytecodes) • We would like to have frameworks for – Generating bytecode easily – Transforming bytecode
  • 13. Generating Bytecodes • IRBuilder: A tool for generating bytecode • Part of the new compiler for Squeak 3.9 • Idea: a symbolic Assembler for Squeak Marcus Denker
  • 14. IRBuilder: Simple Example • Number>>asInteger iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" pushTemp: #self; send: #truncated; returnTop; ir. aCompiledMethod := iRMethod compiledMethod. aCompiledMethod valueWithReceiver:3.5 arguments: #() Marcus Denker
  • 15. IRBuilder: Step by Step • Number>>asInteger iRMethod := IRBuilder new – Make a instance of IRBuilder Marcus Denker
  • 16. IRBuilder: Step by Step • Number>>asInteger iRMethod := IRBuilder new numRargs: 1; – Define arguments. Note: “self” is default argument Marcus Denker
  • 17. IRBuilder: Step by Step • Number>>asInteger iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" – define temporary variables. Note: arguments are temps Marcus Denker
  • 18. IRBuilder: Step by Step • Number>>asInteger iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" pushTemp: #self – push “self” on the stack Marcus Denker
  • 19. IRBuilder: Step by Step • Number>>asInteger iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" pushTemp: #self send: #truncated; – call method truncated on “self” Marcus Denker
  • 20. IRBuilder: Step by Step • Number>>asInteger iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" pushTemp: #self send: #truncated; returnTop; – return Top of Stack Marcus Denker
  • 21. IRBuilder: Step by Step • Number>>asInteger iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" pushTemp: #self send: #truncated; returnTop; ir. – tell IRBuilder to generate Intermediate Representation (IR) Marcus Denker
  • 22. IRBuilder: Step by Step • Number>>asInteger iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" pushTemp: #self send: #truncated; returnTop; ir. aCompiledMethod := iRMethod compiledMethod. – Generate method from IR Marcus Denker
  • 23. IRBuilder: Step by Step • Number>>asInteger iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" pushTemp: #self send: #truncated; returnTop; ir. aCompiledMethod := iRMethod compiledMethod. aCompiledMethod valueWithReceiver:3.5 arguments: #() – Execute the method with reveiver 3.5 and no arguments. – “3.5 truncated” Marcus Denker
  • 24. IRBuilder: Stack Manipulation • popTop - remove the top of stack • pushDup - push top of stack on the stack • pushLiteral: • pushReceiver - push self • pushThisContext Marcus Denker
  • 25. IRBuilder: Symbolic Jumps • Jump targets are resolved: • Example: false ifTrue: [’true’] ifFalse: [’false’] iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" pushLiteral: false; jumpAheadTo: #false if: false; pushLiteral: 'true'; "ifTrue: ['true']" jumpAheadTo: #end; jumpAheadTarget: #false; pushLiteral: 'false'; "ifFalse: ['false']" jumpAheadTarget: #end; returnTop; ir. Marcus Denker
  • 26. IRBuiler: Instance Variables • Access by offset • Read: getField: – receiver on top of stack • Write: setField: – receiver and value on stack • Example: set the first instance variable to 2 iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" pushLiteral: 2; pushTemp: #self; setField: 1; pushTemp: #self; returnTop; ir. aCompiledMethod := iRMethod compiledMethod. aCompiledMethod valueWithReceiver: 1@2 arguments: #() Marcus Denker
  • 27. IRBuilder: Temporary Variables • Accessed by name • Define with addTemp: / addTemps: • Read with pushTemp: • Write with storeTemp: • Examle: set variables a and b, return value of a iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver" addTemps: #(a b); pushLiteral: 1; storeTemp: #a; pushLiteral: 2; storeTemp: #b; pushTemp: #a; returnTop; ir. Marcus Denker
  • 28. IRBuilder: Sends • normal send builder pushLiteral: ‘hello’ builder send: #size; • super send .... builder send: #selector toSuperOf: aClass; – The second parameter specifies the class were the lookup starts. Marcus Denker
  • 29. IRBuilder: Lessons learned • IRBuilder: Easy bytecode generation – Jumps – Instance variable – Temporary variables – Sends • Next: Manipulating bytecode
  • 30. ByteSurgeon • Library for bytecode transformation in Smalltalk • Full flexibility of Smalltalk Runtime • Provides high-level API • For Squeak, but portable • Runtime transformation needed for • Adaptation of running systems • Tracing / debugging • New language features (MOP, AOP) Marcus Denker
  • 31. Example: Logging • Goal: logging message send. • First way: Just edit the text: example self test. example Transcript show: ‘sending #test’. self test. Marcus Denker
  • 32. Logging with Bytesurgen • Goal: Change the method without changing program text • Example: (Example>>#example)instrumentSend: [:send | send insertBefore: ‘Transcript show: ‘’sending #test’’ ‘. ] Marcus Denker
  • 33. Logging: Step by Step (Example>>#example)instrumentSend: [:send | send insertBefore: ‘Transcript show: ‘’sending #test’’ ‘. ] Example >> #example Class Name of Method >>: - takes a name of a method - returns the CompiledMethod object Marcus Denker
  • 34. Logging: Step by Step (Example>>#example)instrumentSend: [:send | send insertBefore: ‘Transcript show: ‘’sending #test’’ ‘. ] • instrumentSend: – takes a block as an argument – evaluates it for all send bytecodes Marcus Denker
  • 35. Logging: Step by Step (Example>>#example)instrumentSend: [:send | send insertBefore: ‘Transcript show: ‘’sending #test’’ ‘. ] • The block has one parameter: send • It is executed for each send bytecode in the method Marcus Denker
  • 36. Logging: Step by Step (Example>>#example)instrumentSend: [:send | send insertBefore: ‘Transcript show: ‘’sending #test’’ ‘. ] • Objects describing bytecode understand how to insert code – insertBefor – insertAfter – replace Marcus Denker
  • 37. Logging: Step by Step (Example>>#example)instrumentSend: [:send | send insertBefore: ‘Transcript show: ‘’sending #test’’ ‘. ] • The code to be inserted. • Double quoting for string inside string –Transcript show: ’sending #test’ Marcus Denker
  • 38. Inside ByteSurgeon • Uses IRBuilder internally Decompile Compile Bytecode IR Bytecode • Transformation (Code inlining) done on IR Marcus Denker
  • 39. ByteSurgeon Usage • On Methods or Classes: MyClass instrument: [.... ]. (MyClass>>#myMethod) instrument: [.... ]. • Different instrument methods: – instrument: – instrumentSend: – instrumentTempVarRead: – instrumentTempVarStore: – instrumentTempVarAccess: – same for InstVar Marcus Denker
  • 40. ByteSurgeon: Lessons learned • ByteSurgeon: Tool for editing bytecode – Simple example – Based on IRBuilder • Next: Advanced ByteSurgeon
  • 41. Advanced ByteSurgeon: • Goal: extend a send with after logging example self test. example self test. Logger logSendTo: self. Marcus Denker
  • 42. Advanced ByteSurgeon • With Bytesurgeon, something like: (Example>>#example)instrumentSend: [:send | send insertAfter: ‘Logger logSendTo: ?’ . ] • How can we access the receiver of the send? • Solution: Metavariable Marcus Denker
  • 43. Advanced ByteSurgeon • With Bytesurgeon, something like: (Example>>#example)instrumentSend: [:send | send insertAfter: ‘Logger logSendTo: <meta: #receiver>’ . ] • How can we access the receiver of the send? • Solution: Metavariable Marcus Denker
  • 44. Implementation Metavariables • Stack during send: receiver arg1 arg2 result before after • Problem 1: After send, receiver is not available • Problem II: Before send, receiver is deep in the stack Marcus Denker
  • 45. Metavariables: Implementation • Solution: ByteSurgeon generates preamble – Pop the arguments into temps – Pop the receiver into temps – Rebuild the stack – Do the send – Now we can acces the receiver even after the send Marcus Denker
  • 46. Metavariables: Implementation 25 <70> self 26 <81 40> storeIntoTemp: 0 Preamble 28 <D0> send: test 29 <41> pushLit: Transcript 30 <10> pushTemp: 0 Inlined Code 31 <E2> send: show: 32 <87> pop 33 <87> pop 34 <78> returnSelf Marcus Denker
  • 47. End • Short overview of Squeak bytecode • Introduction to bytecode generation with IRBuilder • Manipulating bytecode with ByteSurgeon • Questions?