diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2017-08-17 14:21:57 -0400 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2017-08-17 14:21:57 -0400 |
commit | 4cb5071ecb94d0789392b1748b49388099a8a2ec (patch) | |
tree | 2d1725f70e278da924ae4019f3f7f86be7e4771d | |
parent | 66e2805eb1c5d130ae37ef4f72bc19b8db0fc8dc (diff) | |
download | mongo-4cb5071ecb94d0789392b1748b49388099a8a2ec.tar.gz |
SERVER-30362 MozJS - implement resolve instead of getProperty for native types
-rw-r--r-- | jstests/core/js_jit.js | 40 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/db.cpp | 33 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/db.h | 5 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/dbcollection.cpp | 10 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/dbcollection.h | 5 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/dbquery.cpp | 25 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/dbquery.h | 6 |
7 files changed, 79 insertions, 45 deletions
diff --git a/jstests/core/js_jit.js b/jstests/core/js_jit.js new file mode 100644 index 00000000000..4ccdd2917ae --- /dev/null +++ b/jstests/core/js_jit.js @@ -0,0 +1,40 @@ +/** + * Validate various native types continue to work when run in JITed code. + * + * In SERVER-30362, the JIT would not compile natives types which had custom getProperty + * implementations correctly. We force the JIT to kick in by using large loops. + */ +(function() { + 'use strict'; + + function testDBCollection() { + const c = new DBCollection(null, null, "foo", "test.foo"); + for (let i = 0; i < 100000; i++) { + if (c.toString() != "test.foo") { + throw i; + } + } + } + + function testDB() { + const c = new DB(null, "test"); + for (let i = 0; i < 100000; i++) { + if (c.toString() != "test") { + throw i; + } + } + } + + function testDBQuery() { + const c = DBQuery('a', 'b', 'c', 'd'); + for (let i = 0; i < 100000; i++) { + if (c.toString() != "DBQuery: d -> null") { + throw i; + } + } + } + + testDBCollection(); + testDB(); + testDBQuery(); +})();
\ No newline at end of file diff --git a/src/mongo/scripting/mozjs/db.cpp b/src/mongo/scripting/mozjs/db.cpp index aa886830556..7a7877e012b 100644 --- a/src/mongo/scripting/mozjs/db.cpp +++ b/src/mongo/scripting/mozjs/db.cpp @@ -44,30 +44,25 @@ namespace mozjs { const char* const DBInfo::className = "DB"; -void DBInfo::getProperty(JSContext* cx, - JS::HandleObject obj, - JS::HandleId id, - JS::MutableHandleValue vp) { - // 2nd look into real values, may be cached collection object - if (!vp.isUndefined()) { - auto scope = getScope(cx); - auto opContext = scope->getOpContext(); - - if (opContext && vp.isObject()) { - ObjectWrapper o(cx, vp); - } +void DBInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) { + *resolvedp = false; - return; - } + JS::RootedValue coll(cx); JS::RootedObject parent(cx); if (!JS_GetPrototype(cx, obj, &parent)) uasserted(ErrorCodes::JSInterpreterFailure, "Couldn't get prototype"); ObjectWrapper parentWrapper(cx, parent); + ObjectWrapper o(cx, obj); + // Check if this exists on the parent, ie. DBCollection::resolve case if (parentWrapper.hasOwnField(id)) { - parentWrapper.getValue(id, vp); + parentWrapper.getValue(id, &coll); + + o.defineProperty(id, coll, 0); + + *resolvedp = true; return; } @@ -86,15 +81,17 @@ void DBInfo::getProperty(JSContext* cx, JS::RootedValue getCollection(cx); parentWrapper.getValue(InternedString::getCollection, &getCollection); + // Check if getCollection has been installed yet + // It is undefined if the user has a db name the same as one of methods/properties of the DB + // object. if (!(getCollection.isObject() && JS_ObjectIsFunction(cx, getCollection.toObjectOrNull()))) { - uasserted(ErrorCodes::BadValue, "getCollection is not a function"); + return; } JS::AutoValueArray<1> args(cx); idw.toValue(args[0]); - JS::RootedValue coll(cx); ObjectWrapper(cx, obj).callMethod(getCollection, args, &coll); uassert(16861, @@ -104,7 +101,7 @@ void DBInfo::getProperty(JSContext* cx, // cache collection for reuse, don't enumerate ObjectWrapper(cx, obj).defineProperty(id, coll, 0); - vp.set(coll); + *resolvedp = true; } void DBInfo::construct(JSContext* cx, JS::CallArgs args) { diff --git a/src/mongo/scripting/mozjs/db.h b/src/mongo/scripting/mozjs/db.h index c752953236f..8f080265ef0 100644 --- a/src/mongo/scripting/mozjs/db.h +++ b/src/mongo/scripting/mozjs/db.h @@ -44,10 +44,7 @@ namespace mozjs { */ struct DBInfo : public BaseInfo { static void construct(JSContext* cx, JS::CallArgs args); - static void getProperty(JSContext* cx, - JS::HandleObject obj, - JS::HandleId id, - JS::MutableHandleValue vp); + static void resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp); static const char* const className; }; diff --git a/src/mongo/scripting/mozjs/dbcollection.cpp b/src/mongo/scripting/mozjs/dbcollection.cpp index 1de0f49212f..e06b063b23a 100644 --- a/src/mongo/scripting/mozjs/dbcollection.cpp +++ b/src/mongo/scripting/mozjs/dbcollection.cpp @@ -43,11 +43,11 @@ namespace mozjs { const char* const DBCollectionInfo::className = "DBCollection"; -void DBCollectionInfo::getProperty(JSContext* cx, - JS::HandleObject obj, - JS::HandleId id, - JS::MutableHandleValue vp) { - DBInfo::getProperty(cx, obj, id, vp); +void DBCollectionInfo::resolve(JSContext* cx, + JS::HandleObject obj, + JS::HandleId id, + bool* resolvedp) { + DBInfo::resolve(cx, obj, id, resolvedp); } void DBCollectionInfo::construct(JSContext* cx, JS::CallArgs args) { diff --git a/src/mongo/scripting/mozjs/dbcollection.h b/src/mongo/scripting/mozjs/dbcollection.h index 34be422dfd4..ed3c39ff0f2 100644 --- a/src/mongo/scripting/mozjs/dbcollection.h +++ b/src/mongo/scripting/mozjs/dbcollection.h @@ -44,10 +44,7 @@ namespace mozjs { */ struct DBCollectionInfo : public BaseInfo { static void construct(JSContext* cx, JS::CallArgs args); - static void getProperty(JSContext* cx, - JS::HandleObject obj, - JS::HandleId id, - JS::MutableHandleValue vp); + static void resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp); static const char* const className; }; diff --git a/src/mongo/scripting/mozjs/dbquery.cpp b/src/mongo/scripting/mozjs/dbquery.cpp index c2543814505..15bd45bde3c 100644 --- a/src/mongo/scripting/mozjs/dbquery.cpp +++ b/src/mongo/scripting/mozjs/dbquery.cpp @@ -105,13 +105,8 @@ void DBQueryInfo::construct(JSContext* cx, JS::CallArgs args) { args.rval().setObjectOrNull(thisv); } -void DBQueryInfo::getProperty(JSContext* cx, - JS::HandleObject obj, - JS::HandleId id, - JS::MutableHandleValue vp) { - if (!vp.isUndefined()) { - return; - } +void DBQueryInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) { + *resolvedp = false; IdWrapper wid(cx, id); @@ -134,9 +129,19 @@ void DBQueryInfo::getProperty(JSContext* cx, args[0].setInt32(wid.toInt32()); - ObjectWrapper(cx, obj).callMethod(arrayAccess, args, vp); - } else { - uasserted(ErrorCodes::BadValue, "arrayAccess is not a function"); + JS::RootedValue vp(cx); + + ObjectWrapper(cx, obj).callMethod(arrayAccess, args, &vp); + + if (!vp.isNullOrUndefined()) { + ObjectWrapper o(cx, obj); + + // Assumes the user won't modify the contents of what DBQuery::arrayAccess returns + // otherwise we need to install a getter. + o.defineProperty(id, vp, 0); + } + + *resolvedp = true; } } diff --git a/src/mongo/scripting/mozjs/dbquery.h b/src/mongo/scripting/mozjs/dbquery.h index dc844c3084c..590185c55ee 100644 --- a/src/mongo/scripting/mozjs/dbquery.h +++ b/src/mongo/scripting/mozjs/dbquery.h @@ -41,10 +41,8 @@ namespace mozjs { */ struct DBQueryInfo : public BaseInfo { static void construct(JSContext* cx, JS::CallArgs args); - static void getProperty(JSContext* cx, - JS::HandleObject obj, - JS::HandleId id, - JS::MutableHandleValue vp); + static void resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp); + static const char* const className; }; |