vec3ToScriptValue optimizations

This commit is contained in:
ksuprynowicz 2023-04-01 19:51:21 +02:00
parent 43939290b2
commit 8b9cd84df7
4 changed files with 77 additions and 47 deletions

View file

@ -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<QVector3D, qVector3DToScriptValue, qVector3DFromScriptValue>(engine);
scriptRegisterMetaType<glm::vec2, vec2ToScriptValue, vec2FromScriptValue>(engine);
#ifdef CONVERSIONS_OPTIMIZED_FOR_V8
scriptRegisterMetaType<glm::vec3, vec3ToScriptValueFast, vec3FromScriptValueFast>(engine);
#else
scriptRegisterMetaType<glm::vec3, vec3ToScriptValue, vec3FromScriptValue>(engine);
#endif
scriptRegisterMetaType<glm::u8vec3, u8vec3ToScriptValue, u8vec3FromScriptValue>(engine);
scriptRegisterMetaType<glm::vec4, vec4toScriptValue, vec4FromScriptValue>(engine);
scriptRegisterMetaType<glm::quat, quatToScriptValue, quatFromScriptValue>(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<gl
ScriptValue qVectorVec3ToScriptValue(ScriptEngine* engine, const QVector<glm::vec3>& 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;
}

View file

@ -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<v8::Object> v8Object = v8::Local<v8::Object>::Cast(v8ScriptValue.get());
v8::Local<v8::Value> 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<v8::Object> prototypeObject = v8::Local<v8::Object>::Cast(prototype);
v8::Local<v8::Value> 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<v8::Script> script;
if (!v8::Script::Compile(context, v8::String::NewFromUtf8(isolate, sourceCode.toStdString().c_str()).ToLocalChecked(), &scriptOrigin).ToLocal(&script)) {
Q_ASSERT(false);
}
v8::Local<v8::Value> 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

View file

@ -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

View file

@ -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<v8::Script> 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;