From 8b9cd84df7ea6ff460f9c79f4d648c9de8d88945 Mon Sep 17 00:00:00 2001 From: ksuprynowicz Date: Sat, 1 Apr 2023 19:51:21 +0200 Subject: [PATCH] vec3ToScriptValue optimizations --- .../script-engine/src/ScriptValueUtils.cpp | 35 ++-------- .../src/v8/FastScriptValueUtils.cpp | 65 ++++++++++++++++--- .../src/v8/FastScriptValueUtils.h | 12 +++- .../script-engine/src/v8/ScriptEngineV8.cpp | 12 ++-- 4 files changed, 77 insertions(+), 47 deletions(-) diff --git a/libraries/script-engine/src/ScriptValueUtils.cpp b/libraries/script-engine/src/ScriptValueUtils.cpp index 4929093821..c081a67925 100644 --- a/libraries/script-engine/src/ScriptValueUtils.cpp +++ b/libraries/script-engine/src/ScriptValueUtils.cpp @@ -33,12 +33,7 @@ #include "ScriptEngineCast.h" #include "ScriptValueIterator.h" #include "ScriptEngineLogging.h" - -#define CONVERSIONS_OPTIMIZED_FOR_V8 - -#ifdef CONVERSIONS_OPTIMIZED_FOR_V8 #include "v8/FastScriptValueUtils.h" -#endif bool isListOfStrings(const ScriptValue& arg) { if (!arg.isArray()) { @@ -65,11 +60,7 @@ void registerMetaTypes(ScriptEngine* engine) { scriptRegisterMetaType(engine); scriptRegisterMetaType(engine); -#ifdef CONVERSIONS_OPTIMIZED_FOR_V8 - scriptRegisterMetaType(engine); -#else scriptRegisterMetaType(engine); -#endif scriptRegisterMetaType(engine); scriptRegisterMetaType(engine); scriptRegisterMetaType(engine); @@ -127,11 +118,7 @@ bool qVector2DFromScriptValue(const ScriptValue& object, QVector2D& qVector2D) { ScriptValue qVector3DToScriptValue(ScriptEngine* engine, const QVector3D& qVector3D) { glm::vec3 vec3(qVector3D.x(), qVector3D.y(), qVector3D.z()); -#ifdef CONVERSIONS_OPTIMIZED_FOR_V8 - return vec3ToScriptValueFast(engine, vec3); -#else return vec3ToScriptValue(engine, vec3); -#endif } bool qVector3DFromScriptValue(const ScriptValue& object, QVector3D& qVector3D) { @@ -191,6 +178,7 @@ bool vec2FromScriptValue(const ScriptValue& object, glm::vec2& vec2) { return true; } +#ifndef CONVERSIONS_OPTIMIZED_FOR_V8 ScriptValue vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) { auto prototype = engine->globalObject().property("__hifi_vec3__"); if (!prototype.hasProperty("defined") || !prototype.property("defined").toBool()) { @@ -215,6 +203,7 @@ ScriptValue vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) { value.setPrototype(prototype); return value; } +#endif ScriptValue vec3ColorToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) { auto prototype = engine->globalObject().property("__hifi_vec3_color__"); @@ -242,6 +231,7 @@ ScriptValue vec3ColorToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) } // V8TODO: add similar checks to rest of the conversions +#ifndef CONVERSIONS_OPTIMIZED_FOR_V8 bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) { if (object.isNumber()) { vec3 = glm::vec3(object.toVariant().toFloat()); @@ -301,6 +291,7 @@ bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) { } return true; } +#endif ScriptValue u8vec3ToScriptValue(ScriptEngine* engine, const glm::u8vec3& vec3) { auto prototype = engine->globalObject().property("__hifi_u8vec3__"); @@ -470,11 +461,7 @@ ScriptValue qVectorVec3ColorToScriptValue(ScriptEngine* engine, const QVector& vector) { ScriptValue array = engine->newArray(); for (int i = 0; i < vector.size(); i++) { -#ifdef CONVERSIONS_OPTIMIZED_FOR_V8 - array.setProperty(i, vec3ToScriptValueFast(engine, vector.at(i))); -#else array.setProperty(i, vec3ToScriptValue(engine, vector.at(i))); -#endif } return array; } @@ -794,17 +781,9 @@ bool qURLFromScriptValue(const ScriptValue& object, QUrl& url) { ScriptValue pickRayToScriptValue(ScriptEngine* engine, const PickRay& pickRay) { ScriptValue obj = engine->newObject(); -#ifdef CONVERSIONS_OPTIMIZED_FOR_V8 - ScriptValue origin = vec3ToScriptValueFast(engine, pickRay.origin); -#else ScriptValue origin = vec3ToScriptValue(engine, pickRay.origin); -#endif obj.setProperty("origin", origin); -#ifdef CONVERSIONS_OPTIMIZED_FOR_V8 - ScriptValue direction = vec3ToScriptValueFast(engine, pickRay.direction); -#else ScriptValue direction = vec3ToScriptValue(engine, pickRay.direction); -#endif obj.setProperty("direction", direction); return obj; } @@ -850,15 +829,9 @@ ScriptValue collisionToScriptValue(ScriptEngine* engine, const Collision& collis obj.setProperty("type", collision.type); obj.setProperty("idA", quuidToScriptValue(engine, collision.idA)); obj.setProperty("idB", quuidToScriptValue(engine, collision.idB)); -#ifdef CONVERSIONS_OPTIMIZED_FOR_V8 - obj.setProperty("penetration", vec3ToScriptValueFast(engine, collision.penetration)); - obj.setProperty("contactPoint", vec3ToScriptValueFast(engine, collision.contactPoint)); - obj.setProperty("velocityChange", vec3ToScriptValueFast(engine, collision.velocityChange)); -#else obj.setProperty("penetration", vec3ToScriptValue(engine, collision.penetration)); obj.setProperty("contactPoint", vec3ToScriptValue(engine, collision.contactPoint)); obj.setProperty("velocityChange", vec3ToScriptValue(engine, collision.velocityChange)); -#endif return obj; } diff --git a/libraries/script-engine/src/v8/FastScriptValueUtils.cpp b/libraries/script-engine/src/v8/FastScriptValueUtils.cpp index f5b5f44c37..130ac1f7b8 100644 --- a/libraries/script-engine/src/v8/FastScriptValueUtils.cpp +++ b/libraries/script-engine/src/v8/FastScriptValueUtils.cpp @@ -17,9 +17,11 @@ #include "V8Types.h" #include "ScriptValueV8Wrapper.h" -ScriptValue vec3ToScriptValueFast(ScriptEngine* engine, const glm::vec3& vec3) { - auto prototype = engine->globalObject().property("__hifi_vec3__"); - if (!prototype.hasProperty("defined") || !prototype.property("defined").toBool()) { +#ifdef CONVERSIONS_OPTIMIZED_FOR_V8 + +ScriptValue vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) { + //auto prototype = engine->globalObject().property("__hifi_vec3__"); + /*if (!prototype.hasProperty("defined") || !prototype.property("defined").toBool()) { prototype = engine->evaluate( "__hifi_vec3__ = Object.defineProperties({}, { " "defined: { value: true }," @@ -33,7 +35,7 @@ ScriptValue vec3ToScriptValueFast(ScriptEngine* engine, const glm::vec3& vec3) { "green: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } }," "blue: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } }" "})"); - } + }*/ ScriptValue value = engine->newObject(); ScriptValueV8Wrapper *proxy = ScriptValueV8Wrapper::unwrap(value); @@ -49,6 +51,51 @@ ScriptValue vec3ToScriptValueFast(ScriptEngine* engine, const glm::vec3& vec3) { V8ScriptValue v8ScriptValue = proxy->toV8Value(); v8::Local v8Object = v8::Local::Cast(v8ScriptValue.get()); + v8::Local prototype; + bool hasPrototype = false; + + if (context->Global()->Get(context, v8::String::NewFromUtf8(isolate, "__hifi_vec3__").ToLocalChecked()).ToLocal(&prototype)) { + if (!prototype->IsNullOrUndefined() && prototype->IsObject()) { + v8::Local prototypeObject = v8::Local::Cast(prototype); + v8::Local isDefined; + if (prototypeObject->Get(context, v8::String::NewFromUtf8(isolate, "defined").ToLocalChecked()).ToLocal(&isDefined)) { + if ((!isDefined->IsNullOrUndefined()) && isDefined->BooleanValue(isolate)) { + hasPrototype = true; + } + } + } + } + + if (!hasPrototype) { + QString sourceCode("globalThis.__hifi_vec3__ = Object.defineProperties({}, { " + "defined: { value: true }," + "0: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } }," + "1: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } }," + "2: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } }," + "r: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } }," + "g: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } }," + "b: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } }," + "red: { set: function(nv) { return this.x = nv; }, get: function() { return this.x; } }," + "green: { set: function(nv) { return this.y = nv; }, get: function() { return this.y; } }," + "blue: { set: function(nv) { return this.z = nv; }, get: function() { return this.z; } }" + "})"); + v8::TryCatch tryCatch(isolate); + v8::ScriptOrigin scriptOrigin(isolate, v8::String::NewFromUtf8(isolate, "Vec3prototype").ToLocalChecked()); + v8::Local script; + if (!v8::Script::Compile(context, v8::String::NewFromUtf8(isolate, sourceCode.toStdString().c_str()).ToLocalChecked(), &scriptOrigin).ToLocal(&script)) { + Q_ASSERT(false); + } + v8::Local result; + if (!script->Run(context).ToLocal(&result)) { + Q_ASSERT(false); + } + if (!context->Global()->Get(context, v8::String::NewFromUtf8(isolate, "__hifi_vec3__").ToLocalChecked()).ToLocal(&prototype)) { + Q_ASSERT(false); + } + Q_ASSERT(!tryCatch.HasCaught()); + qDebug() <<"vec3ToScriptValue: creating prototype"; + } + if (!v8Object->Set(context, v8::String::NewFromUtf8(isolate, "x").ToLocalChecked(), v8::Number::New(isolate, vec3.x)).FromMaybe(false)) { Q_ASSERT(false); } @@ -59,15 +106,15 @@ ScriptValue vec3ToScriptValueFast(ScriptEngine* engine, const glm::vec3& vec3) { Q_ASSERT(false); } - auto v8Prototype = ScriptValueV8Wrapper::fullUnwrap(engineV8, prototype); - if (!v8Object->SetPrototype(context, v8Prototype.get()).FromMaybe(false)) { + //auto v8Prototype = ScriptValueV8Wrapper::fullUnwrap(engineV8, prototype); + if (!v8Object->SetPrototype(context, prototype).FromMaybe(false)) { Q_ASSERT(false); } - value.setPrototype(prototype); + //value.setPrototype(prototype); return value; } -bool vec3FromScriptValueFast(const ScriptValue& object, glm::vec3& vec3) { +bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) { ScriptValueV8Wrapper *proxy = ScriptValueV8Wrapper::unwrap(object); auto engineV8 = proxy->getV8Engine(); @@ -185,3 +232,5 @@ bool vec3FromScriptValueFast(const ScriptValue& object, glm::vec3& vec3) { } return true; } + +#endif \ No newline at end of file diff --git a/libraries/script-engine/src/v8/FastScriptValueUtils.h b/libraries/script-engine/src/v8/FastScriptValueUtils.h index 8401f9ab36..80d97023a5 100644 --- a/libraries/script-engine/src/v8/FastScriptValueUtils.h +++ b/libraries/script-engine/src/v8/FastScriptValueUtils.h @@ -9,7 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// Contains V8-specific implementations of th +// Contains V8-specific implementations of the function converting Overte datatypes to and from script values. +// These are used instead of generic implementations if CONVERSIONS_OPTIMIZED_FOR_V8 is defined. +// V8-specific implementations can make script engine several times faster. #ifndef overte_FastScriptValueUtils_h #define overte_FastScriptValueUtils_h @@ -19,8 +21,12 @@ #include "../ScriptValue.h" -ScriptValue vec3ToScriptValueFast(ScriptEngine* engine, const glm::vec3& vec3); +#define CONVERSIONS_OPTIMIZED_FOR_V8 -bool vec3FromScriptValueFast(const ScriptValue& object, glm::vec3& vec3); +#ifdef CONVERSIONS_OPTIMIZED_FOR_V8 +ScriptValue vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3); + +bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3); +#endif #endif // overte_FastScriptValueUtils_h diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.cpp b/libraries/script-engine/src/v8/ScriptEngineV8.cpp index bf3750ef4f..746483cc8a 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8.cpp @@ -937,13 +937,15 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f v8::Isolate::Scope isolateScope(_v8Isolate); v8::HandleScope handleScope(_v8Isolate); v8::Context::Scope contextScope(getContext()); - v8::TryCatch tryCatch(getIsolate()); v8::ScriptOrigin scriptOrigin(getIsolate(), v8::String::NewFromUtf8(getIsolate(), fileName.toStdString().c_str()).ToLocalChecked()); v8::Local script; - if (!v8::Script::Compile(getContext(), v8::String::NewFromUtf8(getIsolate(), sourceCode.toStdString().c_str()).ToLocalChecked(), &scriptOrigin).ToLocal(&script)) { - setUncaughtException(tryCatch, "Error while compiling script"); - _evaluatingCounter--; - return nullValue(); + { + v8::TryCatch tryCatch(getIsolate()); + if (!v8::Script::Compile(getContext(), v8::String::NewFromUtf8(getIsolate(), sourceCode.toStdString().c_str()).ToLocalChecked(), &scriptOrigin).ToLocal(&script)) { + setUncaughtException(tryCatch, "Error while compiling script"); + _evaluatingCounter--; + return nullValue(); + } } //qCDebug(scriptengine_v8) << "Script compilation succesful: " << fileName;