├── .gitignore ├── LICENSE ├── README.md ├── graal └── src │ └── main │ └── java │ └── Foo.java ├── javac ├── README.md └── src │ └── main │ └── java │ ├── CompileMyClass.java │ ├── ConstFold.java │ ├── Foo.java │ ├── HelloWorldProcessor.java │ └── Sugar.java ├── papers └── Inlining of Virtual Methods.pdf ├── python └── GDB.md └── v8 ├── Ignition Design Doc.pdf └── Ignition_ Register Equivalence Optimization.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Richard 宫文学 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Compilers In Practice 2 | 本项目是极客时间的[《编译原理实战课》](https://time.geekbang.org/column/intro/314)课程的示例代码。 3 | 4 | 课程Web网址:[https://time.geekbang.org/column/intro/314](https://time.geekbang.org/column/intro/314) 5 | 6 | ## 目录内容 7 | ### [javac](javac) 8 | Java编译器课程资料。 9 | 10 | -------------------------------------------------------------------------------- /graal/src/main/java/Foo.java: -------------------------------------------------------------------------------- 1 | public class Foo{ 2 | public static void main(String args[]){ 3 | 4 | Foo foo = new Foo(); 5 | 6 | int i = 0; 7 | while(true){ 8 | if(i%1000==0){ 9 | //System.out.println(i); 10 | try{ 11 | Thread.sleep(100); 12 | }catch(Exception e){} 13 | } 14 | 15 | i++; 16 | 17 | // add(i, i+1); 18 | add1(i, i+1); 19 | // addmemory(i, i, i, i, i, i, i, i+1); 20 | // addMemory(i); 21 | // foo.atLeastTen(i%20); 22 | // foo.add(i,i+1); 23 | // foo.add2(); 24 | // foo.doif2(i, i+1); 25 | // foo.constantFolding(i); 26 | // foo.strengthReduction(i, 10); 27 | // foo.negneg(i); 28 | // foo.gvn(i,3); 29 | // foo.inlining2(i); 30 | // foo.escapeTest(i%100); 31 | // foo.add3(i); 32 | // average(i, 10); 33 | // triple(i,5); 34 | } 35 | } 36 | 37 | int x = 3; 38 | int y = 4; 39 | final int z = 2; 40 | 41 | final public int getX(){ 42 | return x; 43 | } 44 | 45 | final public int getY(){ 46 | return y; 47 | } 48 | 49 | int getZ(){ 50 | return z + 1; 51 | } 52 | 53 | 54 | public static int add(int x, int y){ 55 | return x + y; 56 | } 57 | 58 | public static int add1(int x, int y){ 59 | return x + y + 10; 60 | } 61 | 62 | // public int addmemory(int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8){ 63 | // return x1*2; 64 | // } 65 | 66 | 67 | static int m = 3; 68 | public static int addMemory(int a){ 69 | return m + a; 70 | } 71 | 72 | public int addAll(int max){ 73 | int sum = 0; 74 | for (int i = 0; i< max; i++){ 75 | sum = add(sum, i); 76 | } 77 | return sum; 78 | } 79 | 80 | public int add2(){ 81 | return getX() + getY(); 82 | } 83 | 84 | public int doif(int x, int y){ 85 | if (x > 2){ 86 | return x+y; 87 | } 88 | else{ 89 | return x*y; 90 | } 91 | } 92 | 93 | public int doif2(int x, int y){ 94 | int z; 95 | if (x < 2) 96 | z=x+y; 97 | else 98 | z=x*y; 99 | return z; 100 | } 101 | 102 | public int add3(int a){ 103 | return getX() + doif(a, getY()); 104 | } 105 | 106 | public int doDouble(int a){ 107 | return 2*a; 108 | } 109 | 110 | public int[] strengthReduction(int a, int N){ 111 | int[] y = new int[N]; 112 | for (int i = 0; i < N; i++) 113 | { 114 | y[i] = a * i; 115 | } 116 | return y; 117 | } 118 | 119 | public int negneg(int a){ 120 | return -(-a); 121 | } 122 | 123 | public int gvn(int a, int b){ 124 | return (a+b) * (a+3); 125 | } 126 | 127 | public int inlining(int a){ 128 | return atLeastTen(3); 129 | } 130 | 131 | //至少返回10 132 | public int atLeastTen(int a){ 133 | if (a < 10) 134 | return 10; 135 | else 136 | return a; 137 | } 138 | 139 | public float average(float x, float y){ 140 | return (x + y)/2; 141 | } 142 | 143 | public int triple(int x, int y){ 144 | return (x + y)*3; 145 | } 146 | 147 | public int average2(int[] values) { 148 | int sum = 0; 149 | for (int n = 0; n < values.length; n++) { 150 | sum += values[n]; 151 | } 152 | return sum / values.length; 153 | } 154 | 155 | public int escapeTest(int age){ 156 | Person p = new Person(age); 157 | return p.ageSegment(); 158 | } 159 | 160 | public class Person{ 161 | private int age; 162 | private float weight; 163 | 164 | public Person(int age){ 165 | this.age = age; 166 | } 167 | 168 | final public int ageSegment(){ 169 | if (age < 20) 170 | return 1; 171 | else 172 | return 2; 173 | } 174 | 175 | public void setWeight(float weight){ 176 | this.weight = weight; 177 | } 178 | 179 | public float getWeidht(){ 180 | return weight; 181 | } 182 | } 183 | 184 | } -------------------------------------------------------------------------------- /javac/README.md: -------------------------------------------------------------------------------- 1 | #javac编译器 2 | 3 | ##如何调试java编译器对注解的处理过程 4 | 5 | 可以参照该链接[配置Idea](https://medium.com/@joachim.beckers/debugging-an-annotation-processor-using-intellij-idea-in-2018-cde72758b78a) 6 | 7 | -------------------------------------------------------------------------------- /javac/src/main/java/CompileMyClass.java: -------------------------------------------------------------------------------- 1 | import javax.tools.JavaCompiler; 2 | import javax.tools.ToolProvider; 3 | 4 | 5 | public class CompileMyClass { 6 | public static void main(String[] args) { 7 | System.out.println(System.getProperty("user.dir")); 8 | JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 9 | // int result = compiler.run(null, null, null, "/Users/richard/Unreachable.java"); 10 | // int result = compiler.run(null, null, null, "/Users/richard/MyClass3.java"); 11 | 12 | //把需要编译的java文件放到你的工作目录下。 13 | int result = compiler.run(null, null, null, "ByteCode.java"); 14 | 15 | // int result = compiler.run(null, null, null, "MyClass.java"); 16 | // int result = compiler.run(null, null, null, "RefResolve.java"); 17 | 18 | // int result = compiler.run(null, null, null, "ParamTypeInfer.java"); 19 | // int result = compiler.run(null, null, null, "ConstFold.java"); 20 | 21 | System.out.println("Compile result code = " + result); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /javac/src/main/java/ConstFold.java: -------------------------------------------------------------------------------- 1 | //测试ConstFold 2 | public class ConstFold { 3 | public String foo(){ 4 | final int a = 2; //int类型的常数 5 | final String b = "Hello "; //String类型的常数 6 | String c = b + a * 3; //发生两次折叠 7 | return c; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /javac/src/main/java/Foo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 测试HelloWold注解。 3 | * HelloFoo是在处理完注解以后才生成的。 4 | */ 5 | @HelloWorld 6 | public class Foo { 7 | static HelloFoo helloFoo = new HelloFoo(); 8 | public static void main(String args[]){ 9 | helloFoo.sayHello(); //HelloFoo类是处理完注解后才生成的。 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /javac/src/main/java/HelloWorldProcessor.java: -------------------------------------------------------------------------------- 1 | import javax.annotation.processing.AbstractProcessor; 2 | import javax.annotation.processing.RoundEnvironment; 3 | import javax.annotation.processing.SupportedAnnotationTypes; 4 | import javax.lang.model.SourceVersion; 5 | import javax.lang.model.element.Element; 6 | import javax.lang.model.element.TypeElement; 7 | import javax.tools.JavaFileObject; 8 | import java.io.IOException; 9 | import java.io.PrintWriter; 10 | import java.util.Set; 11 | 12 | @SupportedAnnotationTypes("HelloWorld") 13 | public class HelloWorldProcessor extends AbstractProcessor { 14 | @Override 15 | public boolean process(Set annotations, RoundEnvironment roundEnv) { 16 | for (TypeElement annotation : annotations){ 17 | Set annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); 18 | for (Element element : annotatedElements){ 19 | if (element instanceof TypeElement){ 20 | String className = ((TypeElement) element).getQualifiedName().toString(); 21 | try { 22 | generateClass(className); 23 | } 24 | catch (Exception e){ 25 | 26 | } 27 | 28 | } 29 | } 30 | } 31 | return true; 32 | } 33 | 34 | @Override 35 | public SourceVersion getSupportedSourceVersion() { 36 | return SourceVersion.latestSupported(); 37 | } 38 | 39 | 40 | private void generateClass(String className) throws IOException { 41 | String packageName = null; 42 | int lastDot = className.lastIndexOf('.'); 43 | if (lastDot > 0) { 44 | packageName = className.substring(0, lastDot); 45 | } 46 | 47 | String simpleClassName = className.substring(lastDot + 1); 48 | String helloSimpleClassName = "Hello" + simpleClassName; 49 | String helloClassName = (packageName == null)? helloSimpleClassName : packageName + helloSimpleClassName; 50 | 51 | JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(helloClassName); 52 | try (PrintWriter out = new PrintWriter(builderFile.openWriter())) { 53 | if (packageName != null) { 54 | out.print("package "); 55 | out.print(packageName); 56 | out.println(";"); 57 | out.println(); 58 | } 59 | 60 | out.print("public class "); 61 | out.print(helloClassName); 62 | out.println(" {"); 63 | out.println(); 64 | 65 | //main方法,打印出: 66 | //Hello 类名! 67 | out.println(" public static void sayHello(){"); 68 | out.print(" System.out.println(\"Hello "); 69 | out.print(simpleClassName); 70 | out.println("!\");"); 71 | out.println(" }"); 72 | 73 | out.println("}"); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /javac/src/main/java/Sugar.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Iterator; 3 | import java.util.List; 4 | 5 | public class Sugar { 6 | public static void main(String args[]) { 7 | List a = new ArrayList(); 8 | String b = new String(); 9 | List names = new ArrayList(); 10 | names.add("john"); 11 | names.add("richard"); 12 | names.add("rose"); 13 | 14 | for (String name:names) 15 | System.out.println(name); 16 | 17 | } 18 | } 19 | 20 | /* 21 | class Sugar1 { 22 | public static void main(String args[]) { 23 | List names = new ArrayList(); 24 | names.add("john"); 25 | names.add("richard"); 26 | names.add("rose"); 27 | 28 | String name; 29 | for (Iterator iterator = names.iterator(); iterator.hasNext(); System.out.println(name)) 30 | name = (String)iterator.next(); 31 | } 32 | } 33 | */ -------------------------------------------------------------------------------- /papers/Inlining of Virtual Methods.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RichardGong/CompilersInPractice/cf042d53973092eb71c4e184b742dd676f01da1d/papers/Inlining of Virtual Methods.pdf -------------------------------------------------------------------------------- /python/GDB.md: -------------------------------------------------------------------------------- 1 | # GDB的安装和配置 2 | 为了调试跟踪和运行Python,我们需要配置好一个环境。 3 | 4 | ## 选择操作系统 5 | 目前MacOS对GDB并不友好,在MacOS下使用GDB需要签名,并且还经常会遇到一些其他问题,比如找不到某些标准库的调试信息。 6 | 所以,建议选择一个Linux操作系统,CentOS或Ubuntu什么的都可以。我目前用的是一个CentOS系统。 7 | 你可以用VirtualBox安装一个Linux的虚拟机就行了。 8 | 9 | ## 安装GDB 10 | 在CentOS下,我用下面的命令一股脑装了所有与开发有关的工具包,其中就包含了GDB。 11 | >yum groupinstall "Development Tools" 12 | 13 | 因为我们还要编译Python,上述命令也安装了编译所需的工具链。 14 | 15 | 设置.gdbinit文件。该文件位于当前用户的主目录。内容为: 16 | >add-auto-load-safe-path /home/richard/Python-3.8.3 17 | >set auto-load safe-path / 18 | 19 | 其中的目录名,需要换成你自己的。这个配置文件会告诉GDB到哪里去加载Python扩展。 20 | 21 | ## 安装并编译Python 22 | 首先,下载Python3.8.3的源代码,下载链接是:https://github.com/python/cpython/tree/v3.8.3 23 | 24 | 下载后的代码放到用户主目录下,比如~/Python-3.8.3 25 | 26 | 27 | 第二步,运行: 28 | >./configure --with-pydebug 29 | 30 | 第三步,运行: 31 | >make -s -j2 32 | 33 | 其中j2是指用几个内核做编译。你根据虚拟机的内核数来修改这个参数。 34 | 35 | ## 用GDB调试Python 36 | 第一步,运行Python 37 | 打开一个终端(我通常是用ssh连接到Linux上),进入~/Python-3.8.3目录。 38 | 运行: 39 | > ./python 40 | 41 | 这样就进入了Python的REPL。 42 | 43 | 第二步,运行GDB,并attach到python进程上。 44 | 打开第二个终端,并输入: 45 | > gdb -p \`pidof python` 46 | 47 | 这个命令会找出python的进程id,并attach上去。你也可以用ps命令手工查找python的进程id。 48 | 49 | 50 | 第三步,在GDB里面调试python的运行 51 | 通常,你要先设置断点,然后再跟踪其执行。 52 | 至于GDB的命令,你可以搜索一下,网上有很多介绍文章。多用几遍就熟悉起来了。 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /v8/Ignition Design Doc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RichardGong/CompilersInPractice/cf042d53973092eb71c4e184b742dd676f01da1d/v8/Ignition Design Doc.pdf -------------------------------------------------------------------------------- /v8/Ignition_ Register Equivalence Optimization.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RichardGong/CompilersInPractice/cf042d53973092eb71c4e184b742dd676f01da1d/v8/Ignition_ Register Equivalence Optimization.pdf --------------------------------------------------------------------------------