Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (243363 => 243364)
--- trunk/Source/_javascript_Core/ChangeLog 2019-03-22 05:56:02 UTC (rev 243363)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-03-22 06:45:20 UTC (rev 243364)
@@ -1,3 +1,27 @@
+2019-03-21 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Shrink sizeof(RegExpObject)
+ https://bugs.webkit.org/show_bug.cgi?id=196130
+
+ Reviewed by Saam Barati.
+
+ sizeof(RegExpObject) is 48B due to one bool flag. We should compress this flag into lower bit of RegExp* field so that we can make RegExpObject 32B.
+ It saves memory footprint 1.3% in RAMification's regexp.
+
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileNewRegexp):
+ (JSC::DFG::SpeculativeJIT::compileSetRegExpObjectLastIndex):
+ * ftl/FTLAbstractHeapRepository.h:
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
+ (JSC::FTL::DFG::LowerDFGToB3::compileSetRegExpObjectLastIndex):
+ * runtime/RegExpObject.cpp:
+ (JSC::RegExpObject::RegExpObject):
+ (JSC::RegExpObject::visitChildren):
+ (JSC::RegExpObject::getOwnPropertySlot):
+ (JSC::RegExpObject::defineOwnProperty):
+ * runtime/RegExpObject.h:
+
2019-03-21 Tomas Popela <tpop...@redhat.com>
[JSC] Fix build after r243232 on unsupported 64bit architectures
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (243363 => 243364)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2019-03-22 05:56:02 UTC (rev 243363)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2019-03-22 06:45:20 UTC (rev 243364)
@@ -9790,9 +9790,8 @@
m_jit.storePtr(
TrustedImmPtr(node->cellOperand()),
- CCallHelpers::Address(resultGPR, RegExpObject::offsetOfRegExp()));
+ CCallHelpers::Address(resultGPR, RegExpObject::offsetOfRegExpAndLastIndexIsNotWritableFlag()));
m_jit.storeValue(lastIndexRegs, CCallHelpers::Address(resultGPR, RegExpObject::offsetOfLastIndex()));
- m_jit.store8(TrustedImm32(true), CCallHelpers::Address(resultGPR, RegExpObject::offsetOfLastIndexIsWritable()));
m_jit.mutatorFence(*m_jit.vm());
addSlowPathGenerator(slowPathCall(slowPath, this, operationNewRegexpWithLastIndex, resultGPR, regexp, lastIndexRegs));
@@ -11130,9 +11129,10 @@
speculateRegExpObject(node->child1(), regExpGPR);
speculationCheck(
ExoticObjectMode, JSValueRegs(), nullptr,
- m_jit.branchTest8(
- JITCompiler::Zero,
- JITCompiler::Address(regExpGPR, RegExpObject::offsetOfLastIndexIsWritable())));
+ m_jit.branchTestPtr(
+ JITCompiler::NonZero,
+ JITCompiler::Address(regExpGPR, RegExpObject::offsetOfRegExpAndLastIndexIsNotWritableFlag()),
+ JITCompiler::TrustedImm32(RegExpObject::lastIndexIsNotWritableFlag)));
}
m_jit.storeValue(valueRegs, JITCompiler::Address(regExpGPR, RegExpObject::offsetOfLastIndex()));
Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (243363 => 243364)
--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2019-03-22 05:56:02 UTC (rev 243363)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2019-03-22 06:45:20 UTC (rev 243364)
@@ -96,9 +96,8 @@
macro(JSScope_next, JSScope::offsetOfNext()) \
macro(JSSymbolTableObject_symbolTable, JSSymbolTableObject::offsetOfSymbolTable()) \
macro(JSWrapperObject_internalValue, JSWrapperObject::internalValueOffset()) \
- macro(RegExpObject_regExp, RegExpObject::offsetOfRegExp()) \
+ macro(RegExpObject_regExpAndLastIndexIsNotWritableFlag, RegExpObject::offsetOfRegExpAndLastIndexIsNotWritableFlag()) \
macro(RegExpObject_lastIndex, RegExpObject::offsetOfLastIndex()) \
- macro(RegExpObject_lastIndexIsWritable, RegExpObject::offsetOfLastIndexIsWritable()) \
macro(ShadowChicken_Packet_callee, OBJECT_OFFSETOF(ShadowChicken::Packet, callee)) \
macro(ShadowChicken_Packet_frame, OBJECT_OFFSETOF(ShadowChicken::Packet, frame)) \
macro(ShadowChicken_Packet_callerFrame, OBJECT_OFFSETOF(ShadowChicken::Packet, callerFrame)) \
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (243363 => 243364)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2019-03-22 05:56:02 UTC (rev 243363)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2019-03-22 06:45:20 UTC (rev 243364)
@@ -11290,9 +11290,8 @@
auto structure = m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->regExpStructure());
LValue fastResultValue = allocateObject<RegExpObject>(structure, m_out.intPtrZero, slowCase);
- m_out.storePtr(frozenPointer(regexp), fastResultValue, m_heaps.RegExpObject_regExp);
+ m_out.storePtr(frozenPointer(regexp), fastResultValue, m_heaps.RegExpObject_regExpAndLastIndexIsNotWritableFlag);
m_out.store64(lastIndex, fastResultValue, m_heaps.RegExpObject_lastIndex);
- m_out.store32As8(m_out.constInt32(true), m_out.address(fastResultValue, m_heaps.RegExpObject_lastIndexIsWritable));
mutatorFence();
ValueFromBlock fastResult = m_out.anchor(fastResultValue);
m_out.jump(continuation);
@@ -11378,7 +11377,9 @@
speculate(
ExoticObjectMode, noValue(), nullptr,
- m_out.isZero32(m_out.load8ZeroExt32(regExp, m_heaps.RegExpObject_lastIndexIsWritable)));
+ m_out.testNonZeroPtr(
+ m_out.loadPtr(regExp, m_heaps.RegExpObject_regExpAndLastIndexIsNotWritableFlag),
+ m_out.constIntPtr(RegExpObject::lastIndexIsNotWritableFlag)));
m_out.store64(value, regExp, m_heaps.RegExpObject_lastIndex);
return;
Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.cpp (243363 => 243364)
--- trunk/Source/_javascript_Core/runtime/RegExpObject.cpp 2019-03-22 05:56:02 UTC (rev 243363)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.cpp 2019-03-22 06:45:20 UTC (rev 243364)
@@ -38,8 +38,7 @@
RegExpObject::RegExpObject(VM& vm, Structure* structure, RegExp* regExp)
: JSNonFinalObject(vm, structure)
- , m_regExp(vm, this, regExp)
- , m_lastIndexIsWritable(true)
+ , m_regExpAndLastIndexIsNotWritableFlag(bitwise_cast<uintptr_t>(regExp)) // lastIndexIsNotWritableFlag is not set.
{
m_lastIndex.setWithoutWriteBarrier(jsNumber(0));
}
@@ -56,7 +55,7 @@
RegExpObject* thisObject = jsCast<RegExpObject*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
- visitor.append(thisObject->m_regExp);
+ visitor.appendUnbarriered(thisObject->regExp());
visitor.append(thisObject->m_lastIndex);
}
@@ -65,7 +64,7 @@
VM& vm = exec->vm();
if (propertyName == vm.propertyNames->lastIndex) {
RegExpObject* regExp = jsCast<RegExpObject*>(object);
- unsigned attributes = regExp->m_lastIndexIsWritable ? PropertyAttribute::DontDelete | PropertyAttribute::DontEnum : PropertyAttribute::DontDelete | PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly;
+ unsigned attributes = regExp->lastIndexIsWritable() ? PropertyAttribute::DontDelete | PropertyAttribute::DontEnum : PropertyAttribute::DontDelete | PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly;
slot.setValue(regExp, attributes, regExp->getLastIndex());
return true;
}
@@ -117,7 +116,7 @@
return typeError(exec, scope, shouldThrow, UnconfigurablePropertyChangeEnumerabilityError);
if (descriptor.isAccessorDescriptor())
return typeError(exec, scope, shouldThrow, UnconfigurablePropertyChangeAccessMechanismError);
- if (!regExp->m_lastIndexIsWritable) {
+ if (!regExp->lastIndexIsWritable()) {
if (descriptor.writablePresent() && descriptor.writable())
return typeError(exec, scope, shouldThrow, UnconfigurablePropertyChangeWritabilityError);
if (descriptor.value() && !sameValue(exec, regExp->getLastIndex(), descriptor.value()))
@@ -129,7 +128,7 @@
RETURN_IF_EXCEPTION(scope, false);
}
if (descriptor.writablePresent() && !descriptor.writable())
- regExp->m_lastIndexIsWritable = false;
+ regExp->setLastIndexIsNotWritable();
return true;
}
Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.h (243363 => 243364)
--- trunk/Source/_javascript_Core/runtime/RegExpObject.h 2019-03-22 05:56:02 UTC (rev 243363)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.h 2019-03-22 06:45:20 UTC (rev 243364)
@@ -32,6 +32,8 @@
using Base = JSNonFinalObject;
static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames;
+ static constexpr uintptr_t lastIndexIsNotWritableFlag = 1;
+
static RegExpObject* create(VM& vm, Structure* structure, RegExp* regExp)
{
RegExpObject* object = new (NotNull, allocateCell<RegExpObject>(vm.heap)) RegExpObject(vm, structure, regExp);
@@ -46,15 +48,24 @@
return object;
}
- void setRegExp(VM& vm, RegExp* r) { m_regExp.set(vm, this, r); }
- RegExp* regExp() const { return m_regExp.get(); }
+ void setRegExp(VM& vm, RegExp* regExp)
+ {
+ uintptr_t result = (m_regExpAndLastIndexIsNotWritableFlag & lastIndexIsNotWritableFlag) | bitwise_cast<uintptr_t>(regExp);
+ m_regExpAndLastIndexIsNotWritableFlag = result;
+ vm.heap.writeBarrier(this, regExp);
+ }
+ RegExp* regExp() const
+ {
+ return bitwise_cast<RegExp*>(m_regExpAndLastIndexIsNotWritableFlag & (~lastIndexIsNotWritableFlag));
+ }
+
bool setLastIndex(ExecState* exec, size_t lastIndex)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- if (LIKELY(m_lastIndexIsWritable)) {
+ if (LIKELY(lastIndexIsWritable())) {
m_lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
return true;
}
@@ -66,11 +77,10 @@
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- if (LIKELY(m_lastIndexIsWritable)) {
+ if (LIKELY(lastIndexIsWritable())) {
m_lastIndex.set(vm, this, lastIndex);
return true;
}
-
return typeError(exec, scope, shouldThrow, ReadonlyPropertyWriteError);
}
JSValue getLastIndex() const
@@ -95,9 +105,9 @@
return Structure::create(vm, globalObject, prototype, TypeInfo(RegExpObjectType, StructureFlags), info());
}
- static ptrdiff_t offsetOfRegExp()
+ static ptrdiff_t offsetOfRegExpAndLastIndexIsNotWritableFlag()
{
- return OBJECT_OFFSETOF(RegExpObject, m_regExp);
+ return OBJECT_OFFSETOF(RegExpObject, m_regExpAndLastIndexIsNotWritableFlag);
}
static ptrdiff_t offsetOfLastIndex()
@@ -105,11 +115,6 @@
return OBJECT_OFFSETOF(RegExpObject, m_lastIndex);
}
- static ptrdiff_t offsetOfLastIndexIsWritable()
- {
- return OBJECT_OFFSETOF(RegExpObject, m_lastIndexIsWritable);
- }
-
static size_t allocationSize(Checked<size_t> inlineCapacity)
{
ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
@@ -122,6 +127,16 @@
static void visitChildren(JSCell*, SlotVisitor&);
+ bool lastIndexIsWritable() const
+ {
+ return !(m_regExpAndLastIndexIsNotWritableFlag & lastIndexIsNotWritableFlag);
+ }
+
+ void setLastIndexIsNotWritable()
+ {
+ m_regExpAndLastIndexIsNotWritableFlag = (m_regExpAndLastIndexIsNotWritableFlag | lastIndexIsNotWritableFlag);
+ }
+
JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
@@ -131,9 +146,8 @@
private:
MatchResult matchInline(ExecState*, JSGlobalObject*, JSString*);
- WriteBarrier<RegExp> m_regExp;
+ uintptr_t m_regExpAndLastIndexIsNotWritableFlag { 0 };
WriteBarrier<Unknown> m_lastIndex;
- uint8_t m_lastIndexIsWritable;
};
} // namespace JSC