Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (253930 => 253931)
--- trunk/Source/_javascript_Core/ChangeLog 2019-12-29 03:39:27 UTC (rev 253930)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-12-29 04:47:44 UTC (rev 253931)
@@ -1,3 +1,28 @@
+2019-12-28 Yusuke Suzuki <[email protected]>
+
+ [JSC] StructureChain should hold vector of StructureID
+ https://bugs.webkit.org/show_bug.cgi?id=205592
+
+ Reviewed by Mark Lam.
+
+ StructureChain should keep vector of StructureID instead of Structure* to minimize the size of vector.
+
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/JSPropertyNameEnumerator.h:
+ (JSC::propertyNameEnumerator):
+ * runtime/ProxyObject.h:
+ * runtime/Structure.cpp:
+ (JSC::Structure::canCachePropertyNameEnumerator const):
+ * runtime/Structure.h:
+ * runtime/StructureChain.cpp:
+ (JSC::StructureChain::StructureChain):
+ (JSC::StructureChain::create):
+ (JSC::StructureChain::finishCreation):
+ (JSC::StructureChain::visitChildren):
+ * runtime/StructureChain.h:
+ * runtime/StructureInlines.h:
+ (JSC::Structure::isValid const):
+
2019-12-25 Yusuke Suzuki <[email protected]>
[JSC] Compact Bytecodes more by emitting 1-byte Opcode
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (253930 => 253931)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2019-12-29 03:39:27 UTC (rev 253930)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2019-12-29 04:47:44 UTC (rev 253931)
@@ -1448,11 +1448,20 @@
loadp OpPutById::Metadata::m_structureChain[t5], t3
btpz t3, .opPutByIdTransitionDirect
- structureIDToStructureWithScratch(t2, t1, t3)
+ loadp CodeBlock[cfr], t1
+ loadp CodeBlock::m_vm[t1], t1
+ loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[t1], t1
- # reload the StructureChain since we used t3 as a scratch above
- loadp OpPutById::Metadata::m_structureChain[t5], t3
+ macro structureIDToStructureWithScratchAndTable(structureIDThenStructure, table, scratch)
+ move structureIDThenStructure, scratch
+ rshifti NumberOfStructureIDEntropyBits, scratch
+ loadp [table, scratch, PtrSize], scratch
+ lshiftp StructureEntropyBitsShift, structureIDThenStructure
+ xorp scratch, structureIDThenStructure
+ end
+ structureIDToStructureWithScratchAndTable(t2, t1, t0)
+
loadp StructureChain::m_vector[t3], t3
assert(macro (ok) btpnz t3, ok end)
@@ -1459,20 +1468,19 @@
loadq Structure::m_prototype[t2], t2
bqeq t2, ValueNull, .opPutByIdTransitionChainDone
.opPutByIdTransitionChainLoop:
- # At this point, t2 contains a prototye, and [t3] contains the Structure* that we want that
- # prototype to have. We don't want to have to load the Structure* for t2. Instead, we load
- # the Structure* from [t3], and then we compare its id to the id in the header of t2.
- loadp [t3], t1
loadi JSCell::m_structureID[t2], t2
- # Now, t1 has the Structure* and t2 has the StructureID that we want that Structure* to have.
- bineq t2, Structure::m_blob + StructureIDBlob::u.fields.structureID[t1], .opPutByIdSlow
- addp PtrSize, t3
- loadq Structure::m_prototype[t1], t2
+ bineq t2, [t3], .opPutByIdSlow
+ addp 4, t3
+ structureIDToStructureWithScratchAndTable(t2, t1, t0)
+ loadq Structure::m_prototype[t2], t2
bqneq t2, ValueNull, .opPutByIdTransitionChainLoop
.opPutByIdTransitionChainDone:
# Reload the new structure, since we clobbered it above.
loadi OpPutById::Metadata::m_newStructureID[t5], t1
+ # Reload base into t0
+ get(m_base, t3)
+ loadConstantOrVariable(size, t3, t0)
.opPutByIdTransitionDirect:
storei t1, JSCell::m_structureID[t0]
Modified: trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.h (253930 => 253931)
--- trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.h 2019-12-29 03:39:27 UTC (rev 253930)
+++ trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.h 2019-12-29 04:47:44 UTC (rev 253931)
@@ -142,7 +142,7 @@
enumerator = JSPropertyNameEnumerator::create(vm, structureAfterGettingPropertyNames, indexedLength, numberStructureProperties, WTFMove(propertyNames));
if (!indexedLength && successfullyNormalizedChain && structureAfterGettingPropertyNames == structure) {
enumerator->setCachedPrototypeChain(vm, structure->prototypeChain(globalObject, base));
- if (structure->canCachePropertyNameEnumerator())
+ if (structure->canCachePropertyNameEnumerator(vm))
structure->setCachedPropertyNameEnumerator(vm, enumerator);
}
return enumerator;
Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.h (253930 => 253931)
--- trunk/Source/_javascript_Core/runtime/ProxyObject.h 2019-12-29 03:39:27 UTC (rev 253930)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.h 2019-12-29 04:47:44 UTC (rev 253931)
@@ -59,7 +59,7 @@
Structure* result = Structure::create(vm, globalObject, prototype, TypeInfo(ProxyObjectType, flags), info(), NonArray | MayHaveIndexedAccessors);
result->setIsQuickPropertyAccessAllowedForEnumeration(false);
RELEASE_ASSERT(!result->canAccessPropertiesQuicklyForEnumeration());
- RELEASE_ASSERT(!result->canCachePropertyNameEnumerator());
+ RELEASE_ASSERT(!result->canCachePropertyNameEnumerator(vm));
return result;
}
Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (253930 => 253931)
--- trunk/Source/_javascript_Core/runtime/Structure.cpp 2019-12-29 03:39:27 UTC (rev 253930)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp 2019-12-29 04:47:44 UTC (rev 253931)
@@ -1207,7 +1207,7 @@
return rareData()->cachedPropertyNameEnumerator();
}
-bool Structure::canCachePropertyNameEnumerator() const
+bool Structure::canCachePropertyNameEnumerator(VM& vm) const
{
if (!this->canCacheOwnKeys())
return false;
@@ -1214,13 +1214,15 @@
StructureChain* structureChain = m_cachedPrototypeChain.get();
ASSERT(structureChain);
- WriteBarrier<Structure>* structure = structureChain->head();
+ StructureID* currentStructureID = structureChain->head();
while (true) {
- if (!structure->get())
+ StructureID structureID = *currentStructureID;
+ if (!structureID)
return true;
- if (!structure->get()->canCacheOwnKeys())
+ Structure* structure = vm.getStructure(structureID);
+ if (!structure->canCacheOwnKeys())
return false;
- structure++;
+ currentStructureID++;
}
ASSERT_NOT_REACHED();
Modified: trunk/Source/_javascript_Core/runtime/Structure.h (253930 => 253931)
--- trunk/Source/_javascript_Core/runtime/Structure.h 2019-12-29 03:39:27 UTC (rev 253930)
+++ trunk/Source/_javascript_Core/runtime/Structure.h 2019-12-29 04:47:44 UTC (rev 253931)
@@ -476,7 +476,7 @@
void setCachedPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
JSPropertyNameEnumerator* cachedPropertyNameEnumerator() const;
- bool canCachePropertyNameEnumerator() const;
+ bool canCachePropertyNameEnumerator(VM&) const;
bool canAccessPropertiesQuicklyForEnumeration() const;
void setCachedOwnKeys(VM&, JSImmutableButterfly*);
Modified: trunk/Source/_javascript_Core/runtime/StructureChain.cpp (253930 => 253931)
--- trunk/Source/_javascript_Core/runtime/StructureChain.cpp 2019-12-29 03:39:27 UTC (rev 253930)
+++ trunk/Source/_javascript_Core/runtime/StructureChain.cpp 2019-12-29 04:47:44 UTC (rev 253931)
@@ -34,7 +34,7 @@
const ClassInfo StructureChain::s_info = { "StructureChain", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(StructureChain) };
-StructureChain::StructureChain(VM& vm, Structure* structure, WriteBarrier<Structure>* vector)
+StructureChain::StructureChain(VM& vm, Structure* structure, StructureID* vector)
: Base(vm, structure)
, m_vector(vm, this, vector)
{
@@ -49,9 +49,9 @@
for (JSObject* current = head; current; current = current->structure(vm)->storedPrototypeObject(current))
++size;
++size; // Sentinel nullptr.
- WriteBarrier<Structure>* vector = static_cast<WriteBarrier<Structure>*>(vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(vm, (Checked<size_t>(size) * sizeof(WriteBarrier<Structure>)).unsafeGet(), nullptr, AllocationFailureMode::Assert));
- for (size_t i = 0; i < size; ++i)
- vector[i].clear();
+ size_t bytes = (Checked<size_t>(size) * sizeof(StructureID)).unsafeGet();
+ StructureID* vector = static_cast<StructureID*>(vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(vm, bytes, nullptr, AllocationFailureMode::Assert));
+ memset(vector, 0, bytes);
StructureChain* chain = new (NotNull, allocateCell<StructureChain>(vm.heap)) StructureChain(vm, vm.structureChainStructure.get(), vector);
chain->finishCreation(vm, head);
return chain;
@@ -61,8 +61,11 @@
{
Base::finishCreation(vm);
size_t i = 0;
- for (JSObject* current = head; current; current = current->structure(vm)->storedPrototypeObject(current))
- m_vector.get()[i++].set(vm, this, current->structure(vm));
+ for (JSObject* current = head; current; current = current->structure(vm)->storedPrototypeObject(current)) {
+ Structure* structure = current->structure(vm);
+ m_vector.get()[i++] = structure->id();
+ vm.heap.writeBarrier(this);
+ }
}
void StructureChain::visitChildren(JSCell* cell, SlotVisitor& visitor)
@@ -71,8 +74,12 @@
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
visitor.markAuxiliary(thisObject->m_vector.get());
- for (auto* current = thisObject->m_vector.get(); *current; ++current)
- visitor.append(*current);
+ VM& vm = visitor.vm();
+ for (auto* current = thisObject->m_vector.get(); *current; ++current) {
+ StructureID structureID = *current;
+ Structure* structure = vm.getStructure(structureID);
+ visitor.appendUnbarriered(structure);
+ }
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/StructureChain.h (253930 => 253931)
--- trunk/Source/_javascript_Core/runtime/StructureChain.h 2019-12-29 03:39:27 UTC (rev 253930)
+++ trunk/Source/_javascript_Core/runtime/StructureChain.h 2019-12-29 04:47:44 UTC (rev 253931)
@@ -50,7 +50,7 @@
}
static StructureChain* create(VM&, JSObject*);
- WriteBarrier<Structure>* head() { return m_vector.get(); }
+ StructureID* head() { return m_vector.get(); }
static void visitChildren(JSCell*, SlotVisitor&);
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
@@ -65,8 +65,8 @@
void finishCreation(VM&, JSObject* head);
- StructureChain(VM&, Structure*, WriteBarrier<Structure>*);
- AuxiliaryBarrier<WriteBarrier<Structure>*> m_vector;
+ StructureChain(VM&, Structure*, StructureID*);
+ AuxiliaryBarrier<StructureID*> m_vector;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/StructureInlines.h (253930 => 253931)
--- trunk/Source/_javascript_Core/runtime/StructureInlines.h 2019-12-29 03:39:27 UTC (rev 253930)
+++ trunk/Source/_javascript_Core/runtime/StructureInlines.h 2019-12-29 04:47:44 UTC (rev 253931)
@@ -313,9 +313,9 @@
VM& vm = globalObject->vm();
JSValue prototype = prototypeForLookup(globalObject, base);
- WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
+ StructureID* cachedStructure = cachedPrototypeChain->head();
while (*cachedStructure && !prototype.isNull()) {
- if (asObject(prototype)->structure(vm) != cachedStructure->get())
+ if (asObject(prototype)->structureID() != *cachedStructure)
return false;
++cachedStructure;
prototype = asObject(prototype)->getPrototypeDirect(vm);