77// 
88
99#include  " FFICall.h" 
10+ #include  " FFICache.h" 
1011#include  < JavaScriptCore/Interpreter.h> 
1112#include  < JavaScriptCore/JSPromiseDeferred.h> 
1213#include  < JavaScriptCore/StrongInlines.h> 
@@ -18,9 +19,12 @@ using namespace JSC;
1819
1920const  ClassInfo FFICall::s_info = { " FFICall" 0 , CREATE_METHOD_TABLE (FFICall) };
2021
21- void  FFICall::initializeFFI (VM& vm, const  InvocationHooks& hooks, JSCell* returnType, const  Vector<JSCell*>& parameterTypes, size_t  initialArgumentIndex) {
22-     ASSERT (this ->methodTable ()->destroy  != FFICall::destroy);
22+ void  deleteCif (ffi_cif* cif) {
23+     delete[]  cif->arg_types ;
24+     delete  cif;
25+ }
2326
27+ void  FFICall::initializeFFI (VM& vm, const  InvocationHooks& hooks, JSCell* returnType, const  Vector<JSCell*>& parameterTypes, size_t  initialArgumentIndex) {
2428    this ->_invocationHooks  = hooks;
2529
2630    this ->_initialArgumentIndex  = initialArgumentIndex;
@@ -33,8 +37,11 @@ void FFICall::initializeFFI(VM& vm, const InvocationHooks& hooks, JSCell* return
3337
3438    const  ffi_type** parameterTypesFFITypes = new  const  ffi_type*[parametersCount + initialArgumentIndex];
3539
40+     this ->signatureVector .push_back (getFFITypeMethodTable (returnType).ffiType );
41+ 
3642    for  (size_t  i = 0 ; i < initialArgumentIndex; ++i) {
3743        parameterTypesFFITypes[i] = &ffi_type_pointer;
44+         this ->signatureVector .push_back (&ffi_type_pointer);
3845    }
3946
4047    for  (size_t  i = 0 ; i < parametersCount; i++) {
@@ -45,10 +52,10 @@ void FFICall::initializeFFI(VM& vm, const InvocationHooks& hooks, JSCell* return
4552        this ->_parameterTypes .append (ffiTypeMethodTable);
4653
4754        parameterTypesFFITypes[i + initialArgumentIndex] = ffiTypeMethodTable.ffiType ;
55+         this ->signatureVector .push_back (parameterTypesFFITypes[i + initialArgumentIndex]);
4856    }
4957
50-     this ->_cif  = new  ffi_cif;
51-     ffi_prep_cif (this ->_cif , FFI_DEFAULT_ABI, parametersCount + initialArgumentIndex, const_cast <ffi_type*>(this ->_returnType .ffiType ), const_cast <ffi_type**>(parameterTypesFFITypes));
58+     this ->_cif  = checkForExistingCif (parametersCount + initialArgumentIndex, const_cast <ffi_type*>(this ->_returnType .ffiType ), const_cast <ffi_type**>(parameterTypesFFITypes));
5259
5360    this ->_argsCount  = _cif->nargs ;
5461    this ->_stackSize  = 0 ;
@@ -57,17 +64,34 @@ void FFICall::initializeFFI(VM& vm, const InvocationHooks& hooks, JSCell* return
5764    this ->_stackSize  += malloc_good_size (sizeof (void  * [this ->_cif ->nargs ]));
5865
5966    this ->_returnOffset  = this ->_stackSize ;
60-     this ->_stackSize  += malloc_good_size (std::max (this ->_cif ->rtype ->size , sizeof (ffi_arg)));
67+     this ->_stackSize  += malloc_good_size (std::max (this ->_cif . get () ->rtype ->size , sizeof (ffi_arg)));
6168
6269    for  (size_t  i = 0 ; i < this ->_argsCount ; i++) {
6370        this ->_argValueOffsets .push_back (this ->_stackSize );
6471        this ->_stackSize  += malloc_good_size (std::max (this ->_cif ->arg_types [i]->size , sizeof (ffi_arg)));
6572    }
6673}
6774
75+ std::shared_ptr<ffi_cif> FFICall::checkForExistingCif (unsigned  int  nargs, ffi_type* rtype, ffi_type** atypes) {
76+ 
77+     std::unordered_map<std::vector<const  ffi_type*>, std::shared_ptr<ffi_cif>, SignatureHash>::const_iterator it = FFICache::global ()->cifCache .find (this ->signatureVector );
78+ 
79+     if  (it == FFICache::global ()->cifCache .end ()) {
80+         std::shared_ptr<ffi_cif> shared (new  ffi_cif, deleteCif);
81+         ffi_prep_cif (shared.get (), FFI_DEFAULT_ABI, nargs, rtype, atypes);
82+         FFICache::global ()->cifCache [this ->signatureVector ] = shared;
83+     }
84+ 
85+     return  FFICache::global ()->cifCache [this ->signatureVector ];
86+ }
87+ 
6888FFICall::~FFICall () {
69-     delete[]  this ->_cif ->arg_types ;
70-     delete  this ->_cif ;
89+ 
90+     if  (this ->_cif .use_count () == 2 ) {
91+         std::unordered_map<std::vector<const  ffi_type*>, std::shared_ptr<ffi_cif>, SignatureHash>::const_iterator it;
92+         it = FFICache::global ()->cifCache .find (this ->signatureVector );
93+         FFICache::global ()->cifCache .erase (it);
94+     }
7195}
7296
7397void  FFICall::visitChildren (JSCell* cell, SlotVisitor& visitor) {
@@ -99,7 +123,7 @@ EncodedJSValue JSC_HOST_CALL FFICall::call(ExecState* execState) {
99123
100124    {
101125        JSLock::DropAllLocks locksDropper (execState);
102-         ffi_call (callee->_cif , FFI_FN (invocation.function ), invocation._buffer  + callee->_returnOffset , reinterpret_cast <void **>(invocation._buffer  + callee->_argsArrayOffset ));
126+         ffi_call (callee->_cif . get () , FFI_FN (invocation.function ), invocation._buffer  + callee->_returnOffset , reinterpret_cast <void **>(invocation._buffer  + callee->_argsArrayOffset ));
103127    }
104128
105129    JSValue result = callee->_returnType .read (execState, invocation._buffer  + callee->_returnOffset , callee->_returnTypeCell .get ());
@@ -150,7 +174,7 @@ JSObject* FFICall::async(ExecState* execState, JSValue thisValue, const ArgList&
150174      JSC::VM& vm = fakeExecState->vm ();
151175      auto  scope = DECLARE_CATCH_SCOPE (vm);
152176
153-       ffi_call (callee->_cif , FFI_FN (invocation->function ), invocation->resultBuffer (), reinterpret_cast <void **>(invocation->_buffer  + callee->_argsArrayOffset ));
177+       ffi_call (callee->_cif . get () , FFI_FN (invocation->function ), invocation->resultBuffer (), reinterpret_cast <void **>(invocation->_buffer  + callee->_argsArrayOffset ));
154178
155179      JSLockHolder lockHolder (fakeExecState);
156180      //  we no longer have a valid caller on the stack, what with being async and all
@@ -189,4 +213,4 @@ JSObject* FFICall::async(ExecState* execState, JSValue thisValue, const ArgList&
189213
190214    return  deferred->promise ();
191215}
192- }
216+ }  //  namespace NativeScript 
0 commit comments