summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2017-08-17 14:21:57 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2017-08-17 14:21:57 -0400
commit4cb5071ecb94d0789392b1748b49388099a8a2ec (patch)
tree2d1725f70e278da924ae4019f3f7f86be7e4771d
parent66e2805eb1c5d130ae37ef4f72bc19b8db0fc8dc (diff)
downloadmongo-4cb5071ecb94d0789392b1748b49388099a8a2ec.tar.gz
SERVER-30362 MozJS - implement resolve instead of getProperty for native types
-rw-r--r--jstests/core/js_jit.js40
-rw-r--r--src/mongo/scripting/mozjs/db.cpp33
-rw-r--r--src/mongo/scripting/mozjs/db.h5
-rw-r--r--src/mongo/scripting/mozjs/dbcollection.cpp10
-rw-r--r--src/mongo/scripting/mozjs/dbcollection.h5
-rw-r--r--src/mongo/scripting/mozjs/dbquery.cpp25
-rw-r--r--src/mongo/scripting/mozjs/dbquery.h6
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;
};