编译器优化

volatile变量

て烟熏妆下的殇ゞ 提交于 2020-01-04 02:55:07
volatile 的作用是: 作为指令 关键字 ,确保本条指令不会因 编译器 的优化而省略,且要求每次直接读值. 简单地说就是防止编译器对代码进行优化.比如如下程序: ? 1 2 3 4 XBYTE[2]=0x55; XBYTE[2]=0x56; XBYTE[2]=0x57; XBYTE[2]=0x58; 对外部硬件而言,上述四条语句分别表示不同的操作,会产生四种不同的动作,但是编译器却会对上述四条语句进行优化,认为只有XBYTE[2]=0x58(即忽略前三条语句,只产生一条机器代码)。如果键入 volatile ,则编译器会逐一的进行编译并产生相应的机器代码(产生四条代码). 来源: https://www.cnblogs.com/heiming/p/5804271.html

volatile变量

一个人想着一个人 提交于 2020-01-04 02:53:53
一、volatile概述 volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址(内存)中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举例说明。 volatile一般用于修饰多线程间被多个任务共享的变量和并行设备硬件寄存器等。 二、volatile使用案例 在DSP开发中,经常需要等待某个事件的触发,所以经常会写出这样的程序: 1 short flag; 2 void test() 3 { 4 do1(); 5 while(flag==0); 6 do2(); 7 } 这段程序等待内存变量flag的值变为1,之后才运行do2()。变量flag的值由别的程序更改,这个程序可能是某个硬件中断服务程序。例如:如果某个按钮按下的话,就会对DSP产生中断,在按键中断程序中修改flag为1,这样上面的程序就能够得以继续运行。但是,编译器并不知道flag的值会被别的程序修改,因此在它进行优化的时候,可能会把flag的值先读入某个寄存器,然后等待那个寄存器变为1。如果不幸进行了这样的优化,那么while循环就变成了死循环,因为寄存器的内容不可能被中断服务程序修改。为了让程序每次都读取真正flag变量的值

JAVA编译器常量

佐手、 提交于 2020-01-03 01:36:46
  编译器常量的特点就是:它的值在编译期就可以确定。比如:   final int i = 5;   再傻的编译器也能在编译时看出它的值是5,不需要到运行时。对于运行时常量,它的值虽然在运行时初始化后不再发生变化,但问题就在于它的初始值要到运行时才能确定。   比如:   Random rand = new Random(47);   final int i4 = rand.nextInt(20);   虽然i4的值在定义并初始化后不会再发生变化(除非你使用一些不符合标准的小技巧),但再聪明的编译器也无法在编译时确定它的值呀。   为了更清楚的理解编译器常量的概念,我们引入【常量折叠】的概念:在编译器里进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表,可以算作一种编译优化。   对于编译期常量,编译器常常在编译时就可以折叠开。而对于运行期常量,编译期无法折叠,编译器能做的,只是对所有可能修改它的动作报错。 案例1: package testPage; class InitalizedClass { static { System.out.println("You have initalized InitalizedClass!"); } public static int inititalize_varible = 1; } public class

c++常用库

故事扮演 提交于 2019-12-29 10:32:16
c++常用库 C++ 资源大全 关于 C++ 框架、库和资源的一些汇总列表,内容包括:标准库、Web应用框架、人工智能、数据库、图片处理、机器学习、日志、代码分析等。 标准库 C++标准库,包括了STL容器,算法和函数等。 C++ Standard Library:是一系列类和函数的集合,使用核心语言编写,也是C++ISO自身标准的一部分。 Standard Template Library:标准模板库 C POSIX library : POSIX系统的C标准库规范 ISO C++ Standards Committee :C++标准委员会 框架 C++通用框架和库 Apache C++ Standard Library:是一系列算法,容器,迭代器和其他基本组件的集合 ASL :Adobe源代码库提供了同行的评审和可移植的C++源代码库。 Boost :大量通用C++库的集合。 BDE :来自于彭博资讯实验室的开发环境。 Cinder:提供专业品质创造性编码的开源开发社区。 Cxxomfort:轻量级的,只包含头文件的库,将C++ 11的一些新特性移植到C++03中。 Dlib:使用契约式编程和现代C++科技设计的通用的跨平台的C++库。 EASTL :EA-STL公共部分 ffead-cpp :企业应用程序开发框架 Folly:由Facebook开发和使用的开源C++库

java内存模型之重排序

淺唱寂寞╮ 提交于 2019-12-29 03:15:28
1.重排序   在执行程序时为了提高性能,编译器和处理器常常会对指令做重排序.重排序分三种类型:   1.编译器优化的重排序.编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序.   2.指令级并行的重排序.现代处理器采用了指令级并行技术(Instruction-Level Parallelism, ILP)来将多条指令重叠执行.如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序.   3.内存系统的重排序.由于处理器是使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是乱序执行.   从java源代码到最终实际执行的指令序列,会分别经历下面三中重排序:      上述的1属于编译器重排序,2和3属于处理器重排序.这些重排序都可能会导致多线程程序出现内存可见性问题.对于编译器,JMM的编译器重排序规则会禁止特定类型的编译器重排序(不是所有的编译器重排序都要禁止).对于处理器重排序,JMM的处理器重排序规则会要求java编译器在生成指令序列时,插入特定类型的内存屏障(memory barriers,inter称之为memory fence)指令,通过特点的内存屏障来禁止特定的处理器重排序(不是所有的处理器重排序都要禁止).   JMM属于语言级的内存模型,他确保在不同的编译器和不同的处理器平台上,通过禁止特定类型的编译器重排序和处理器重排序

【深入Java虚拟机】之七:Javac编译与JIT编译

那年仲夏 提交于 2019-12-28 18:04:33
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 转载请注明出处: http://blog.csdn .NET /ns_code/article/details/18009455 编译过程 不论是物理机还是虚拟机,大部分的程序代码从开始编译到最终转化成物理机的目标代码或虚拟机能执行的指令集之前,都会按照如下图所示的各个步骤进行: 其中绿色的模块可以选择性实现。很容易看出,上图中间的那条分支是解释执行的过程(即一条字节码一条字节码地解释执行,如 JavaScript ),而下面的那条分支就是传统编译原理中从源代码到目标机器代码的生成过程。 如今,基于物理机、虚拟机等的语言,大多都遵循这种基于现代经典编译原理的思路,在执行前先对程序源码进行词法解析和语法解析处理,把源码转化为抽象语法树。对于一门具体语言的实现来说,词法和语法分析乃至后面的优化器和目标代码生成器都可以选择独立于执行引擎,形成一个完整意义的编译器去实现,这类代表是C/C++语言。也可以把抽象语法树或指令流之前的步骤实现一个半独立的编译器,这类代表是 Java 语言。又或者可以把这些步骤和执行引擎全部集中在一起实现,如大多数的JavaScript执行器。 Javac编译 在Java中提到“编译”,自然很容易想到Javac编译器将*.java文件编译成为*.class文件的过程

Go程序的一生是怎样的?

天大地大妈咪最大 提交于 2019-12-25 21:28:35
Go 程序是怎样跑起来的 原创: 饶全成 码农桃花源 刚开始写这篇文章的时候,目标非常大,想要探索 Go 程序的一生:编码、编译、汇编、链接、运行、退出。它的每一步具体如何进行,力图弄清 Go 程序的这一生。 在这个过程中,我又复习了一遍《程序员的自我修养》。这是一本讲编译、链接的书,非常详细,值得一看!数年前,我第一次看到这本书的书名,就非常喜欢。因为它模仿了周星驰喜剧之王里出现的一本书 ——《演员的自我修养》。心向往之! 在开始本文之前,先推荐一位头条大佬的博客——《面向信仰编程》,他的 Go 编译系列文章,非常有深度,直接深入编译器源代码,我是看了很多遍了。博客链接可以从参考资料里获取。 理想很大,实现的难度也是非常大。为了避免砸了“深度解密”这个牌子,这次起了个更温和的名字,嘿嘿。 下面是文章的目录: 引入 我们从一个 HelloWorld 的例子开始: package main import "fmt" func main() { fmt. Println ( "hello world" ) } 当我用我那价值 1800 元的 cherry 键盘潇洒地敲完上面的 hello world 代码时,保存在硬盘上的 hello.go 文件就是一个字节序列了,每个字节代表一个字符。 用 vim 打开 hello.go 文件,在命令行模式下,输入命令: :%!xxd 就能在 vim

CLR基础之一---认识CLR [《CLR via C#》读书笔记]

情到浓时终转凉″ 提交于 2019-12-24 23:05:10
《CLR via C#》读书笔记 什么是CLR CLR的基本概念 通用语言运行平台(Common Language Runtime,简称CLR)是微软为他们的.Net虚拟机所选用的名称。这是通用语言架构(简称CLI)的微软实现版本,它定义了一个代码运行的环境。CLR运行一种称为“通用中间语言”的字节码,这个是微软的通用中间语言实现版本。 CLR运行在微软的视窗操作系统上。查看通用语言架构可以找到该规格的实现版本列表。其中有一些版本是运行在非Windows的操作系统中。(维基百科CLR) 以上定义至少包含以下几点信息: CLR是一个类似于JVM的虚拟机,为微软的.Net产品提供运行环境。 CLR上实际运行的并不是我们通常所用的编程语言(例如C#、VB等),而是一种字节码形态的“中间语言”。这意味着只要能将代码编译成这种特定的“中间语言”(MSIL),任何语言的产品都能运行在CLR上。 CLR通常被运行在Windows系统上,但是也有一些非Windows的版本。这意味着.Net也很容易实现“跨平台”。(至于为什么大家的印象中.Net的跨平台性不如Java,更多的是微软商业战略导致的) CLR和.Net Framework的关系 .NET框架 (.NET Framework) 是由微软开发,一个致力于敏捷软件开发(Agile software development)、快速应用开发

V8 是怎么跑起来的 —— V8 的 JavaScript 执行管道

帅比萌擦擦* 提交于 2019-12-23 10:21:26
文章创作于 2019-11-08,2019-12-20 迁移至此。 作者有话说 “V8 是怎么跑起来的” 系列是我学习 V8 过程中的总结。从一年前正式成为前端工程师开始,我便有意识地了解和学习 V8。我也发现,在技术社区中鲜有内容新鲜的、原创度高的中文资料,于是开始将我学习过程中的总结分享出来。 由于工作繁忙,我已经半年没有更新博客。这个系列的引子是 4 月写的一篇 《V8 是怎么跑起来的 —— V8 中的对象表示》 ,我们通过使用 Chrome DevTools 验证的方式介绍了 V8 中的对象表示。 本文是这个系列真正意义的第一篇文章。文章的定位是这个系列的大纲,将按照 JavaScript 在 V8 中的执行流程,顺序介绍每一步的操作,并澄清一个社区中流传甚广的 “错误”。本文不会过于深究其中的细节(后续篇章将展开),您可以在评论中留下您想了解 V8 引擎的部分,也许下一篇选题会采纳并优先介绍。 祝阅读愉快。 1. 为什么是 V8 Any application that can be written in JavaScript, will eventually be written in JavaScript. 相信很多的朋友都听过前端界的一个著名定律,叫做 Atwood’s Law 。2007 年,Jeff Atwood 提出 “所有可以用 JavaScript

编译和链接的过程(非原创,转载)

扶醉桌前 提交于 2019-12-22 05:04:35
转载这篇博文的目的是想要记录自己不太明白的地方 程序要运行起来,必须要经过四个步骤:预处理、编译、汇编和链接。接下来通过几个简单的例子来详细讲解一下这些过程。 对于上边用到的几个选项需要说明一下。 使用 gcc 命令不跟任何的选项的话,会默认执行预处理、编译、汇编、链接这整个过程,如果程序没有错,就会得到一个可执行文件,默认为a.out -E选项:提示编译器执行完预处理就停下来,后边的编译、汇编、链接就先不执行了。 -S选项:提示编译器执行完编译就停下来,不去执行汇编和链接了。 -c选项:提示编译器执行完汇编就停下来。 所以,这三个选项相当于是限定了编译器执行操作的停止时间,而不是单独的将某一步拎出来执行。 上述程序的执行过程大家应该都很熟悉了,就不浪费口舌了。 一、预处理: 使用-E选项,表示只进行预编译,对应生成一个 .i 文件。 预处理过程进行的操作: 将所有的“#define”删除,并且展开所有的宏定义 处理所有的条件编译指令,比如“#if”、“#ifdef”、“#elif”、“#else”、“#endif” 处理“#include”预编译指令,将被包含的头文件插入到该编译指令的位置。(这个过程是递归进行的,因为被包含的文件可能还包含了其他文件) 删除所有的注释“//”和“/* */”。 添加行号和文件名标识