summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Carey <jcarey@argv.me>2015-10-06 20:23:08 -0400
committerJason Carey <jcarey@argv.me>2015-10-06 20:26:14 -0400
commit8d65462cd4b56fd12d3fbe8799ee78be677bae38 (patch)
treef86313611afb4c9e4e5e04238f0e88f830ed49c2 /src
parent95060c27ed2dddcb6343a88f7aa405ed8a935ad7 (diff)
downloadmongo-8d65462cd4b56fd12d3fbe8799ee78be677bae38.tar.gz
SERVER-19977 Offer a stack based JSStringWrapper
Small string optimization for encoding utf8 strings from JS strings on the stack. Additions to the api to use on stack buffers.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/scripting/mozjs/bson.cpp7
-rw-r--r--src/mongo/scripting/mozjs/idwrapper.cpp11
-rw-r--r--src/mongo/scripting/mozjs/idwrapper.h2
-rw-r--r--src/mongo/scripting/mozjs/jsstringwrapper.cpp29
-rw-r--r--src/mongo/scripting/mozjs/jsstringwrapper.h4
-rw-r--r--src/mongo/scripting/mozjs/objectwrapper.cpp51
-rw-r--r--src/mongo/scripting/mozjs/objectwrapper.h2
-rw-r--r--src/mongo/scripting/mozjs/valuewriter.cpp11
-rw-r--r--src/mongo/scripting/mozjs/valuewriter.h1
9 files changed, 82 insertions, 36 deletions
diff --git a/src/mongo/scripting/mozjs/bson.cpp b/src/mongo/scripting/mozjs/bson.cpp
index f2c30407845..9f0a6125d22 100644
--- a/src/mongo/scripting/mozjs/bson.cpp
+++ b/src/mongo/scripting/mozjs/bson.cpp
@@ -194,15 +194,16 @@ void BSONInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, boo
}
IdWrapper idw(cx, id);
+ JSStringWrapper jsstr;
- if (!holder->_readOnly && holder->_removed.count(idw.toString())) {
+ auto sname = idw.toStringData(&jsstr);
+
+ if (!holder->_readOnly && holder->_removed.find(sname.toString()) != holder->_removed.end()) {
return;
}
ObjectWrapper o(cx, obj);
- std::string sname = IdWrapper(cx, id).toString();
-
if (holder->_obj.hasField(sname)) {
auto elem = holder->_obj[sname];
diff --git a/src/mongo/scripting/mozjs/idwrapper.cpp b/src/mongo/scripting/mozjs/idwrapper.cpp
index 2c701037a22..89c24807d53 100644
--- a/src/mongo/scripting/mozjs/idwrapper.cpp
+++ b/src/mongo/scripting/mozjs/idwrapper.cpp
@@ -41,15 +41,22 @@ namespace mozjs {
IdWrapper::IdWrapper(JSContext* cx, JS::HandleId value) : _context(cx), _value(cx, value) {}
std::string IdWrapper::toString() const {
+ JSStringWrapper jsstr;
+ return toStringData(&jsstr).toString();
+}
+
+StringData IdWrapper::toStringData(JSStringWrapper* jsstr) const {
if (JSID_IS_STRING(_value)) {
- return JSStringWrapper(_context, JSID_TO_STRING(_value)).toString();
+ *jsstr = JSStringWrapper(_context, JSID_TO_STRING(_value));
} else if (JSID_IS_INT(_value)) {
- return std::to_string(JSID_TO_INT(_value));
+ *jsstr = JSStringWrapper(JSID_TO_INT(_value));
} else {
throwCurrentJSException(_context,
ErrorCodes::TypeMismatch,
"Cannot toString() non-string and non-integer jsid");
}
+
+ return jsstr->toStringData();
}
uint32_t IdWrapper::toInt32() const {
diff --git a/src/mongo/scripting/mozjs/idwrapper.h b/src/mongo/scripting/mozjs/idwrapper.h
index 4865e5e0aec..0ba380c64cb 100644
--- a/src/mongo/scripting/mozjs/idwrapper.h
+++ b/src/mongo/scripting/mozjs/idwrapper.h
@@ -32,6 +32,7 @@
#include <string>
#include "mongo/base/string_data.h"
+#include "mongo/scripting/mozjs/jsstringwrapper.h"
namespace mongo {
namespace mozjs {
@@ -51,6 +52,7 @@ public:
* Converts to a string. This coerces for integers
*/
std::string toString() const;
+ StringData toStringData(JSStringWrapper* jsstr) const;
/**
* Converts to an int. This throws if the id is not an integer
diff --git a/src/mongo/scripting/mozjs/jsstringwrapper.cpp b/src/mongo/scripting/mozjs/jsstringwrapper.cpp
index 8261b44a2fe..2732c98607b 100644
--- a/src/mongo/scripting/mozjs/jsstringwrapper.cpp
+++ b/src/mongo/scripting/mozjs/jsstringwrapper.cpp
@@ -41,7 +41,11 @@
namespace mongo {
namespace mozjs {
-JSStringWrapper::JSStringWrapper(JSContext* cx, JSString* str) : _context(cx) {
+JSStringWrapper::JSStringWrapper(std::int32_t value) : _isSet(true) {
+ _length = sprintf(_buf, "%d", value);
+}
+
+JSStringWrapper::JSStringWrapper(JSContext* cx, JSString* str) : _isSet(true) {
if (!str)
throwCurrentJSException(cx, ErrorCodes::InternalError, "Cannot encode null JSString");
@@ -56,20 +60,21 @@ JSStringWrapper::JSStringWrapper(JSContext* cx, JSString* str) : _context(cx) {
_length = JS::GetDeflatedUTF8StringLength(flat);
- JS::RootedString rstr(cx, str);
-
- JSAutoByteString abs;
- abs.encodeUtf8(cx, rstr);
-
- if (!abs)
- throwCurrentJSException(cx, ErrorCodes::InternalError, "Failed to encode JSString");
+ char* out;
+ if (_length < sizeof(_buf)) {
+ out = _buf;
+ } else {
+ _str.reset(new char[_length + 1]);
+ out = _str.get();
+ }
- _str.reset(new char[_length]);
- std::memcpy(_str.get(), abs.ptr(), _length);
+ JS::DeflateStringToUTF8Buffer(flat, mozilla::RangedPtr<char>(out, _length));
+ out[_length] = '\0';
}
StringData JSStringWrapper::toStringData() const {
- return StringData(_str.get(), _length);
+ invariant(_isSet);
+ return StringData(_str ? _str.get() : _buf, _length);
}
std::string JSStringWrapper::toString() const {
@@ -77,7 +82,7 @@ std::string JSStringWrapper::toString() const {
}
JSStringWrapper::operator bool() const {
- return _str.get();
+ return _isSet;
}
} // namespace mozjs
diff --git a/src/mongo/scripting/mozjs/jsstringwrapper.h b/src/mongo/scripting/mozjs/jsstringwrapper.h
index 9a0ee21e900..ec94593bd05 100644
--- a/src/mongo/scripting/mozjs/jsstringwrapper.h
+++ b/src/mongo/scripting/mozjs/jsstringwrapper.h
@@ -45,6 +45,7 @@ class JSStringWrapper {
public:
JSStringWrapper() = default;
JSStringWrapper(JSContext* cx, JSString* str);
+ JSStringWrapper(std::int32_t val);
StringData toStringData() const;
std::string toString() const;
@@ -52,9 +53,10 @@ public:
explicit operator bool() const;
private:
- JSContext* _context = nullptr;
std::unique_ptr<char[]> _str;
size_t _length = 0;
+ char _buf[64];
+ bool _isSet = false;
};
} // namespace mozjs
diff --git a/src/mongo/scripting/mozjs/objectwrapper.cpp b/src/mongo/scripting/mozjs/objectwrapper.cpp
index 8e1bc5aa92e..e467dfe8b48 100644
--- a/src/mongo/scripting/mozjs/objectwrapper.cpp
+++ b/src/mongo/scripting/mozjs/objectwrapper.cpp
@@ -198,23 +198,40 @@ void ObjectWrapper::Key::del(JSContext* cx, JS::HandleObject o) {
}
std::string ObjectWrapper::Key::toString(JSContext* cx) {
- switch (_type) {
- case Type::Field:
- return _field;
- case Type::Index:
- return std::to_string(_idx);
- case Type::Id: {
- JS::RootedId id(cx, _id);
- return IdWrapper(cx, id).toString();
- }
- case Type::InternedString: {
- InternedStringId id(cx, _internedString);
- return IdWrapper(cx, id).toString();
- }
+ JSStringWrapper jsstr;
+ return toStringData(cx, &jsstr).toString();
+}
+
+StringData ObjectWrapper::Key::toStringData(JSContext* cx, JSStringWrapper* jsstr) {
+ if (_type == Type::Field) {
+ return _field;
}
- throwCurrentJSException(
- cx, ErrorCodes::InternalError, "Failed to toString a ObjectWrapper::Key");
+ if (_type == Type::Index) {
+ *jsstr = JSStringWrapper(_idx);
+ return jsstr->toStringData();
+ }
+
+ JS::RootedId rid(cx);
+
+ if (_type == Type::Id) {
+ rid.set(_id);
+ } else {
+ InternedStringId id(cx, _internedString);
+ rid.set(id);
+ }
+
+ if (JSID_IS_INT(rid)) {
+ *jsstr = JSStringWrapper(JSID_TO_INT(rid));
+ return jsstr->toStringData();
+ }
+
+ if (JSID_IS_STRING(rid)) {
+ *jsstr = JSStringWrapper(cx, JSID_TO_STRING(rid));
+ return jsstr->toStringData();
+ }
+
+ uasserted(ErrorCodes::BadValue, "Couldn't convert key to String");
}
ObjectWrapper::ObjectWrapper(JSContext* cx, JS::HandleObject obj)
@@ -500,7 +517,9 @@ void ObjectWrapper::_writeField(BSONObjBuilder* b,
ValueWriter x(_context, value);
x.setOriginalBSON(originalParent);
- x.writeThis(b, key.toString(_context), frames);
+ JSStringWrapper jsstr;
+
+ x.writeThis(b, key.toStringData(_context, &jsstr), frames);
}
std::string ObjectWrapper::getClassName() {
diff --git a/src/mongo/scripting/mozjs/objectwrapper.h b/src/mongo/scripting/mozjs/objectwrapper.h
index efc8039bf26..4463cd99c98 100644
--- a/src/mongo/scripting/mozjs/objectwrapper.h
+++ b/src/mongo/scripting/mozjs/objectwrapper.h
@@ -35,6 +35,7 @@
#include "mongo/platform/decimal128.h"
#include "mongo/scripting/mozjs/exception.h"
#include "mongo/scripting/mozjs/internedstring.h"
+#include "mongo/scripting/mozjs/jsstringwrapper.h"
#include "mongo/scripting/mozjs/lifetimestack.h"
namespace mongo {
@@ -85,6 +86,7 @@ public:
void define(JSContext* cx, JS::HandleObject o, JS::HandleValue value, unsigned attrs);
void del(JSContext* cx, JS::HandleObject o);
std::string toString(JSContext* cx);
+ StringData toStringData(JSContext* cx, JSStringWrapper* jsstr);
union {
const char* _field;
diff --git a/src/mongo/scripting/mozjs/valuewriter.cpp b/src/mongo/scripting/mozjs/valuewriter.cpp
index 6f57d48c460..33097e99e18 100644
--- a/src/mongo/scripting/mozjs/valuewriter.cpp
+++ b/src/mongo/scripting/mozjs/valuewriter.cpp
@@ -121,7 +121,13 @@ BSONObj ValueWriter::toBSON() {
}
std::string ValueWriter::toString() {
- return JSStringWrapper(_context, JS::ToString(_context, _value)).toString();
+ JSStringWrapper jsstr;
+ return toStringData(&jsstr).toString();
+}
+
+StringData ValueWriter::toStringData(JSStringWrapper* jsstr) {
+ *jsstr = JSStringWrapper(_context, JS::ToString(_context, _value));
+ return jsstr->toStringData();
}
double ValueWriter::toNumber() {
@@ -192,7 +198,8 @@ void ValueWriter::writeThis(BSONObjBuilder* b,
(std::string::npos == sd.find('\0')));
if (_value.isString()) {
- b->append(sd, toString());
+ JSStringWrapper jsstr;
+ b->append(sd, toStringData(&jsstr));
} else if (_value.isNumber()) {
double val = toNumber();
diff --git a/src/mongo/scripting/mozjs/valuewriter.h b/src/mongo/scripting/mozjs/valuewriter.h
index 65f6f418d09..9947f61d741 100644
--- a/src/mongo/scripting/mozjs/valuewriter.h
+++ b/src/mongo/scripting/mozjs/valuewriter.h
@@ -54,6 +54,7 @@ public:
* toNumber()
*/
std::string toString();
+ StringData toStringData(JSStringWrapper* jsstr);
int type();
double toNumber();
int32_t toInt32();