AMD has an ABI specification that describes the calling convention to use on x86-64. All OSes follow it, except for Windows which has it's own x86-64 calling convention. Why?
Does anyone know the technical, historical, or political reasons for this difference, or is it purely a matter of NIHsyndrome?
I understand that different OSes may have different needs for higher level things, but that doesn't explain why for example the register parameter passing order on Windows is rcx - rdx …
C++有多重继承.在程序集级别实现多重继承可能非常复杂,但在线上有关于如何正常完成(vtables,指针修正,thunks等)的良好描述.
Java没有多个实现继承,但它确实有多个接口继承,所以我不认为每个类有一个vtable的直接实现可以实现它.java如何在内部实现接口?
我意识到与C++相反,Java是Jit编译的,因此不同的代码片段可能会有不同的优化,不同的JVM可能会做不同的事情.那么,是否存在许多JVM遵循的一般策略,或者有人知道特定JVM中的实现吗?
此外,JVM通常是虚拟化和内联方法调用,在这种情况下根本没有涉及vtable或等效项,因此询问实现虚拟/接口方法调用的实际汇编序列可能没有意义,但我认为大多数JVM仍然保留一些如果类无法将所有内容虚拟化,那么这些类的一般表示形式即可使用.这个假设是错的吗?这种表示形式是否像C++ vtable一样?如果是这样,接口有单独的vtable,它们如何与类vtable链接?如果是这样,对象实例可以有多个vtable指针(对于类/接口vtable),就像C++中的对象实例一样吗?对同一对象的类类型和接口类型的引用是否总是具有相同的二进制值,或者它们是否可以像C++中那样需要指针修复?
(供参考:这个问题提出了类似CLR的相似之处,这篇msdn文章似乎有一个很好的解释,虽然现在可能已经过时了.我找不到任何类似的Java.)
编辑:
在逐步执行一些Qt代码时,我遇到了以下内容.该函数QMainWindowLayout::invalidate()具有以下实现:
void QMainWindowLayout::invalidate()
{
QLayout::invalidate()
minSize = szHint = QSize();
}
Run Code Online (Sandbox Code Playgroud)
它被编译为:
<invalidate()> push %rbx
<invalidate()+1> mov %rdi,%rbx
<invalidate()+4> callq 0x7ffff4fd9090 <QLayout::invalidate()>
<invalidate()+9> movl $0xffffffff,0x564(%rbx)
<invalidate()+19> movl $0xffffffff,0x568(%rbx)
<invalidate()+29> mov 0x564(%rbx),%rax
<invalidate()+36> mov %rax,0x56c(%rbx)
<invalidate()+43> pop %rbx
<invalidate()+44> retq
Run Code Online (Sandbox Code Playgroud)
从invalidate + 9到invalidate + 36的程序集似乎很愚蠢.首先,代码将-1写入%rbx + 0x564和%rbx + 0x568,但是然后它将-1从%rbx + 0x564加载回寄存器,只是将其写入%rbx + 0x56c.这似乎是编译器应该能够轻松优化到另一个立即行动的东西.
那么这个愚蠢的代码(如果是这样,为什么编译器不会对它进行优化?)或者这是否比使用另一个立即动作更聪明,更快?
(注意:此代码来自ubuntu提供的正常发布库版本,因此它可能是由GCC在优化模式下编译的.minSize而且szHint变量是类型的正常变量QSize.)
我知道PHP mt_rand()不应该用于安全目的,因为它的结果不是加密强.然而,许多PHP代码就是这样做的,或者如果没有更好的随机源,则将其用作后备.
那有多糟糕呢?哪些随机源mt_rand用于播种?mt_rand加密应用程序是否存在其他安全问题?
从Java 6的某个地方开始,Hotspot JVM可以进行转义分析并在堆栈上而不是在垃圾收集堆上分配非转义对象.这导致生成的代码加速并减少垃圾收集器的压力.
Hotspot何时能够堆叠分配对象的规则是什么?换句话说,我什么时候可以依靠它来进行堆栈分配?
编辑:这个问题是重复的,但是(IMO)下面的答案比原始问题提供的答案更好.
可能重复:
并发:C++ 11内存模型中的原子和易失性
使用C++ 11 <atomic>规范,是否有保证新鲜度?不同内存顺序的描述只涉及重新排序(据我所见).
具体来说,在这种情况下:
#include <atomic>
std::atomic<int> cancel_work(0);
// Thread 1 is executing this function
void thread1_func() {
...
while (cancel_work.load(<some memory order>) == 0) {
...do work...
}
}
// Thread 2 executes this function
void thread2_func() {
...
cancel_work.store(1, <some memory order>);
...
}
Run Code Online (Sandbox Code Playgroud)
如果线程1和线程2不共享任何其他数据cancel_work,那么在我看来,不需要任何排序保证,并且std::memory_order_relax对于存储和加载都是足够的.但这是否能保证线程1能够看到更新,cancel_work而不是只是重复读取其本地缓存线而不从主内存刷新它?如果没有,那么提供保证所需的最低金额是多少?
Grails 3(至少3.1.10)在仅运行特定测试时是不稳定的.如何让它运行单个集成测试?
我正在考虑在C#中创建持久集合(列表或其他),但我无法找到一个好的API.
我在Clojure意义上使用' persistent ' :持久列表是一个列表,其行为就像它具有值语义而不是引用语义,但不会产生复制大值类型的开销.持久性集合使用copy-on-write来共享内部结构.伪代码:
l1 = PersistentList()
l1.add("foo")
l1.add("bar")
l2 = l1
l1.add("baz")
print(l1) # ==> ["foo", "bar", "baz"]
print(l2) # ==> ["foo", "bar"]
# l1 and l2 share a common structure of ["foo", "bar"] to save memory
Run Code Online (Sandbox Code Playgroud)
Clojure使用这样的数据结构,但是在Clojure中,所有数据结构都是不可变的.执行所有写时复制操作会产生一些开销,因此Clojure以瞬态数据结构的形式提供了一种解决方法,如果您确定不与其他任何人共享数据结构,则可以使用它.如果你只有对数据结构的引用,为什么不直接改变它而不是经历所有的写时复制开销.
获得此效率增益的一种方法是在数据结构上保留引用计数(尽管我不认为Clojure以这种方式工作).如果引用计数为1,那么您将保留唯一的引用,因此破坏性地进行更新.如果refcount更高,其他人也持有对它的引用,它应该表现得像一个值类型,所以copy-on-write不会打扰其他引用者.
在这种数据结构的API中,可能会暴露引用计数,这会使API严重降低可用性,或者无法进行引用计数,如果每个操作都是COW,则会导致不必要的写时复制开销,或API丢失它的值类型行为,用户必须管理何时手动执行COW.
如果C#具有结构的复制构造函数,那么这是可能的.可以定义一个包含对实际数据结构的引用的结构,并在结构的复制构造函数和析构函数中执行所有increment()/ decref()调用.
有没有办法在C#中自动执行引用计数或结构复制构造函数,而不会打扰API用户?
编辑:
我想将git哈希嵌入到python模块的版本号中,如果该模块是使用git repository安装的./setup.py install.我怎么做?
我的想法是定义一个函数setup.py来插入哈希并安排在安装程序将模块复制到其build/lib/目录时调用它,但在将模块安装到其最终目标之前.那时有没有办法挂钩构建过程?
编辑:我知道如何从命令行获取当前版本的哈希值,我问的是如何在构建/安装期间在正确的时间运行这样的命令.
只要稍后在翻译单元中定义,就可以声明一个类而不定义它(前向声明).在函数的情况下,可以声明函数而不在转换单元中定义它,并且链接器将其链接到其在不同转换单元中的定义.是否有可能对类声明做同样的事情?
(如果这不可能,对于在当前TL中没有定义的前向声明的类有什么用处,还是总是出错?)
像这样的东西,除了这不编译:
mymain.cpp:
class myclass; // declare without defining
myclass::myclass();
void myclass::barf();
int main() {
myclass *m = new myclass();
m->barf();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
myclass.cpp:
#include <iostream>
class myclass { // define the implementation
public:
myclass();
void barf();
};
myclass::myclass() { } //empty constructor
void myclass::barf() {
std::cout << "barfing\n";
}
Run Code Online (Sandbox Code Playgroud) c++ ×3
java ×2
api-design ×1
assembly ×1
atomic ×1
c# ×1
c++11 ×1
class ×1
clojure ×1
concurrency ×1
distutils ×1
gcc ×1
git ×1
grails ×1
interface ×1
internals ×1
jvm ×1
jvm-hotspot ×1
persistent ×1
php ×1
pytest ×1
python ×1
random ×1
security ×1
unit-testing ×1
vtable ×1
windows ×1
x86-64 ×1