diff options
author | Andrew Morrow <acm@mongodb.com> | 2015-07-16 16:25:13 -0400 |
---|---|---|
committer | Andrew Morrow <acm@mongodb.com> | 2015-08-24 08:31:31 -0400 |
commit | 3184194f9e0eb63fc3f6d73579681c4007022e9b (patch) | |
tree | 8bef720832965ac6af6269247f5185e9f7de9b45 /src/mongo/scripting/engine_v8.h | |
parent | 9a988c6c0ed719a03350d7e7dc7e62f555068bfd (diff) | |
download | mongo-3184194f9e0eb63fc3f6d73579681c4007022e9b.tar.gz |
SERVER-19378 Remove support for building with v8
Diffstat (limited to 'src/mongo/scripting/engine_v8.h')
-rw-r--r-- | src/mongo/scripting/engine_v8.h | 629 |
1 files changed, 0 insertions, 629 deletions
diff --git a/src/mongo/scripting/engine_v8.h b/src/mongo/scripting/engine_v8.h deleted file mode 100644 index 2cf5b218e3c..00000000000 --- a/src/mongo/scripting/engine_v8.h +++ /dev/null @@ -1,629 +0,0 @@ -// engine_v8.h - -/* Copyright 2009 10gen Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects - * for all of the code used other than as permitted herein. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you do not - * wish to do so, delete this exception statement from your version. If you - * delete this exception statement from all source files in the program, - * then also delete it in the license file. - */ - -#pragma once - -#include <v8.h> -#include <vector> - -#include "mongo/base/disallow_copying.h" -#include "mongo/base/string_data.h" -#include "mongo/client/dbclientinterface.h" -#include "mongo/client/dbclientcursor.h" -#include "mongo/platform/unordered_map.h" -#include "mongo/scripting/engine.h" -#include "mongo/scripting/deadline_monitor.h" -#include "mongo/scripting/v8_profiler.h" - -/** - * V8_SIMPLE_HEADER must be placed in any function called from a public API - * that work with v8 handles (and/or must be within the V8Scope's isolate - * and context). Be sure to close the handle_scope if returning a v8::Handle! - */ -#define V8_SIMPLE_HEADER \ - v8::Locker v8lock(_isolate); /* acquire isolate lock */ \ - v8::Isolate::Scope iscope(_isolate); /* enter the isolate; exit when out of scope */ \ - v8::HandleScope handle_scope; /* make the current scope own local handles */ \ - v8::Context::Scope context_scope(_context); /* enter the context; exit when out of scope */ - -namespace mongo { - -class V8ScriptEngine; -class V8Scope; -class BSONHolder; -class JSThreadConfig; - -typedef v8::Handle<v8::Value>(*v8Function)(V8Scope* scope, const v8::Arguments& args); - -/** - * The ObjTracker class keeps track of all weakly referenced v8 objects. This is - * required because v8 does not invoke the WeakReferenceCallback when shutting down - * the context/isolate. To track a new object, add an ObjTracker<MyObjType> member - * variable to the V8Scope (if one does not already exist for that type). Instead - * of calling v8::Persistent::MakeWeak() directly, simply invoke track() with the - * persistent handle and the pointer to be freed. - */ -template <typename _ObjType> -class ObjTracker { -public: - /** Track an object to be freed when it is no longer referenced in JavaScript. - * Return handle to object instance shared pointer. - * @param instanceHandle persistent handle to the weakly referenced object - * @param rawData pointer to the object instance - */ - v8::Local<v8::External> track(v8::Persistent<v8::Value> instanceHandle, _ObjType* instance) { - TrackedPtr* collectionHandle = new TrackedPtr(instance, this); - _container.insert(collectionHandle); - instanceHandle.MakeWeak(collectionHandle, deleteOnCollect); - return v8::External::New(&(collectionHandle->_objPtr)); - } - /** - * Free any remaining objects and their TrackedPtrs. Invoked when the - * V8Scope is destructed. - */ - ~ObjTracker() { - typename std::set<TrackedPtr*>::iterator it = _container.begin(); - while (it != _container.end()) { - delete *it; - _container.erase(it++); - } - } - -private: - /** - * Simple struct which contains a pointer to the tracked object, and a pointer - * to the ObjTracker which owns it. This is the argument supplied to v8's - * WeakReferenceCallback and MakeWeak(). - */ - struct TrackedPtr { - public: - TrackedPtr(_ObjType* instance, ObjTracker<_ObjType>* tracker) - : _objPtr(instance), _tracker(tracker) {} - std::shared_ptr<_ObjType> _objPtr; - ObjTracker<_ObjType>* _tracker; - }; - - /** - * v8 callback for weak persistent handles that have been marked for removal by the - * garbage collector. Signature conforms to v8's WeakReferenceCallback. - * @param instanceHandle persistent handle to the weakly referenced object - * @param rawData pointer to the TrackedPtr instance - */ - static void deleteOnCollect(v8::Persistent<v8::Value> instanceHandle, void* rawData) { - TrackedPtr* trackedPtr = static_cast<TrackedPtr*>(rawData); - trackedPtr->_tracker->_container.erase(trackedPtr); - delete trackedPtr; - instanceHandle.Dispose(); - } - - // container for all TrackedPtrs created by this ObjTracker instance - std::set<TrackedPtr*> _container; -}; - -/** - * A V8Scope represents a unit of javascript execution environment; specifically a single - * isolate and a single context executing in a single mongo thread. A V8Scope can be reused - * in another thread only after reset() has been called. - * - * NB: - * - v8 objects/handles/etc. cannot be shared between V8Scopes - * - in mongod, each scope is associated with an opId (for KillOp support) - * - any public functions that call the v8 API should use a V8_SIMPLE_HEADER - * - the caller of any public function that returns a v8 type or has a v8 handle argument - * must enter the isolate, context, and set up the appropriate handle scope - */ -class V8Scope : public Scope { -public: - V8Scope(V8ScriptEngine* engine); - ~V8Scope(); - - virtual void init(const BSONObj* data); - - /** - * Reset the state of this scope for use by another thread or operation - */ - virtual void reset(); - - /** - * Terminate this scope - */ - virtual void kill(); - - /** check if there is a pending killOp request */ - bool isKillPending() const; - - /** - * Register this scope with the mongo op id. If executing outside the - * context of a mongo operation (e.g. from the shell), killOp will not - * be supported. - */ - virtual void registerOperation(OperationContext* txn); - - /** - * Unregister this scope with the mongo op id. - */ - virtual void unregisterOperation(); - - /** - * Obtains the operation context associated with this Scope, so it can be given to the - * DBDirectClient used by the V8 engine's connection. Only needed for dbEval. - */ - OperationContext* getOpContext() const; - - /** - * Connect to a local database, create a Mongo object instance, and load any - * server-side js into the global object - */ - virtual void localConnectForDbEval(OperationContext* txn, const char* dbName); - - virtual void externalSetup(); - - virtual void installDBAccess(); - - virtual void installBSONTypes(); - - virtual std::string getError() { - return _error; - } - - virtual bool hasOutOfMemoryException(); - - /** - * Run the garbage collector on this scope (native function). @see GCV8 for the - * javascript binding version. - */ - void gc(); - - /** - * get a global property. caller must set up the v8 state. - */ - v8::Handle<v8::Value> get(const char* field); - - virtual double getNumber(const char* field); - virtual int getNumberInt(const char* field); - virtual long long getNumberLongLong(const char* field); - virtual Decimal128 getNumberDecimal(const char* field); - virtual std::string getString(const char* field); - virtual bool getBoolean(const char* field); - virtual BSONObj getObject(const char* field); - - virtual void setNumber(const char* field, double val); - virtual void setString(const char* field, StringData val); - virtual void setBoolean(const char* field, bool val); - virtual void setElement(const char* field, const BSONElement& e); - virtual void setObject(const char* field, const BSONObj& obj, bool readOnly); - virtual void setFunction(const char* field, const char* code); - - virtual int type(const char* field); - - virtual void rename(const char* from, const char* to); - - virtual int invoke(ScriptingFunction func, - const BSONObj* args, - const BSONObj* recv, - int timeoutMs = 0, - bool ignoreReturn = false, - bool readOnlyArgs = false, - bool readOnlyRecv = false); - - virtual bool exec(StringData code, - const std::string& name, - bool printResult, - bool reportError, - bool assertOnError, - int timeoutMs); - - // functions to create v8 object and function templates - virtual void injectNative(const char* field, NativeFunction func, void* data = 0); - void injectNative(const char* field, - NativeFunction func, - v8::Handle<v8::Object>& obj, - void* data = 0); - - // These functions inject a function (either an unwrapped function pointer or a pre-wrapped - // FunctionTemplate) into the provided object. If no object is provided, the function will - // be injected at global scope. These functions take care of setting the function and class - // name on the returned FunctionTemplate. - v8::Handle<v8::FunctionTemplate> injectV8Function(const char* name, v8Function func); - v8::Handle<v8::FunctionTemplate> injectV8Function(const char* name, - v8Function func, - v8::Handle<v8::Object>& obj); - v8::Handle<v8::FunctionTemplate> injectV8Function(const char* name, - v8::Handle<v8::FunctionTemplate> ft, - v8::Handle<v8::Object>& obj); - - // Injects a method into the provided prototype - v8::Handle<v8::FunctionTemplate> injectV8Method(const char* name, - v8Function func, - v8::Handle<v8::ObjectTemplate>& proto); - v8::Handle<v8::FunctionTemplate> createV8Function(v8Function func); - virtual ScriptingFunction _createFunction(const char* code, - ScriptingFunction functionNumber = 0); - v8::Local<v8::Function> __createFunction(const char* code, - ScriptingFunction functionNumber = 0); - - /** - * Convert BSON types to v8 Javascript types - */ - v8::Handle<v8::Object> mongoToLZV8(const mongo::BSONObj& m, bool readOnly = false); - v8::Handle<v8::Value> mongoToV8Element(const BSONElement& f, bool readOnly = false); - - /** - * Convert v8 Javascript types to BSON types - */ - mongo::BSONObj v8ToMongo(v8::Handle<v8::Object> obj, int depth = 0); - void v8ToMongoElement(BSONObjBuilder& b, - StringData sname, - v8::Handle<v8::Value> value, - int depth = 0, - BSONObj* originalParent = 0); - void v8ToMongoObject(BSONObjBuilder& b, - StringData sname, - v8::Handle<v8::Value> value, - int depth, - BSONObj* originalParent); - void v8ToMongoNumber(BSONObjBuilder& b, - StringData elementName, - v8::Handle<v8::Number> value, - BSONObj* originalParent); - void v8ToMongoRegex(BSONObjBuilder& b, StringData elementName, v8::Handle<v8::RegExp> v8Regex); - void v8ToMongoDBRef(BSONObjBuilder& b, StringData elementName, v8::Handle<v8::Object> obj); - void v8ToMongoBinData(BSONObjBuilder& b, StringData elementName, v8::Handle<v8::Object> obj); - OID v8ToMongoObjectID(v8::Handle<v8::Object> obj); - - v8::Local<v8::Value> newId(const OID& id); - - /** - * Convert a JavaScript exception to a stl string. Requires - * access to the V8Scope instance to report source context information. - */ - std::string v8ExceptionToSTLString(const v8::TryCatch* try_catch); - - /** - * Create a V8 std::string with a local handle - */ - static inline v8::Handle<v8::String> v8StringData(StringData str) { - return v8::String::New(str.rawData(), str.size()); - } - - /** - * Get the isolate this scope belongs to (can be called from any thread, but v8 requires - * the new thread enter the isolate and context. Only one thread can enter the isolate. - */ - v8::Isolate* getIsolate() { - return _isolate; - } - - /** - * Get the JS context this scope executes within. - */ - v8::Persistent<v8::Context> getContext() { - return _context; - } - - /** - * Get the global JS object - */ - v8::Persistent<v8::Object> getGlobal() { - return _global; - } - - ObjTracker<BSONHolder> bsonHolderTracker; - ObjTracker<DBClientBase> dbClientBaseTracker; - // Track both cursor and connection. - // This ensures the connection outlives the cursor. - struct DBConnectionAndCursor { - std::shared_ptr<DBClientBase> conn; - std::shared_ptr<DBClientCursor> cursor; - DBConnectionAndCursor(std::shared_ptr<DBClientBase> conn, - std::shared_ptr<DBClientCursor> cursor) - : conn(conn), cursor(cursor) {} - }; - ObjTracker<DBConnectionAndCursor> dbConnectionAndCursor; - ObjTracker<JSThreadConfig> jsThreadConfigTracker; - - // These are all named after the JS constructor name + FT - v8::Handle<v8::FunctionTemplate> ObjectIdFT() const { - return _ObjectIdFT; - } - v8::Handle<v8::FunctionTemplate> DBRefFT() const { - return _DBRefFT; - } - v8::Handle<v8::FunctionTemplate> DBPointerFT() const { - return _DBPointerFT; - } - v8::Handle<v8::FunctionTemplate> BinDataFT() const { - return _BinDataFT; - } - v8::Handle<v8::FunctionTemplate> NumberLongFT() const { - return _NumberLongFT; - } - v8::Handle<v8::FunctionTemplate> NumberIntFT() const { - return _NumberIntFT; - } - v8::Handle<v8::FunctionTemplate> NumberDecimalFT() const { - return _NumberDecimalFT; - } - v8::Handle<v8::FunctionTemplate> TimestampFT() const { - return _TimestampFT; - } - v8::Handle<v8::FunctionTemplate> MinKeyFT() const { - return _MinKeyFT; - } - v8::Handle<v8::FunctionTemplate> MaxKeyFT() const { - return _MaxKeyFT; - } - v8::Handle<v8::FunctionTemplate> MongoFT() const { - return _MongoFT; - } - v8::Handle<v8::FunctionTemplate> DBFT() const { - return _DBFT; - } - v8::Handle<v8::FunctionTemplate> DBCollectionFT() const { - return _DBCollectionFT; - } - v8::Handle<v8::FunctionTemplate> DBQueryFT() const { - return _DBQueryFT; - } - v8::Handle<v8::FunctionTemplate> InternalCursorFT() const { - return _InternalCursorFT; - } - v8::Handle<v8::FunctionTemplate> LazyBsonFT() const { - return _LazyBsonFT; - } - v8::Handle<v8::FunctionTemplate> ROBsonFT() const { - return _ROBsonFT; - } - - template <size_t N> - v8::Handle<v8::String> strLitToV8(const char(&str)[N]) { - // Note that _strLitMap is keyed on std::string pointer not string - // value. This is OK because each std::string literal has a constant - // pointer for the program's lifetime. This works best if (but does - // not require) the linker interns all std::string literals giving - // identical strings used in different places the same pointer. - - StrLitMap::iterator it = _strLitMap.find(str); - if (it != _strLitMap.end()) - return it->second; - - StringData sd(str, StringData::LiteralTag()); - v8::Handle<v8::String> v8Str = v8StringData(sd); - - // We never need to Dispose since this should last as long as V8Scope exists - _strLitMap[str] = v8::Persistent<v8::String>::New(v8Str); - - return v8Str; - } - -private: - /** - * Recursion limit when converting from JS objects to BSON. - */ - static const int objectDepthLimit = 150; - - /** - * Attach data to obj such that the data has the same lifetime as the Object obj points to. - * obj must have been created by either LazyBsonFT or ROBsonFT. - */ - void wrapBSONObject(v8::Handle<v8::Object> obj, BSONObj data, bool readOnly); - - /** - * Trampoline to call a c++ function with a specific signature (V8Scope*, v8::Arguments&). - * Handles interruption, exceptions, etc. - */ - static v8::Handle<v8::Value> v8Callback(const v8::Arguments& args); - - /** - * Interpreter agnostic 'Native Callback' trampoline. Note this is only called - * from v8Callback(). - */ - static v8::Handle<v8::Value> nativeCallback(V8Scope* scope, const v8::Arguments& args); - - /** - * v8-specific implementations of basic global functions - */ - static v8::Handle<v8::Value> load(V8Scope* scope, const v8::Arguments& args); - static v8::Handle<v8::Value> Print(V8Scope* scope, const v8::Arguments& args); - static v8::Handle<v8::Value> Version(V8Scope* scope, const v8::Arguments& args); - static v8::Handle<v8::Value> GCV8(V8Scope* scope, const v8::Arguments& args); - - static v8::Handle<v8::Value> startCpuProfiler(V8Scope* scope, const v8::Arguments& args); - static v8::Handle<v8::Value> stopCpuProfiler(V8Scope* scope, const v8::Arguments& args); - static v8::Handle<v8::Value> getCpuProfile(V8Scope* scope, const v8::Arguments& args); - - /** Signal that this scope has entered a native (C++) execution context. - * @return false if execution has been interrupted - */ - bool nativePrologue(); - - /** Signal that this scope has completed native execution and is returning to v8. - * @return false if execution has been interrupted - */ - bool nativeEpilogue(); - - /** - * Create a new function; primarily used for BSON/V8 conversion. - */ - v8::Local<v8::Value> newFunction(StringData code); - - template <typename _HandleType> - bool checkV8ErrorState(const _HandleType& resultHandle, - const v8::TryCatch& try_catch, - bool reportError = true, - bool assertOnError = true); - - V8ScriptEngine* _engine; - - v8::Persistent<v8::Context> _context; - v8::Persistent<v8::Object> _global; - std::string _error; - std::vector<v8::Persistent<v8::Value>> _funcs; - - enum ConnectState { NOT, LOCAL, EXTERNAL }; - ConnectState _connectState; - - // These are all named after the JS constructor name + FT - v8::Persistent<v8::FunctionTemplate> _ObjectIdFT; - v8::Persistent<v8::FunctionTemplate> _DBRefFT; - v8::Persistent<v8::FunctionTemplate> _DBPointerFT; - v8::Persistent<v8::FunctionTemplate> _BinDataFT; - v8::Persistent<v8::FunctionTemplate> _NumberLongFT; - v8::Persistent<v8::FunctionTemplate> _NumberIntFT; - v8::Persistent<v8::FunctionTemplate> _NumberDecimalFT; - v8::Persistent<v8::FunctionTemplate> _TimestampFT; - v8::Persistent<v8::FunctionTemplate> _MinKeyFT; - v8::Persistent<v8::FunctionTemplate> _MaxKeyFT; - v8::Persistent<v8::FunctionTemplate> _MongoFT; - v8::Persistent<v8::FunctionTemplate> _DBFT; - v8::Persistent<v8::FunctionTemplate> _DBCollectionFT; - v8::Persistent<v8::FunctionTemplate> _DBQueryFT; - v8::Persistent<v8::FunctionTemplate> _InternalCursorFT; - v8::Persistent<v8::FunctionTemplate> _LazyBsonFT; - v8::Persistent<v8::FunctionTemplate> _ROBsonFT; - - v8::Persistent<v8::Function> _jsRegExpConstructor; - - /// Like v8::Isolate* but calls Dispose() in destructor. - class IsolateHolder { - MONGO_DISALLOW_COPYING(IsolateHolder); - - public: - IsolateHolder() : _isolate(NULL) {} - ~IsolateHolder() { - if (_isolate) { - _isolate->Dispose(); - _isolate = NULL; - } - } - - void set(v8::Isolate* isolate) { - fassert(17184, !_isolate); - _isolate = isolate; - } - - v8::Isolate* operator->() const { - return _isolate; - }; - operator v8::Isolate*() const { - return _isolate; - }; - - private: - v8::Isolate* _isolate; - }; - - IsolateHolder _isolate; // NOTE: this must be destructed before the ObjTrackers - - V8CpuProfiler _cpuProfiler; - - // See comments in strLitToV8 - typedef unordered_map<const char*, v8::Handle<v8::String>> StrLitMap; - StrLitMap _strLitMap; - - stdx::mutex _interruptLock; // protects interruption-related flags - bool _inNativeExecution; // protected by _interruptLock - bool _pendingKill; // protected by _interruptLock - unsigned int _opId; // op id for this scope - OperationContext* _opCtx; // Op context for DbEval -}; - -/// Helper to extract V8Scope for an Isolate -inline V8Scope* getScope(v8::Isolate* isolate) { - return static_cast<V8Scope*>(isolate->GetData()); -} - -class V8ScriptEngine : public ScriptEngine { -public: - V8ScriptEngine(); - virtual ~V8ScriptEngine(); - virtual Scope* createScope() { - return new V8Scope(this); - } - virtual void runTest() {} - bool utf8Ok() const { - return true; - } - - /** - * Interrupt a single active v8 execution context - * NB: To interrupt a context, we must acquire the following locks (in order): - * - mutex to protect the the map of all scopes (_globalInterruptLock) - * - mutex to protect the scope that's being interrupted (_interruptLock) - * The scope will be removed from the map upon destruction, and the op id - * will be updated if the scope is ever reused from a pool. - */ - virtual void interrupt(unsigned opId); - - /** - * Interrupt all v8 contexts (and isolates). @see interrupt(). - */ - virtual void interruptAll(); - -private: - friend class V8Scope; - - std::string printKnownOps_inlock(); - - /** - * Get the deadline monitor instance for the v8 ScriptEngine - */ - DeadlineMonitor<V8Scope>* getDeadlineMonitor() { - return &_deadlineMonitor; - } - - typedef std::map<unsigned, V8Scope*> OpIdToScopeMap; - stdx::mutex _globalInterruptLock; // protects map of all operation ids -> scope - OpIdToScopeMap _opToScopeMap; // map of mongo op ids to scopes (protected by - // _globalInterruptLock). - DeadlineMonitor<V8Scope> _deadlineMonitor; -}; - -class BSONHolder { - MONGO_DISALLOW_COPYING(BSONHolder); - -public: - explicit BSONHolder(BSONObj obj) : _scope(NULL), _obj(obj.getOwned()), _modified(false) { - // give hint v8's GC - v8::V8::AdjustAmountOfExternalAllocatedMemory(_obj.objsize()); - } - ~BSONHolder() { - if (_scope && _scope->getIsolate()) - // if v8 is still up, send hint to GC - v8::V8::AdjustAmountOfExternalAllocatedMemory(-_obj.objsize()); - } - V8Scope* _scope; - BSONObj _obj; - bool _modified; - bool _readOnly; - std::set<std::string> _removed; -}; - -extern ScriptEngine* globalScriptEngine; -} |