SpiderMonkey 31 upgrade

This upgrade also introduces exact stack rooting (see to the wiki:
JSRootingGuide) and fixes problems with moving GC. This allows us to
enable generational garbage collection (GGC).
Measurements a few months ago have shown a performance improvement of a
non-visual replay of around 13.5%. This probably varies quite a bit, but
it should be somewhere between 5-20%. Memory usage has also been
improved. Check the forum thread for details.

Thanks to everyone from the team who helped with this directly or
indirectly (review, finding and fixing issues, the required C++11
upgrade, the new autobuilder etc.)! Also thanks to the SpiderMonkey
developers who helped on the #jsapi channel or elsewhere!

Fixes #2462, #2415, #2428, #2684, #1374
Refs #2973, #2669

This was SVN commit r16214.
This commit is contained in:
Yves
2015-01-24 14:46:52 +00:00
parent b9e46f386b
commit c02a7e1a7b
107 changed files with 1961 additions and 2065 deletions
+96 -100
View File
@@ -36,7 +36,7 @@ JSClass JSI_IGUIObject::JSI_class = {
JSI_IGUIObject::getProperty, JSI_IGUIObject::setProperty,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, NULL,
NULL, NULL, NULL, JSI_IGUIObject::construct
NULL, NULL, JSI_IGUIObject::construct, NULL
};
JSPropertySpec JSI_IGUIObject::JSI_props[] =
@@ -53,22 +53,22 @@ JSFunctionSpec JSI_IGUIObject::JSI_methods[] =
JS_FS_END
};
JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
{
JSAutoRequest rq(cx);
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;
return false;
JS::RootedValue idval(cx);
if (!JS_IdToValue(cx, id, idval.address()))
return JS_FALSE;
if (!JS_IdToValue(cx, id, &idval))
return false;
std::string propName;
if (!ScriptInterface::FromJSVal(cx, idval, propName))
return JS_FALSE;
return false;
// Skip some things which are known to be functions rather than properties.
// ("constructor" *must* be here, else it'll try to GetSettingType before
@@ -83,18 +83,18 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
propName == "blur" ||
propName == "getComputedSize"
)
return JS_TRUE;
return true;
// Use onWhatever to access event handlers
if (propName.substr(0, 2) == "on")
{
CStr eventName (CStr(propName.substr(2)).LowerCase());
std::map<CStr, CScriptValRooted>::iterator it = e->m_ScriptHandlers.find(eventName);
auto it = e->m_ScriptHandlers.find(eventName);
if (it == e->m_ScriptHandlers.end())
vp.set(JS::NullValue());
vp.setNull();
else
vp.set((*it).second.get());
return JS_TRUE;
vp.setObject(*it->second.get());
return true;
}
@@ -112,13 +112,13 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
// Return null if there's no parent
vp.set(JS::NullValue());
}
return JS_TRUE;
return true;
}
// Also handle "name" specially
else if (propName == "name")
{
vp.set(JS::StringValue(JS_NewStringCopyZ(cx, e->GetName().c_str())));
return JS_TRUE;
return true;
}
// Handle all other properties
else
@@ -128,7 +128,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
if (e->GetSettingType(propName, Type) != PSRETURN_OK)
{
JS_ReportError(cx, "Invalid GUIObject property '%s'", propName.c_str());
return JS_FALSE;
return false;
}
// (All the cases are in {...} to avoid scoping problems)
@@ -170,7 +170,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
#define P(x) c = JS::NumberValue(colour.x); \
if (c.isNull()) \
return false; \
JS_SetProperty(cx, obj, #x, c.address())
JS_SetProperty(cx, obj, #x, c)
P(r);
P(g);
P(b);
@@ -278,14 +278,14 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
CGUIList value;
GUI<CGUIList>::GetSetting(e, propName, value);
JS::RootedObject obj(cx, JS_NewArrayObject(cx, 0, NULL));
JS::RootedObject obj(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty()));
vp.setObject(*obj);
for (u32 i = 0; i < value.m_Items.size(); ++i)
{
JS::RootedValue val(cx);
ScriptInterface::ToJSVal(cx, &val, value.m_Items[i].GetOriginalString());
JS_SetElement(cx, obj, i, val.address());
JS_SetElement(cx, obj, i, val);
}
break;
@@ -294,35 +294,35 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
default:
JS_ReportError(cx, "Setting '%s' uses an unimplemented type", propName.c_str());
DEBUG_WARN_ERR(ERR::LOGIC);
return JS_FALSE;
return false;
}
return JS_TRUE;
return true;
}
}
JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JSBool UNUSED(strict), JS::MutableHandleValue vp)
bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool UNUSED(strict), JS::MutableHandleValue vp)
{
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;
return false;
JSAutoRequest rq(cx);
JS::RootedValue idval(cx);
if (!JS_IdToValue(cx, id, idval.address()))
return JS_FALSE;
if (!JS_IdToValue(cx, id, &idval))
return false;
std::string propName;
if (!ScriptInterface::FromJSVal(cx, idval, propName))
return JS_FALSE;
return false;
if (propName == "name")
{
std::string value;
if (!ScriptInterface::FromJSVal(cx, vp, value))
return JS_FALSE;
return false;
e->SetName(value);
return JS_TRUE;
return true;
}
// Use onWhatever to set event handlers
@@ -331,14 +331,14 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
if (vp.isPrimitive() || vp.isNull() || !JS_ObjectIsFunction(cx, &vp.toObject()))
{
JS_ReportError(cx, "on- event-handlers must be functions");
return JS_FALSE;
return false;
}
JS::RootedObject vpObj(cx, &vp.toObject());
CStr eventName (CStr(propName.substr(2)).LowerCase());
e->SetScriptHandler(eventName, vpObj);
return JS_TRUE;
return true;
}
// Retrieve the setting's type (and make sure it actually exists)
@@ -346,9 +346,13 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
if (e->GetSettingType(propName, Type) != PSRETURN_OK)
{
JS_ReportError(cx, "Invalid setting '%s'", propName.c_str());
return JS_TRUE;
return true;
}
JS::RootedObject vpObj(cx);
if (vp.isObject())
vpObj = &vp.toObject();
switch (Type)
{
@@ -356,7 +360,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
{
std::string value;
if (!ScriptInterface::FromJSVal(cx, vp, value))
return JS_FALSE;
return false;
GUI<CStr>::SetSetting(e, propName, value);
break;
@@ -386,7 +390,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
{
std::wstring value;
if (!ScriptInterface::FromJSVal(cx, vp, value))
return JS_FALSE;
return false;
CGUIString str;
str.SetValue(value);
@@ -398,7 +402,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
{
std::string value;
if (!ScriptInterface::FromJSVal(cx, vp, value))
return JS_FALSE;
return false;
EAlign a;
if (value == "left") a = EAlign_Left;
@@ -407,7 +411,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
else
{
JS_ReportError(cx, "Invalid alignment (should be 'left', 'right' or 'center')");
return JS_FALSE;
return false;
}
GUI<EAlign>::SetSetting(e, propName, a);
break;
@@ -417,7 +421,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
{
std::string value;
if (!ScriptInterface::FromJSVal(cx, vp, value))
return JS_FALSE;
return false;
EVAlign a;
if (value == "top") a = EVAlign_Top;
@@ -426,7 +430,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
else
{
JS_ReportError(cx, "Invalid alignment (should be 'top', 'bottom' or 'center')");
return JS_FALSE;
return false;
}
GUI<EVAlign>::SetSetting(e, propName, a);
break;
@@ -440,7 +444,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
else
{
JS_ReportError(cx, "Cannot convert value to int");
return JS_FALSE;
return false;
}
break;
}
@@ -448,26 +452,20 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
case GUIST_float:
{
double value;
if (JS_ValueToNumber(cx, vp, &value) == true)
if (JS::ToNumber(cx, vp, &value) == true)
GUI<float>::SetSetting(e, propName, (float)value);
else
{
JS_ReportError(cx, "Cannot convert value to float");
return JS_FALSE;
return false;
}
break;
}
case GUIST_bool:
{
JSBool value;
if (JS_ValueToBoolean(cx, vp, &value))
GUI<bool>::SetSetting(e, propName, value);
else
{
JS_ReportError(cx, "Cannot convert value to bool");
return JS_FALSE;
}
bool value = JS::ToBoolean(vp);
GUI<bool>::SetSetting(e, propName, value);
break;
}
@@ -477,15 +475,15 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
{
std::wstring value;
if (!ScriptInterface::FromJSVal(cx, vp, value))
return JS_FALSE;
return false;
if (e->SetSetting(propName, value) != PSRETURN_OK)
{
JS_ReportError(cx, "Invalid value for setting '%s'", propName.c_str());
return JS_FALSE;
return false;
}
}
else if (vp.isObject() && JS_InstanceOf(cx, &vp.toObject(), &JSI_GUISize::JSI_class, NULL))
else if (vp.isObject() && JS_InstanceOf(cx, vpObj, &JSI_GUISize::JSI_class, NULL))
{
CClientArea area;
GUI<CClientArea>::GetSetting(e, propName, area);
@@ -507,7 +505,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
else
{
JS_ReportError(cx, "Size only accepts strings or GUISize objects");
return JS_FALSE;
return false;
}
break;
}
@@ -518,21 +516,21 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
{
std::wstring value;
if (!ScriptInterface::FromJSVal(cx, vp, value))
return JS_FALSE;
return false;
if (e->SetSetting(propName, value) != PSRETURN_OK)
{
JS_ReportError(cx, "Invalid value for setting '%s'", propName.c_str());
return JS_FALSE;
return false;
}
}
else if (vp.isObject() && JS_InstanceOf(cx, &vp.toObject(), &JSI_GUIColor::JSI_class, NULL))
else if (vp.isObject() && JS_InstanceOf(cx, vpObj, &JSI_GUIColor::JSI_class, NULL))
{
CColor colour;
JS::RootedObject (cx, &vp.toObject());
JS::RootedValue t(cx);
double s;
#define PROP(x) JS_GetProperty(cx, obj, #x, t.address()); \
#define PROP(x) JS_GetProperty(cx, obj, #x, &t); \
s = t.toDouble(); \
colour.x = (float)s
PROP(r); PROP(g); PROP(b); PROP(a);
@@ -543,7 +541,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
else
{
JS_ReportError(cx, "Color only accepts strings or GUIColor objects");
return JS_FALSE;
return false;
}
break;
}
@@ -551,37 +549,35 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
case GUIST_CGUIList:
{
u32 length;
if (vp.isObject() && JS_GetArrayLength(cx, &vp.toObject(), &length) == true)
{
CGUIList list;
JS::RootedObject obj(cx, &vp.toObject());
for (u32 i=0; i<length; ++i)
{
JS::RootedValue element(cx);
if (! JS_GetElement(cx, obj, i, element.address()))
{
JS_ReportError(cx, "Failed to get list element");
return JS_FALSE;
}
std::wstring value;
if (!ScriptInterface::FromJSVal(cx, element, value))
return JS_FALSE;
CGUIString str;
str.SetValue(value);
list.m_Items.push_back(str);
}
GUI<CGUIList>::SetSetting(e, propName, list);
}
else
if (!vp.isObject() || !JS_GetArrayLength(cx, vpObj, &length))
{
JS_ReportError(cx, "List only accepts a GUIList object");
return JS_FALSE;
return false;
}
CGUIList list;
JS::RootedObject obj(cx, &vp.toObject());
for (u32 i=0; i<length; ++i)
{
JS::RootedValue element(cx);
if (! JS_GetElement(cx, obj, i, &element))
{
JS_ReportError(cx, "Failed to get list element");
return false;
}
std::wstring value;
if (!ScriptInterface::FromJSVal(cx, element, value))
return false;
CGUIString str;
str.SetValue(value);
list.m_Items.push_back(str);
}
GUI<CGUIList>::SetSetting(e, propName, list);
break;
}
@@ -596,7 +592,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
}
JSBool JSI_IGUIObject::construct(JSContext* cx, uint argc, jsval* vp)
bool JSI_IGUIObject::construct(JSContext* cx, uint argc, jsval* vp)
{
JSAutoRequest rq(cx);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
@@ -605,7 +601,7 @@ JSBool JSI_IGUIObject::construct(JSContext* cx, uint argc, jsval* vp)
if (args.length() == 0)
{
JS_ReportError(cx, "GUIObject has no default constructor");
return JS_FALSE;
return false;
}
JS::RootedObject obj(cx, pScriptInterface->CreateCustomObject("GUIObject"));
@@ -615,7 +611,7 @@ JSBool JSI_IGUIObject::construct(JSContext* cx, uint argc, jsval* vp)
JS_SetPrivate(obj, guiObject);
args.rval().setObject(*obj);
return JS_TRUE;
return true;
}
void JSI_IGUIObject::init(ScriptInterface& scriptInterface)
@@ -623,7 +619,7 @@ void JSI_IGUIObject::init(ScriptInterface& scriptInterface)
scriptInterface.DefineCustomObjectType(&JSI_class, construct, 1, JSI_props, JSI_methods, NULL, NULL);
}
JSBool JSI_IGUIObject::toString(JSContext* cx, uint argc, jsval* vp)
bool JSI_IGUIObject::toString(JSContext* cx, uint argc, jsval* vp)
{
UNUSED2(argc);
JSAutoRequest rq(cx);
@@ -633,16 +629,16 @@ JSBool JSI_IGUIObject::toString(JSContext* cx, uint argc, jsval* vp)
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;
return false;
char buffer[256];
snprintf(buffer, 256, "[GUIObject: %s]", e->GetName().c_str());
buffer[255] = 0;
rec.rval().setString(JS_NewStringCopyZ(cx, buffer));
return JS_TRUE;
return true;
}
JSBool JSI_IGUIObject::focus(JSContext* cx, uint argc, jsval* vp)
bool JSI_IGUIObject::focus(JSContext* cx, uint argc, jsval* vp)
{
UNUSED2(argc);
JSAutoRequest rq(cx);
@@ -652,15 +648,15 @@ JSBool JSI_IGUIObject::focus(JSContext* cx, uint argc, jsval* vp)
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;
return false;
e->GetGUI()->SetFocusedObject(e);
rec.rval().setUndefined();
return JS_TRUE;
return true;
}
JSBool JSI_IGUIObject::blur(JSContext* cx, uint argc, jsval* vp)
bool JSI_IGUIObject::blur(JSContext* cx, uint argc, jsval* vp)
{
UNUSED2(argc);
JSAutoRequest rq(cx);
@@ -670,15 +666,15 @@ JSBool JSI_IGUIObject::blur(JSContext* cx, uint argc, jsval* vp)
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;
return false;
e->GetGUI()->SetFocusedObject(NULL);
rec.rval().setUndefined();
return JS_TRUE;
return true;
}
JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp)
bool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp)
{
UNUSED2(argc);
JSAutoRequest rq(cx);
@@ -688,12 +684,12 @@ JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp)
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;
return false;
e->UpdateCachedSize();
CRect size = e->m_CachedActualSize;
JS::RootedValue objVal(cx, JS::ObjectValue(*JS_NewObject(cx, NULL, NULL, NULL)));
JS::RootedValue objVal(cx, JS::ObjectValue(*JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr())));
try
{
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
@@ -705,9 +701,9 @@ JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp)
catch (PSERROR_Scripting_ConversionFailed&)
{
debug_warn(L"Error creating size object!");
return JS_FALSE;
return false;
}
rec.rval().set(objVal);
return JS_TRUE;
return true;
}