Skip to content
Permalink
Browse files
[JSC] Make Intl fields lazily-allocated
https://bugs.webkit.org/show_bug.cgi?id=195022

Reviewed by Mark Lam.

This patch makes the following memory footprint optimization in IntlObject.

1. Make IntlObject fields including Intl.Collator lazily-allocated because we already removed direct references from JS builtins to these constructors (@Collator etc.).

2. Move LazyProperty<IntlObject, Structure> structures from IntlObject to JSGlobalObject. This makes sizeof(IntlObject) the same to the other ones of usual runtime Objects,
   and drop one MarkedBlock.

* runtime/IntlCollatorConstructor.h:
* runtime/IntlDateTimeFormatConstructor.h:
* runtime/IntlNumberFormatConstructor.h:
* runtime/IntlObject.cpp:
(JSC::createCollatorConstructor):
(JSC::createNumberFormatConstructor):
(JSC::createDateTimeFormatConstructor):
(JSC::createPluralRulesConstructor):
(JSC::IntlObject::finishCreation):
(JSC::IntlObject::visitChildren): Deleted.
* runtime/IntlObject.h:
* runtime/IntlPluralRulesConstructor.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
(JSC::JSGlobalObject::defaultCollator):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::collatorStructure):
(JSC::JSGlobalObject::numberFormatStructure):
(JSC::JSGlobalObject::dateTimeFormatStructure):
(JSC::JSGlobalObject::pluralRulesStructure):
(JSC::JSGlobalObject::intlObject const): Deleted.
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncDateTimeFormat):
* runtime/NumberPrototype.cpp:
(JSC::numberProtoFuncToLocaleString):
* runtime/StringPrototype.cpp:
(JSC::stringProtoFuncLocaleCompare):

Canonical link: https://commits.webkit.org/209387@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Constellation committed Feb 26, 2019
1 parent ebc08ad commit 270fa07783bbe99872cb288a07af2bc970707868
Showing 12 changed files with 105 additions and 72 deletions.
@@ -1,3 +1,46 @@
2019-02-25 Yusuke Suzuki <ysuzuki@apple.com>

[JSC] Make Intl fields lazily-allocated
https://bugs.webkit.org/show_bug.cgi?id=195022

Reviewed by Mark Lam.

This patch makes the following memory footprint optimization in IntlObject.

1. Make IntlObject fields including Intl.Collator lazily-allocated because we already removed direct references from JS builtins to these constructors (@Collator etc.).

2. Move LazyProperty<IntlObject, Structure> structures from IntlObject to JSGlobalObject. This makes sizeof(IntlObject) the same to the other ones of usual runtime Objects,
and drop one MarkedBlock.

* runtime/IntlCollatorConstructor.h:
* runtime/IntlDateTimeFormatConstructor.h:
* runtime/IntlNumberFormatConstructor.h:
* runtime/IntlObject.cpp:
(JSC::createCollatorConstructor):
(JSC::createNumberFormatConstructor):
(JSC::createDateTimeFormatConstructor):
(JSC::createPluralRulesConstructor):
(JSC::IntlObject::finishCreation):
(JSC::IntlObject::visitChildren): Deleted.
* runtime/IntlObject.h:
* runtime/IntlPluralRulesConstructor.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
(JSC::JSGlobalObject::defaultCollator):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::collatorStructure):
(JSC::JSGlobalObject::numberFormatStructure):
(JSC::JSGlobalObject::dateTimeFormatStructure):
(JSC::JSGlobalObject::pluralRulesStructure):
(JSC::JSGlobalObject::intlObject const): Deleted.
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncDateTimeFormat):
* runtime/NumberPrototype.cpp:
(JSC::numberProtoFuncToLocaleString):
* runtime/StringPrototype.cpp:
(JSC::stringProtoFuncLocaleCompare):

2019-02-25 Tadeu Zagallo <tzagallo@apple.com>

Avoid hashing CompactVariableEnvironment when decoding CompactVariableMap::Handle
@@ -46,7 +46,7 @@ class IntlCollatorConstructor final : public InternalFunction {

DECLARE_INFO;

Structure* collatorStructure(VM& vm) const { return globalObject(vm)->intlObject()->collatorStructure(); }
Structure* collatorStructure(VM& vm) const { return globalObject(vm)->collatorStructure(); }

protected:
void finishCreation(VM&, IntlCollatorPrototype*);
@@ -46,7 +46,7 @@ class IntlDateTimeFormatConstructor final : public InternalFunction {

DECLARE_INFO;

Structure* dateTimeFormatStructure(VM& vm) const { return globalObject(vm)->intlObject()->dateTimeFormatStructure(); }
Structure* dateTimeFormatStructure(VM& vm) const { return globalObject(vm)->dateTimeFormatStructure(); }

protected:
void finishCreation(VM&, IntlDateTimeFormatPrototype*);
@@ -46,7 +46,7 @@ class IntlNumberFormatConstructor final : public InternalFunction {

DECLARE_INFO;

Structure* numberFormatStructure(VM& vm) const { return globalObject(vm)->intlObject()->numberFormatStructure(); }
Structure* numberFormatStructure(VM& vm) const { return globalObject(vm)->numberFormatStructure(); }

protected:
void finishCreation(VM&, IntlNumberFormatPrototype*);
@@ -33,21 +33,16 @@
#include "Error.h"
#include "FunctionPrototype.h"
#include "IntlCanonicalizeLanguage.h"
#include "IntlCollator.h"
#include "IntlCollatorConstructor.h"
#include "IntlCollatorPrototype.h"
#include "IntlDateTimeFormat.h"
#include "IntlDateTimeFormatConstructor.h"
#include "IntlDateTimeFormatPrototype.h"
#include "IntlNumberFormat.h"
#include "IntlNumberFormatConstructor.h"
#include "IntlNumberFormatPrototype.h"
#include "IntlPluralRules.h"
#include "IntlPluralRulesConstructor.h"
#include "IntlPluralRulesPrototype.h"
#include "JSCInlines.h"
#include "JSCJSValueInlines.h"
#include "LazyPropertyInlines.h"
#include "Lookup.h"
#include "ObjectPrototype.h"
#include "Options.h"
@@ -68,28 +63,28 @@ static JSValue createCollatorConstructor(VM& vm, JSObject* object)
{
IntlObject* intlObject = jsCast<IntlObject*>(object);
JSGlobalObject* globalObject = intlObject->globalObject(vm);
return IntlCollatorConstructor::create(vm, IntlCollatorConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlCollatorPrototype*>(intlObject->collatorStructure()->storedPrototypeObject()));
return IntlCollatorConstructor::create(vm, IntlCollatorConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlCollatorPrototype*>(globalObject->collatorStructure()->storedPrototypeObject()));
}

static JSValue createNumberFormatConstructor(VM& vm, JSObject* object)
{
IntlObject* intlObject = jsCast<IntlObject*>(object);
JSGlobalObject* globalObject = intlObject->globalObject(vm);
return IntlNumberFormatConstructor::create(vm, IntlNumberFormatConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlNumberFormatPrototype*>(intlObject->numberFormatStructure()->storedPrototypeObject()));
return IntlNumberFormatConstructor::create(vm, IntlNumberFormatConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlNumberFormatPrototype*>(globalObject->numberFormatStructure()->storedPrototypeObject()));
}

static JSValue createDateTimeFormatConstructor(VM& vm, JSObject* object)
{
IntlObject* intlObject = jsCast<IntlObject*>(object);
JSGlobalObject* globalObject = intlObject->globalObject(vm);
return IntlDateTimeFormatConstructor::create(vm, IntlDateTimeFormatConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlDateTimeFormatPrototype*>(intlObject->dateTimeFormatStructure()->storedPrototypeObject()));
return IntlDateTimeFormatConstructor::create(vm, IntlDateTimeFormatConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlDateTimeFormatPrototype*>(globalObject->dateTimeFormatStructure()->storedPrototypeObject()));
}

static JSValue createPluralRulesConstructor(VM& vm, JSObject* object)
{
IntlObject* intlObject = jsCast<IntlObject*>(object);
JSGlobalObject* globalObject = intlObject->globalObject(vm);
return IntlPluralRulesConstructor::create(vm, IntlPluralRulesConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlPluralRulesPrototype*>(intlObject->pluralRulesStructure()->storedPrototypeObject()));
return IntlPluralRulesConstructor::create(vm, IntlPluralRulesConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlPluralRulesPrototype*>(globalObject->pluralRulesStructure()->storedPrototypeObject()));
}

}
@@ -101,6 +96,9 @@ namespace JSC {
/* Source for IntlObject.lut.h
@begin intlObjectTable
getCanonicalLocales intlObjectFuncGetCanonicalLocales DontEnum|Function 1
Collator createCollatorConstructor DontEnum|PropertyCallback
DateTimeFormat createDateTimeFormatConstructor DontEnum|PropertyCallback
NumberFormat createNumberFormatConstructor DontEnum|PropertyCallback
@end
*/

@@ -129,35 +127,6 @@ void IntlObject::finishCreation(VM& vm)
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));

m_collatorStructure.initLater(
[] (const LazyProperty<IntlObject, Structure>::Initializer& init) {
JSGlobalObject* globalObject = jsCast<IntlObject*>(init.owner)->globalObject(init.vm);
IntlCollatorPrototype* collatorPrototype = IntlCollatorPrototype::create(init.vm, globalObject, IntlCollatorPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
init.set(IntlCollator::createStructure(init.vm, globalObject, collatorPrototype));
});
m_numberFormatStructure.initLater(
[] (const LazyProperty<IntlObject, Structure>::Initializer& init) {
JSGlobalObject* globalObject = jsCast<IntlObject*>(init.owner)->globalObject(init.vm);
IntlNumberFormatPrototype* numberFormatPrototype = IntlNumberFormatPrototype::create(init.vm, globalObject, IntlNumberFormatPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
init.set(IntlNumberFormat::createStructure(init.vm, globalObject, numberFormatPrototype));
});
m_dateTimeFormatStructure.initLater(
[] (const LazyProperty<IntlObject, Structure>::Initializer& init) {
JSGlobalObject* globalObject = jsCast<IntlObject*>(init.owner)->globalObject(init.vm);
IntlDateTimeFormatPrototype* dateTimeFormatPrototype = IntlDateTimeFormatPrototype::create(init.vm, globalObject, IntlDateTimeFormatPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
init.set(IntlDateTimeFormat::createStructure(init.vm, globalObject, dateTimeFormatPrototype));
});
m_pluralRulesStructure.initLater(
[] (const LazyProperty<IntlObject, Structure>::Initializer& init) {
JSGlobalObject* globalObject = jsCast<IntlObject*>(init.owner)->globalObject(init.vm);
IntlPluralRulesPrototype* pluralRulesPrototype = IntlPluralRulesPrototype::create(init.vm, globalObject, IntlPluralRulesPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
init.set(IntlPluralRules::createStructure(init.vm, globalObject, pluralRulesPrototype));
});

putDirectWithoutTransition(vm, vm.propertyNames->Collator, createCollatorConstructor(vm, this), static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectWithoutTransition(vm, vm.propertyNames->NumberFormat, createNumberFormatConstructor(vm, this), static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectWithoutTransition(vm, vm.propertyNames->DateTimeFormat, createDateTimeFormatConstructor(vm, this), static_cast<unsigned>(PropertyAttribute::DontEnum));

// Constructor Properties of the Intl Object
// https://tc39.github.io/ecma402/#sec-constructor-properties-of-the-intl-object
if (Options::useIntlPluralRules())
@@ -981,19 +950,6 @@ EncodedJSValue JSC_HOST_CALL intlObjectFuncGetCanonicalLocales(ExecState* state)
return JSValue::encode(localeArray);
}

void IntlObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
IntlObject* thisObject = jsCast<IntlObject*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());

Base::visitChildren(thisObject, visitor);

thisObject->m_collatorStructure.visit(visitor);
thisObject->m_numberFormatStructure.visit(visitor);
thisObject->m_dateTimeFormatStructure.visit(visitor);
thisObject->m_pluralRulesStructure.visit(visitor);
}

} // namespace JSC

#endif // ENABLE(INTL)
@@ -44,29 +44,18 @@ class IntlPluralRulesPrototype;
class IntlObject final : public JSNonFinalObject {
public:
typedef JSNonFinalObject Base;
static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable | OverridesGetOwnPropertySlot;
static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;

static IntlObject* create(VM&, Structure*);
static Structure* createStructure(VM&, JSGlobalObject*, JSValue);

DECLARE_INFO;

Structure* collatorStructure() { return m_collatorStructure.get(this); }
Structure* numberFormatStructure() { return m_numberFormatStructure.get(this); }
Structure* dateTimeFormatStructure() { return m_dateTimeFormatStructure.get(this); }
Structure* pluralRulesStructure() { return m_pluralRulesStructure.get(this); }

protected:
void finishCreation(VM&);

private:
static void visitChildren(JSCell*, SlotVisitor&);

IntlObject(VM&, Structure*);
LazyProperty<IntlObject, Structure> m_collatorStructure;
LazyProperty<IntlObject, Structure> m_numberFormatStructure;
LazyProperty<IntlObject, Structure> m_dateTimeFormatStructure;
LazyProperty<IntlObject, Structure> m_pluralRulesStructure;
};

String defaultLocale(ExecState&);
@@ -45,7 +45,7 @@ class IntlPluralRulesConstructor final : public InternalFunction {

DECLARE_INFO;

Structure* pluralRulesStructure(VM& vm) const { return globalObject(vm)->intlObject()->pluralRulesStructure(); }
Structure* pluralRulesStructure(VM& vm) const { return globalObject(vm)->pluralRulesStructure(); }

protected:
void finishCreation(VM&, IntlPluralRulesPrototype*);
@@ -179,7 +179,14 @@

#if ENABLE(INTL)
#include "IntlCollator.h"
#include "IntlCollatorPrototype.h"
#include "IntlDateTimeFormat.h"
#include "IntlDateTimeFormatPrototype.h"
#include "IntlNumberFormat.h"
#include "IntlNumberFormatPrototype.h"
#include "IntlObject.h"
#include "IntlPluralRules.h"
#include "IntlPluralRulesPrototype.h"
#include <unicode/ucol.h>
#include <unicode/udat.h>
#include <unicode/unum.h>
@@ -799,6 +806,31 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
putDirectWithoutTransition(vm, vm.propertyNames->eval, m_evalFunction.get(), static_cast<unsigned>(PropertyAttribute::DontEnum));

#if ENABLE(INTL)
m_collatorStructure.initLater(
[] (const Initializer<Structure>& init) {
JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner);
IntlCollatorPrototype* collatorPrototype = IntlCollatorPrototype::create(init.vm, globalObject, IntlCollatorPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
init.set(IntlCollator::createStructure(init.vm, globalObject, collatorPrototype));
});
m_numberFormatStructure.initLater(
[] (const Initializer<Structure>& init) {
JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner);
IntlNumberFormatPrototype* numberFormatPrototype = IntlNumberFormatPrototype::create(init.vm, globalObject, IntlNumberFormatPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
init.set(IntlNumberFormat::createStructure(init.vm, globalObject, numberFormatPrototype));
});
m_dateTimeFormatStructure.initLater(
[] (const Initializer<Structure>& init) {
JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner);
IntlDateTimeFormatPrototype* dateTimeFormatPrototype = IntlDateTimeFormatPrototype::create(init.vm, globalObject, IntlDateTimeFormatPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
init.set(IntlDateTimeFormat::createStructure(init.vm, globalObject, dateTimeFormatPrototype));
});
m_pluralRulesStructure.initLater(
[] (const Initializer<Structure>& init) {
JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner);
IntlPluralRulesPrototype* pluralRulesPrototype = IntlPluralRulesPrototype::create(init.vm, globalObject, IntlPluralRulesPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
init.set(IntlPluralRules::createStructure(init.vm, globalObject, pluralRulesPrototype));
});

IntlObject* intl = IntlObject::create(vm, IntlObject::createStructure(vm, this, m_objectPrototype.get()));
putDirectWithoutTransition(vm, vm.propertyNames->Intl, intl, static_cast<unsigned>(PropertyAttribute::DontEnum));
m_intlObject.set(vm, this, intl);
@@ -1568,6 +1600,10 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
#if ENABLE(INTL)
visitor.append(thisObject->m_intlObject);
visitor.append(thisObject->m_defaultCollator);
thisObject->m_collatorStructure.visit(visitor);
thisObject->m_numberFormatStructure.visit(visitor);
thisObject->m_dateTimeFormatStructure.visit(visitor);
thisObject->m_pluralRulesStructure.visit(visitor);
#endif
visitor.append(thisObject->m_nullGetterFunction);
visitor.append(thisObject->m_nullSetterFunction);
@@ -1874,7 +1910,7 @@ IntlCollator* JSGlobalObject::defaultCollator(ExecState* exec)
if (m_defaultCollator)
return m_defaultCollator.get();

IntlCollator* collator = IntlCollator::create(vm, intlObject()->collatorStructure());
IntlCollator* collator = IntlCollator::create(vm, collatorStructure());
collator->initializeCollator(*exec, jsUndefined(), jsUndefined());
RETURN_IF_EXCEPTION(scope, nullptr);
m_defaultCollator.set(vm, this, collator);
@@ -278,6 +278,10 @@ class JSGlobalObject : public JSSegmentedVariableObject {
#if ENABLE(INTL)
WriteBarrier<IntlObject> m_intlObject;
WriteBarrier<IntlCollator> m_defaultCollator;
LazyProperty<JSGlobalObject, Structure> m_collatorStructure;
LazyProperty<JSGlobalObject, Structure> m_numberFormatStructure;
LazyProperty<JSGlobalObject, Structure> m_dateTimeFormatStructure;
LazyProperty<JSGlobalObject, Structure> m_pluralRulesStructure;
#endif
WriteBarrier<NullGetterFunction> m_nullGetterFunction;
WriteBarrier<NullSetterFunction> m_nullSetterFunction;
@@ -588,7 +592,6 @@ class JSGlobalObject : public JSSegmentedVariableObject {
JSInternalPromiseConstructor* internalPromiseConstructor() const { return m_internalPromiseConstructor.get(); }

#if ENABLE(INTL)
IntlObject* intlObject() const { return m_intlObject.get(); }
IntlCollator* defaultCollator(ExecState*);
#endif

@@ -766,6 +769,12 @@ class JSGlobalObject : public JSSegmentedVariableObject {
Structure* webAssemblyWrapperFunctionStructure() const { return m_webAssemblyWrapperFunctionStructure.get(); }
Structure* webAssemblyToJSCalleeStructure() const { return m_webAssemblyToJSCalleeStructure.get(); }
#endif // ENABLE(WEBASSEMBLY)
#if ENABLE(INTL)
Structure* collatorStructure() { return m_collatorStructure.get(this); }
Structure* numberFormatStructure() { return m_numberFormatStructure.get(this); }
Structure* dateTimeFormatStructure() { return m_dateTimeFormatStructure.get(this); }
Structure* pluralRulesStructure() { return m_pluralRulesStructure.get(this); }
#endif // ENABLE(INTL)

JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool);
JS_EXPORT_PRIVATE bool remoteDebuggingEnabled() const;
@@ -839,7 +839,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncDateTimeFormat(ExecState* exec)
auto scope = DECLARE_THROW_SCOPE(vm);

JSGlobalObject* globalObject = exec->lexicalGlobalObject();
IntlDateTimeFormat* dateTimeFormat = IntlDateTimeFormat::create(vm, globalObject->intlObject()->dateTimeFormatStructure());
IntlDateTimeFormat* dateTimeFormat = IntlDateTimeFormat::create(vm, globalObject->dateTimeFormatStructure());
dateTimeFormat->initializeDateTimeFormat(*exec, exec->argument(0), exec->argument(1));
RETURN_IF_EXCEPTION(scope, encodedJSValue());
double value = exec->argument(2).toNumber(exec);
@@ -602,7 +602,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec)

#if ENABLE(INTL)
JSGlobalObject* globalObject = exec->lexicalGlobalObject();
IntlNumberFormat* numberFormat = IntlNumberFormat::create(vm, globalObject->intlObject()->numberFormatStructure());
IntlNumberFormat* numberFormat = IntlNumberFormat::create(vm, globalObject->numberFormatStructure());
numberFormat->initializeNumberFormat(*exec, exec->argument(0), exec->argument(1));
RETURN_IF_EXCEPTION(scope, encodedJSValue());
RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatNumber(*exec, x)));
@@ -1517,7 +1517,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
collator = globalObject->defaultCollator(exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
} else {
collator = IntlCollator::create(vm, globalObject->intlObject()->collatorStructure());
collator = IntlCollator::create(vm, globalObject->collatorStructure());
collator->initializeCollator(*exec, locales, options);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
}

0 comments on commit 270fa07

Please sign in to comment.