閱讀hotspot的代碼,須要先弄清楚這兩個很容易混淆的概念。
最近我想到一個辦法去區分折扣兩個,就是在中間加個「的」:java
指針
函數
這樣就很容易區分了。數組
其實在C語言中,指針數組和數組指針也是同樣的區分辦法。 加個「的」即可以解決。
爲何會有這樣的問題?老外怎麼理解這個事情?我得回去翻翻K&R的那本C的英文教材。TODO。函數
是指返回指針的函數,好比:指針
int *fun (int a, int b) { int c = a + b; return &c; // 返回一個指針 }
是指指向函數的指針code
#include <stdio.h> int (* fun)(int a, int b); // fun 就是指向函數的指針變量 int add (int a, int b) { int c = a + b; return c; } int main(){ fun = add; int result = fun(100, 200); printf("result=%d\n", result); }
還能夠結合類型聲明將函數指針定義成類型blog
#include <stdio.h> // 定義一個 返回值是int 參數是兩個int的函數指針 typedef int (* FunRefTypeTwoIntArgs)(int a, int b); // 將上面的函數指針變量 演化爲類型 FunRefTypeTwoIntArgs 就是個類型 這樣就好用多了 FunRefTypeTwoIntArgs addFun; FunRefTypeTwoIntArgs subFun; int add (int a, int b) { int c = a + b; return c; } int sub (int a, int b) { int c = a - b; return c; } int main(){ addFun = add; int result = addFun(100, 200); printf("result=%d\n", result); subFun = add; int result = subFun(500, 100); // 也能夠寫成 result = (*subFun)(500, 100); printf("result=%d\n", result); }
這就有點相似java中接口的樣子了。接口
先是類型定義結合函數指針定義一個CallStub類型,該類型是 一個 指向函數的指針內存
// share/vm/runtime/stubRoutines.hpp // Calls to Java SimonNote: 函數指針結合typedef類型定義 最終調用是在 javaCalls中的call_helper() typedef void (*CallStub)( address link, intptr_t* result, BasicType result_type, Method* method, address entry_point, intptr_t* parameters, int size_of_parameters, TRAPS );
再定義一個返回函數指針的函數,拆開講:本質是一個函數,是一個返回函數指針的函數,是一個返回 指向函數的指針的 函數,此處還涉及將內存地址直接轉成函數指針(指向函數的指針)string
// share/vm/runtime/stubRoutines.hpp // Calls to Java SimonNote: 將內存地址 轉換成函數指針 CAST_TO_FN_PTR call_stub 就是一個××返回函數指針×× 的 指針函數 ((CallStub)(castable_address(_call_stub_entry))) static CallStub call_stub() { return CAST_TO_FN_PTR(CallStub, _call_stub_entry); }
調用上面定義的io
// share/vm/runtime/javaCalls.cpp // 發起調用的地方 StubRoutines::call_stub()( (address)&link, // (intptr_t*)&(result->_value), // see NOTE above (compiler problem) result_val_address, // see NOTE above (compiler problem) result_type, method(), entry_point, args->parameters(), args->size_of_parameters(), CHECK );
下面這段 代碼 還有遺留問題 仍是沒能跑成功,至於緣由,我目前尚未答案。
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/mman.h> typedef int (* addFun)(int a, int b); int addWrap(int a, int b) { int c = add(a, b); return c; } int add(int a, int b) { return a + b; } int main() { int codeSize = sizeof(char) * 42; char* pCode = (char*)malloc(codeSize); char* pGen = pCode; mprotect(pCode, codeSize, PROT_READ | PROT_WRITE | PROT_EXEC); // 加了這一行也是core。 *pGen++ = 0x55; // 0x00000000004004fd <+0>: 55 push %rbp *pGen++ = 0x48; *pGen++ = 0x89; *pGen++ = 0xe5; // 0x00000000004004fe <+1>: 48 89 e5 mov %rsp,%rbp *pGen++ = 0x48; *pGen++ = 0x83; *pGen++ = 0xec; *pGen++ = 0x20; // 0x0000000000400501 <+4>: 48 83 ec 20 sub $0x20,%rsp *pGen++ = 0x89; *pGen++ = 0x7d; *pGen++ = 0xec; // 0x0000000000400505 <+8>: 89 7d ec mov %edi,-0x14(%rbp) *pGen++ = 0x89; *pGen++ = 0x75; *pGen++ = 0xe8; // 0x0000000000400508 <+11>: 89 75 e8 mov %esi,-0x18(%rbp) *pGen++ = 0x8b; *pGen++ = 0x55; *pGen++ = 0xe8; // 0x000000000040050b <+14>: 8b 55 e8 mov -0x18(%rbp),%edx *pGen++ = 0x8b; *pGen++ = 0x45; *pGen++ = 0xec; // 0x000000000040050e <+17>: 8b 45 ec mov -0x14(%rbp),%eax *pGen++ = 0x89; *pGen++ = 0xd6; // 0x0000000000400511 <+20>: 89 d6 mov %edx,%esi *pGen++ = 0x89; *pGen++ = 0xc7; // 0x0000000000400513 <+22>: 89 c7 mov %eax,%edi *pGen++ = 0xb8; *pGen++ = 0x00; *pGen++ = 0x00; *pGen++ = 0x00; *pGen++ = 0x00; // 0x0000000000400515 <+24>: b8 00 00 00 00 mov $0x0,%eax *pGen++ = 0xe8; *pGen++ = 0x08; *pGen++ = 0x00; *pGen++ = 0x00; *pGen++ = 0x00; // 0x000000000040051a <+29>: e8 08 00 00 00 callq 0x400527 <add> *pGen++ = 0x89; *pGen++ = 0x45; *pGen++ = 0xfc; // 0x000000000040051f <+34>: 89 45 fc mov %eax,-0x4(%rbp) *pGen++ = 0x8b; *pGen++ = 0x45; *pGen++ = 0xfc; // 0x0000000000400522 <+37>: 8b 45 fc mov -0x4(%rbp),%eax *pGen++ = 0xc9; // 0x0000000000400525 <+40>: c9 leaveq *pGen++ = 0xc3; // 0x0000000000400526 <+41>: c3 retq // addFun af = addWrap; addFun af = (addFun)pCode; // 若是我把這行註釋掉 上一行行去掉註釋 用上一行的方式 就沒問題 可是反之 跑起來就會core core在下一行 int r = af(5, 15); printf("%d\n", r); free(pCode); return 0; }
有人說用mmap才能夠解決core的問題
我有空試試