diff options
author | Anna Henningsen <anna@addaleax.net> | 2018-12-31 00:59:25 +0100 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2019-01-02 14:46:13 +0100 |
commit | 112ee2ab071da24390515b3a91588c1590872498 (patch) | |
tree | e173534964a2ee8344524c4f7c88751d834379f6 | |
parent | 2370bc7143211d860fc14e710cc8400fb4004bed (diff) | |
download | android-node-v8-112ee2ab071da24390515b3a91588c1590872498.tar.gz android-node-v8-112ee2ab071da24390515b3a91588c1590872498.tar.bz2 android-node-v8-112ee2ab071da24390515b3a91588c1590872498.zip |
src: improve ToV8Value() functions
- Cache the `isolate` value between calls
- Introduce an overload for dealing with integers/numbers
- Use the vectored `v8::Array::New` constructor + `MaybeStackBuffer`
for faster array creation
PR-URL: https://github.com/nodejs/node/pull/25288
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
-rw-r--r-- | src/util-inl.h | 55 | ||||
-rw-r--r-- | src/util.h | 15 |
2 files changed, 53 insertions, 17 deletions
diff --git a/src/util-inl.h b/src/util-inl.h index acd370e235..6d612f1eb7 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -377,8 +377,9 @@ inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<char>(n); } void ThrowErrStringTooLong(v8::Isolate* isolate); v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, - const std::string& str) { - v8::Isolate* isolate = context->GetIsolate(); + const std::string& str, + v8::Isolate* isolate) { + if (isolate == nullptr) isolate = context->GetIsolate(); if (UNLIKELY(str.size() >= static_cast<size_t>(v8::String::kMaxLength))) { // V8 only has a TODO comment about adding an exception when the maximum // string size is exceeded. @@ -393,33 +394,33 @@ v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, template <typename T> v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, - const std::vector<T>& vec) { - v8::Isolate* isolate = context->GetIsolate(); + const std::vector<T>& vec, + v8::Isolate* isolate) { + if (isolate == nullptr) isolate = context->GetIsolate(); v8::EscapableHandleScope handle_scope(isolate); - v8::Local<v8::Array> arr = v8::Array::New(isolate, vec.size()); + MaybeStackBuffer<v8::Local<v8::Value>, 128> arr(vec.size()); + arr.SetLength(vec.size()); for (size_t i = 0; i < vec.size(); ++i) { - v8::Local<v8::Value> val; - if (!ToV8Value(context, vec[i]).ToLocal(&val) || - arr->Set(context, i, val).IsNothing()) { + if (!ToV8Value(context, vec[i], isolate).ToLocal(&arr[i])) return v8::MaybeLocal<v8::Value>(); - } } - return handle_scope.Escape(arr); + return handle_scope.Escape(v8::Array::New(isolate, arr.out(), arr.length())); } template <typename T, typename U> v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, - const std::unordered_map<T, U>& map) { - v8::Isolate* isolate = context->GetIsolate(); + const std::unordered_map<T, U>& map, + v8::Isolate* isolate) { + if (isolate == nullptr) isolate = context->GetIsolate(); v8::EscapableHandleScope handle_scope(isolate); v8::Local<v8::Map> ret = v8::Map::New(isolate); for (const auto& item : map) { v8::Local<v8::Value> first, second; - if (!ToV8Value(context, item.first).ToLocal(&first) || - !ToV8Value(context, item.second).ToLocal(&second) || + if (!ToV8Value(context, item.first, isolate).ToLocal(&first) || + !ToV8Value(context, item.second, isolate).ToLocal(&second) || ret->Set(context, first, second).IsEmpty()) { return v8::MaybeLocal<v8::Value>(); } @@ -428,6 +429,32 @@ v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, return handle_scope.Escape(ret); } +template <typename T, typename > +v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, + const T& number, + v8::Isolate* isolate) { + if (isolate == nullptr) isolate = context->GetIsolate(); + + using Limits = std::numeric_limits<T>; + // Choose Uint32, Int32, or Double depending on range checks. + // These checks should all collapse at compile time. + if (static_cast<uint32_t>(Limits::max()) <= + std::numeric_limits<uint32_t>::max() && + static_cast<uint32_t>(Limits::min()) >= + std::numeric_limits<uint32_t>::min() && Limits::is_exact) { + return v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(number)); + } + + if (static_cast<int32_t>(Limits::max()) <= + std::numeric_limits<int32_t>::max() && + static_cast<int32_t>(Limits::min()) >= + std::numeric_limits<int32_t>::min() && Limits::is_exact) { + return v8::Integer::New(isolate, static_cast<int32_t>(number)); + } + + return v8::Number::New(isolate, static_cast<double>(number)); +} + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/util.h b/src/util.h index 2db87c18b0..ffa5a308a7 100644 --- a/src/util.h +++ b/src/util.h @@ -35,6 +35,7 @@ #include <string.h> #include <functional> // std::function +#include <limits> #include <set> #include <string> #include <array> @@ -519,13 +520,21 @@ using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer; std::set<std::string> ParseCommaSeparatedSet(const std::string& in); inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, - const std::string& str); + const std::string& str, + v8::Isolate* isolate = nullptr); +template <typename T, typename test_for_number = + typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type> +inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, + const T& number, + v8::Isolate* isolate = nullptr); template <typename T> inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, - const std::vector<T>& vec); + const std::vector<T>& vec, + v8::Isolate* isolate = nullptr); template <typename T, typename U> inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, - const std::unordered_map<T, U>& map); + const std::unordered_map<T, U>& map, + v8::Isolate* isolate = nullptr); // These macros expects a `Isolate* isolate` and a `Local<Context> context` // to be in the scope. |