#include "lmdb-js.h" #if ENABLE_V8_API #include #include #include #include #if NODE_VERSION_AT_LEAST(16,6,0) #if NODE_VERSION_AT_LEAST(17,0,0) #include "../dependencies/v8/v8-fast-api-calls.h" #else #include "../dependencies/v8/v8-fast-api-calls-v16.h" #endif #endif using namespace v8; int32_t getByBinaryFast(Local instance, double dwPointer, uint32_t keySize, uint32_t ifNotTxnId, int64_t txnAddress) { DbiWrap* dw = (DbiWrap*) (size_t) dwPointer; return dw->doGetByBinary(keySize, ifNotTxnId, txnAddress); } //class NanWrap : public Nan::ObjectWrap {}; void getByBinaryV8(const FunctionCallbackInfo& info) { Isolate* isolate = Isolate::GetCurrent(); auto context = isolate->GetCurrentContext(); DbiWrap* dw = (DbiWrap*) (size_t) info[0]->NumberValue(context).FromJust(); info.GetReturnValue().Set(v8::Number::New(isolate, dw->doGetByBinary( info[1]->Uint32Value(context).FromJust(), info[2]->Uint32Value(context).FromJust(), info[3]->NumberValue(context).FromJust()))); } int32_t positionFast(Local instance, double cwPointer, uint32_t flags, uint32_t offset, uint32_t keySize, uint64_t endKeyAddress) { CursorWrap* cw = (CursorWrap*) (size_t) cwPointer; DbiWrap* dw = cw->dw; dw->getFast = true; cw->flags = flags; return cw->doPosition(offset, keySize, endKeyAddress); } void positionV8(const FunctionCallbackInfo& info) { Isolate* isolate = Isolate::GetCurrent(); CursorWrap* cw = (CursorWrap*) (size_t) info[0]->NumberValue(isolate->GetCurrentContext()).FromJust(); cw->flags = info[1]->Uint32Value(isolate->GetCurrentContext()).FromJust(); uint32_t offset = info[2]->Uint32Value(isolate->GetCurrentContext()).FromJust(); uint32_t keySize = info[3]->Uint32Value(isolate->GetCurrentContext()).FromJust(); uint64_t endKeyAddress = info[4]->IntegerValue(isolate->GetCurrentContext()).FromJust(); info.GetReturnValue().Set(v8::Number::New(isolate, cw->doPosition(offset, keySize, endKeyAddress))); } int32_t iterateFast(Local instance, double cwPointer) { CursorWrap* cw = (CursorWrap*) (size_t) cwPointer; DbiWrap* dw = cw->dw; dw->getFast = true; MDB_val key, data; int rc = mdb_cursor_get(cw->cursor, &key, &data, cw->iteratingOp); return cw->returnEntry(rc, key, data); } void iterateV8(const FunctionCallbackInfo& info) { Isolate* isolate = Isolate::GetCurrent(); CursorWrap* cw = (CursorWrap*) (size_t) info[0]->NumberValue(isolate->GetCurrentContext()).FromJust(); DbiWrap* dw = cw->dw; dw->getFast = true; MDB_val key, data; int rc = mdb_cursor_get(cw->cursor, &key, &data, cw->iteratingOp); info.GetReturnValue().Set(v8::Number::New(isolate, cw->returnEntry(rc, key, data))); } int32_t writeFast(Local instance, double ewPointer, uint64_t instructionAddress) { EnvWrap* ew = (EnvWrap*) (size_t) ewPointer; int rc; if (instructionAddress) rc = WriteWorker::DoWrites(ew->writeTxn->txn, ew, (uint32_t*)instructionAddress, nullptr); else { pthread_cond_signal(ew->writingCond); rc = 0; } return rc; // if (rc && !(rc == MDB_KEYEXIST || rc == MDB_NOTFOUND)) // options.fallback = true; } void writeV8(const v8::FunctionCallbackInfo& info) { Isolate* isolate = Isolate::GetCurrent(); EnvWrap* ew = (EnvWrap*) (size_t) info[0]->NumberValue(isolate->GetCurrentContext()).FromJust(); uint64_t instructionAddress = info[1]->IntegerValue(isolate->GetCurrentContext()).FromJust(); int rc; if (instructionAddress) rc = WriteWorker::DoWrites(ew->writeTxn->txn, ew, (uint32_t*)instructionAddress, nullptr); else { pthread_cond_signal(ew->writingCond); rc = 0; } info.GetReturnValue().Set(v8::Number::New(isolate, rc)); } void resetTxnFast(Local instance, double twPointer) { TxnWrap* tw = (TxnWrap*) (size_t) twPointer; tw->reset(); } void resetTxnV8(const FunctionCallbackInfo& info) { Isolate* isolate = Isolate::GetCurrent(); TxnWrap* tw = (TxnWrap*) (size_t) info[0]->NumberValue(isolate->GetCurrentContext()).FromJust(); tw->reset(); } void noopFast(Local instance) { } void noopV8(const FunctionCallbackInfo& info) { } void clearKeptObjects(const FunctionCallbackInfo& info) { #if NODE_VERSION_AT_LEAST(14,0,0) v8::Isolate::GetCurrent()->ClearKeptObjects(); #endif } void detachBuffer(const FunctionCallbackInfo& info) { #if NODE_VERSION_AT_LEAST(12,0,0) v8::Local v8Buffer = Local::Cast(info[0]); v8Buffer->Detach(); #endif } #endif #define EXPORT_FAST(exportName, slowName, fastName) {\ auto fast = CFunction::Make(fastName);\ exports->Set(isolate->GetCurrentContext(), v8::String::NewFromUtf8(isolate, exportName, NewStringType::kInternalized).ToLocalChecked(), FunctionTemplate::New(\ isolate, slowName, Local(),\ Local(), 0, ConstructorBehavior::kThrow,\ SideEffectType::kHasNoSideEffect, &fast)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());\ } #define EXPORT_FUNCTION(exportName, funcName) \ exports->Set(isolate->GetCurrentContext(), v8::String::NewFromUtf8(isolate, exportName, NewStringType::kInternalized).ToLocalChecked(), FunctionTemplate::New(\ isolate, funcName, Local(),\ Local(), 0, ConstructorBehavior::kThrow,\ SideEffectType::kHasNoSideEffect)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()); NAPI_FUNCTION(enableDirectV8) { ARGS(2) #if ENABLE_V8_API Isolate* isolate = Isolate::GetCurrent(); napi_value exportsValue = args[0]; Local exports; memcpy((void*) &exports, (void*) &exportsValue, sizeof(exportsValue)); #if NODE_VERSION_AT_LEAST(16,6,1) bool useFastApi; napi_get_value_bool(env, args[1], &useFastApi); if (useFastApi) { EXPORT_FAST("getByBinary", getByBinaryV8, getByBinaryFast); EXPORT_FAST("position", positionV8, positionFast); EXPORT_FAST("iterate", iterateV8, iterateFast); EXPORT_FAST("write", writeV8, writeFast); EXPORT_FAST("resetTxn", resetTxnV8, resetTxnFast); EXPORT_FAST("noop", noopV8, noopFast); } else { #endif EXPORT_FUNCTION("getByBinary", getByBinaryV8); EXPORT_FUNCTION("position", positionV8); EXPORT_FUNCTION("iterate", iterateV8); EXPORT_FUNCTION("write", writeV8); EXPORT_FUNCTION("noop", noopV8); #if NODE_VERSION_AT_LEAST(16,6,1) } #endif EXPORT_FUNCTION("clearKeptObjects", clearKeptObjects); EXPORT_FUNCTION("detachBuffer", detachBuffer); #endif RETURN_UNDEFINED }