Commit 887a036f authored by oliver@apple.com's avatar oliver@apple.com

2011-03-30 Oliver Hunt <oliver@apple.com>

        Reviewed by Geoffrey Garen.

        Make StructureChain GC allocated
        https://bugs.webkit.org/show_bug.cgi?id=56695

        Make StructureChain GC allocated, and make the various owners
        mark it correctly.

        * bytecode/CodeBlock.cpp:
        (JSC::CodeBlock::dump):
        (JSC::CodeBlock::derefStructures):
        (JSC::CodeBlock::refStructures):
        (JSC::CodeBlock::markAggregate):
        * bytecode/Instruction.h:
        (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
        (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
        (JSC::PolymorphicAccessStructureList::derefStructures):
        (JSC::PolymorphicAccessStructureList::markAggregate):
        (JSC::Instruction::Instruction):
        * bytecode/StructureStubInfo.cpp:
        (JSC::StructureStubInfo::deref):
        (JSC::StructureStubInfo::markAggregate):
        * bytecode/StructureStubInfo.h:
        (JSC::StructureStubInfo::initGetByIdChain):
        (JSC::StructureStubInfo::initPutByIdTransition):
        * bytecompiler/BytecodeGenerator.cpp:
        (JSC::BytecodeGenerator::emitJumpIfNotFunctionCall):
        (JSC::BytecodeGenerator::emitJumpIfNotFunctionApply):
        * interpreter/Interpreter.cpp:
        (JSC::Interpreter::privateExecute):
        * jit/JITOpcodes.cpp:
        (JSC::JIT::emit_op_jneq_ptr):
        * jit/JITOpcodes32_64.cpp:
        (JSC::JIT::emit_op_jneq_ptr):
        * jit/JITPropertyAccess.cpp:
        (JSC::JIT::privateCompileGetByIdChainList):
        * jit/JITPropertyAccess32_64.cpp:
        (JSC::JIT::privateCompileGetByIdChainList):
        * jit/JITStubs.cpp:
        (JSC::getPolymorphicAccessStructureListSlot):
        (JSC::DEFINE_STUB_FUNCTION):
        * runtime/JSCell.h:
        * runtime/JSGlobalData.cpp:
        (JSC::JSGlobalData::JSGlobalData):
        * runtime/JSGlobalData.h:
        * runtime/JSGlobalObject.cpp:
        (JSC::markIfNeeded):
        * runtime/JSGlobalObject.h:
        (JSC::Structure::prototypeChain):
        * runtime/JSObject.h:
        (JSC::JSObject::markChildrenDirect):
        * runtime/JSPropertyNameIterator.cpp:
        (JSC::JSPropertyNameIterator::create):
        (JSC::JSPropertyNameIterator::get):
        (JSC::JSPropertyNameIterator::markChildren):
        * runtime/JSPropertyNameIterator.h:
        (JSC::JSPropertyNameIterator::setCachedPrototypeChain):
        * runtime/MarkStack.h:
        (JSC::MarkStack::append):
        * runtime/Structure.h:
        (JSC::Structure::cachedPrototypeChainSlot):
        * runtime/StructureChain.cpp:
        (JSC::StructureChain::StructureChain):
        * runtime/StructureChain.h:
        (JSC::StructureChain::create):
        (JSC::StructureChain::createStructure):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@82500 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 49cf016f
2011-03-30 Oliver Hunt <oliver@apple.com>
Reviewed by Geoffrey Garen.
Make StructureChain GC allocated
https://bugs.webkit.org/show_bug.cgi?id=56695
Make StructureChain GC allocated, and make the various owners
mark it correctly.
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
(JSC::CodeBlock::derefStructures):
(JSC::CodeBlock::refStructures):
(JSC::CodeBlock::markAggregate):
* bytecode/Instruction.h:
(JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
(JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
(JSC::PolymorphicAccessStructureList::derefStructures):
(JSC::PolymorphicAccessStructureList::markAggregate):
(JSC::Instruction::Instruction):
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::deref):
(JSC::StructureStubInfo::markAggregate):
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::initGetByIdChain):
(JSC::StructureStubInfo::initPutByIdTransition):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitJumpIfNotFunctionCall):
(JSC::BytecodeGenerator::emitJumpIfNotFunctionApply):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_jneq_ptr):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_jneq_ptr):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::privateCompileGetByIdChainList):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::privateCompileGetByIdChainList):
* jit/JITStubs.cpp:
(JSC::getPolymorphicAccessStructureListSlot):
(JSC::DEFINE_STUB_FUNCTION):
* runtime/JSCell.h:
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
* runtime/JSGlobalObject.cpp:
(JSC::markIfNeeded):
* runtime/JSGlobalObject.h:
(JSC::Structure::prototypeChain):
* runtime/JSObject.h:
(JSC::JSObject::markChildrenDirect):
* runtime/JSPropertyNameIterator.cpp:
(JSC::JSPropertyNameIterator::create):
(JSC::JSPropertyNameIterator::get):
(JSC::JSPropertyNameIterator::markChildren):
* runtime/JSPropertyNameIterator.h:
(JSC::JSPropertyNameIterator::setCachedPrototypeChain):
* runtime/MarkStack.h:
(JSC::MarkStack::append):
* runtime/Structure.h:
(JSC::Structure::cachedPrototypeChainSlot):
* runtime/StructureChain.cpp:
(JSC::StructureChain::StructureChain):
* runtime/StructureChain.h:
(JSC::StructureChain::create):
(JSC::StructureChain::createStructure):
2011-03-30 Steve Falkenburg <sfalken@apple.com>
Reviewed by Adam Roben.
......
......@@ -731,7 +731,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
case op_resolve_global_dynamic: {
int r0 = (++it)->u.operand;
int id0 = (++it)->u.operand;
JSValue scope = JSValue((++it)->u.jsCell);
JSValue scope = JSValue((++it)->u.jsCell.get());
++it;
int depth = (++it)->u.operand;
printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth);
......@@ -1437,13 +1437,11 @@ void CodeBlock::derefStructures(Instruction* vPC) const
}
if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) {
vPC[4].u.structure->deref();
vPC[5].u.structureChain->deref();
return;
}
if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
vPC[4].u.structure->deref();
vPC[5].u.structure->deref();
vPC[6].u.structureChain->deref();
return;
}
if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
......@@ -1486,13 +1484,11 @@ void CodeBlock::refStructures(Instruction* vPC) const
}
if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) {
vPC[4].u.structure->ref();
vPC[5].u.structureChain->ref();
return;
}
if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
vPC[4].u.structure->ref();
vPC[5].u.structure->ref();
vPC[6].u.structureChain->ref();
return;
}
if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
......@@ -1527,6 +1523,20 @@ void CodeBlock::markAggregate(MarkStack& markStack)
if (callLinkInfo(i).isLinked())
markStack.append(&callLinkInfo(i).callee);
#endif
#if ENABLE(INTERPRETER)
Interpreter* interpreter = m_globalData->interpreter;
for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {
Instruction* vPC = &m_instructions[m_propertyAccessInstructions[i]];
if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain))
markStack.append(&vPC[5].u.structureChain);
else if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition))
markStack.append(&vPC[6].u.structureChain);
}
#endif
#if ENABLE(JIT)
for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
m_structureStubInfos[i].markAggregate(markStack);
#endif
}
HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
......
......@@ -63,7 +63,7 @@ namespace JSC {
Structure* base;
union {
Structure* proto;
StructureChain* chain;
WriteBarrierBase<StructureChain> chain;
} u;
void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
......@@ -82,11 +82,11 @@ namespace JSC {
isChain = false;
}
void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
{
stubRoutine = _stubRoutine;
base = _base;
u.chain = _chain;
u.chain.set(globalData, owner, _chain);
isChain = true;
}
} list[POLYMORPHIC_LIST_CACHE_SIZE];
......@@ -101,9 +101,9 @@ namespace JSC {
list[0].set(stubRoutine, firstBase, firstProto);
}
PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain)
PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain)
{
list[0].set(stubRoutine, firstBase, firstChain);
list[0].set(globalData, owner, stubRoutine, firstBase, firstChain);
}
void derefStructures(int count)
......@@ -115,13 +115,22 @@ namespace JSC {
info.base->deref();
if (info.u.proto) {
if (info.isChain)
info.u.chain->deref();
else
if (!info.isChain)
info.u.proto->deref();
}
}
}
void markAggregate(MarkStack& markStack, int count)
{
for (int i = 0; i < count; ++i) {
PolymorphicStubInfo& info = list[i];
ASSERT(info.base);
if (info.u.proto && info.isChain)
markStack.append(&info.u.chain);
}
}
};
struct Instruction {
......@@ -130,7 +139,7 @@ namespace JSC {
#if !ENABLE(COMPUTED_GOTO_INTERPRETER)
// We have to initialize one of the pointer members to ensure that
// the entire struct is initialized, when opcode is not a pointer.
u.jsCell = 0;
u.jsCell.clear();
#endif
u.opcode = opcode;
}
......@@ -139,13 +148,21 @@ namespace JSC {
{
// We have to initialize one of the pointer members to ensure that
// the entire struct is initialized in 64-bit.
u.jsCell = 0;
u.jsCell.clear();
u.operand = operand;
}
Instruction(Structure* structure) { u.structure = structure; }
Instruction(StructureChain* structureChain) { u.structureChain = structureChain; }
Instruction(JSCell* jsCell) { u.jsCell = jsCell; }
Instruction(JSGlobalData& globalData, JSCell* owner, StructureChain* structureChain)
{
u.structureChain.clear();
u.structureChain.set(globalData, owner, structureChain);
}
Instruction(JSGlobalData& globalData, JSCell* owner, JSCell* jsCell)
{
u.jsCell.clear();
u.jsCell.set(globalData, owner, jsCell);
}
Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; }
Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
......@@ -153,8 +170,8 @@ namespace JSC {
Opcode opcode;
int operand;
Structure* structure;
StructureChain* structureChain;
JSCell* jsCell;
WriteBarrierBase<StructureChain> structureChain;
WriteBarrierBase<JSCell> jsCell;
PolymorphicAccessStructureList* polymorphicStructures;
PropertySlot::GetValueFunc getterFunc;
} u;
......
......@@ -44,7 +44,6 @@ void StructureStubInfo::deref()
return;
case access_get_by_id_chain:
u.getByIdChain.baseObjectStructure->deref();
u.getByIdChain.chain->deref();
return;
case access_get_by_id_self_list: {
PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
......@@ -61,7 +60,6 @@ void StructureStubInfo::deref()
case access_put_by_id_transition:
u.putByIdTransition.previousStructure->deref();
u.putByIdTransition.structure->deref();
u.putByIdTransition.chain->deref();
return;
case access_put_by_id_replace:
u.putByIdReplace.baseObjectStructure->deref();
......@@ -78,6 +76,42 @@ void StructureStubInfo::deref()
ASSERT_NOT_REACHED();
}
}
void StructureStubInfo::markAggregate(MarkStack& markStack)
{
switch (accessType) {
case access_get_by_id_self:
return;
case access_get_by_id_proto:
return;
case access_get_by_id_chain:
return;
case access_get_by_id_self_list: {
PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
polymorphicStructures->markAggregate(markStack, u.getByIdSelfList.listSize);
return;
}
case access_get_by_id_proto_list: {
PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
polymorphicStructures->markAggregate(markStack, u.getByIdProtoList.listSize);
return;
}
case access_put_by_id_transition:
return;
case access_put_by_id_replace:
return;
case access_get_by_id:
case access_put_by_id:
case access_get_by_id_generic:
case access_put_by_id_generic:
case access_get_array_length:
case access_get_string_length:
// These instructions don't ref their Structures.
return;
default:
ASSERT_NOT_REACHED();
}
}
#endif
} // namespace JSC
......@@ -85,7 +85,6 @@ namespace JSC {
baseObjectStructure->ref();
u.getByIdChain.chain = chain;
chain->ref();
}
void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
......@@ -117,7 +116,6 @@ namespace JSC {
structure->ref();
u.putByIdTransition.chain = chain;
chain->ref();
}
void initPutByIdReplace(Structure* baseObjectStructure)
......@@ -129,6 +127,7 @@ namespace JSC {
}
void deref();
void markAggregate(MarkStack&);
bool seenOnce()
{
......
......@@ -925,7 +925,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond,
emitOpcode(op_jneq_ptr);
instructions().append(cond->index());
instructions().append(m_scopeChain->globalObject->callFunction());
instructions().append(Instruction(*m_globalData, m_codeBlock->ownerExecutable(), m_scopeChain->globalObject->callFunction()));
instructions().append(target->bind(begin, instructions().size()));
return target;
}
......@@ -936,7 +936,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond
emitOpcode(op_jneq_ptr);
instructions().append(cond->index());
instructions().append(m_scopeChain->globalObject->applyFunction());
instructions().append(Instruction(*m_globalData, m_codeBlock->ownerExecutable(), m_scopeChain->globalObject->applyFunction()));
instructions().append(target->bind(begin, instructions().size()));
return target;
}
......
......@@ -3537,10 +3537,9 @@ skip_id_custom_self:
to ptr, using pointer equality.
*/
int src = vPC[1].u.operand;
JSValue ptr = JSValue(vPC[2].u.jsCell);
int target = vPC[3].u.operand;
JSValue srcValue = callFrame->r(src).jsValue();
if (srcValue != ptr) {
if (srcValue != vPC[2].u.jsCell.get()) {
vPC += target;
NEXT_INSTRUCTION();
}
......
......@@ -762,7 +762,7 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)
void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
{
unsigned src = currentInstruction[1].u.operand;
JSCell* ptr = currentInstruction[2].u.jsCell;
JSCell* ptr = currentInstruction[2].u.jsCell.get();
unsigned target = currentInstruction[3].u.operand;
emitGetVirtualRegister(src, regT0);
......
......@@ -979,7 +979,7 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)
void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
{
unsigned src = currentInstruction[1].u.operand;
JSCell* ptr = currentInstruction[2].u.jsCell;
JSCell* ptr = currentInstruction[2].u.jsCell.get();
unsigned target = currentInstruction[3].u.operand;
emitLoad(src, regT1, regT0);
......
......@@ -979,8 +979,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
// Track the stub we have created so that it will be deleted later.
structure->ref();
chain->ref();
prototypeStructures->list[currentIndex].set(entryLabel, structure, chain);
prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, chain);
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
......
......@@ -1007,8 +1007,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
// Track the stub we have created so that it will be deleted later.
structure->ref();
chain->ref();
prototypeStructures->list[currentIndex].set(entryLabel, structure, chain);
prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, chain);
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
......
......@@ -1553,7 +1553,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
return JSValue::encode(result);
}
static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex)
static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(JSGlobalData& globalData, ScriptExecutable* owner, StructureStubInfo* stubInfo, int& listIndex)
{
PolymorphicAccessStructureList* prototypeStructureList = 0;
listIndex = 1;
......@@ -1565,7 +1565,7 @@ static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(Str
stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
break;
case access_get_by_id_chain:
prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
stubInfo->stubRoutine = CodeLocationLabel();
stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
break;
......@@ -1653,7 +1653,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
}
int listIndex;
PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex);
if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
......@@ -1663,7 +1663,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
} else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
ASSERT(!baseValue.asCell()->structure()->isDictionary());
int listIndex;
PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex);
if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
StructureChain* protoChain = structure->prototypeChain(callFrame);
......
......@@ -68,6 +68,7 @@ namespace JSC {
friend class MarkedSpace;
friend class MarkedBlock;
friend class ScopeChainNode;
friend class StructureChain;
private:
explicit JSCell(Structure*);
......
......@@ -184,6 +184,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
programExecutableStructure = ProgramExecutable::createStructure(*this, jsNull());
functionExecutableStructure = FunctionExecutable::createStructure(*this, jsNull());
dummyMarkableCellStructure = JSCell::createDummyStructure(*this);
structureChainStructure = StructureChain::createStructure(*this, jsNull());
interpreter = new Interpreter(*this);
if (globalDataType == Default)
......
......@@ -161,6 +161,7 @@ namespace JSC {
RefPtr<Structure> programExecutableStructure;
RefPtr<Structure> functionExecutableStructure;
RefPtr<Structure> dummyMarkableCellStructure;
RefPtr<Structure> structureChainStructure;
static void storeVPtrs();
static JS_EXPORTDATA void* jsArrayVPtr;
......
......@@ -88,6 +88,8 @@ static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s
{
if (s && s->storedPrototype())
markStack.append(s->storedPrototypeSlot());
if (s && *s->cachedPrototypeChainSlot())
markStack.append(s->cachedPrototypeChainSlot());
}
JSGlobalObject::~JSGlobalObject()
......
......@@ -28,6 +28,7 @@
#include "JSWeakObjectMapRefInternal.h"
#include "NumberPrototype.h"
#include "StringPrototype.h"
#include "StructureChain.h"
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/RandomNumber.h>
......@@ -362,7 +363,7 @@ namespace JSC {
// We cache our prototype chain so our clients can share it.
if (!isValid(exec, m_cachedPrototypeChain.get())) {
JSValue prototype = prototypeForLookup(exec);
m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure());
m_cachedPrototypeChain = StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure());
}
return m_cachedPrototypeChain.get();
}
......
......@@ -814,8 +814,10 @@ inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack)
{
JSCell::markChildren(markStack);
markStack.append(m_structure->storedPrototypeSlot());
if (*m_structure->cachedPrototypeChainSlot())
markStack.append(m_structure->cachedPrototypeChainSlot());
PropertyStorage storage = propertyStorage();
size_t storageSize = m_structure->propertyStorageSize();
markStack.appendValues(storage, storageSize);
......
......@@ -77,7 +77,7 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject
return jsPropertyNameIterator;
}
jsPropertyNameIterator->setCachedPrototypeChain(structureChain);
jsPropertyNameIterator->setCachedPrototypeChain(exec->globalData(), structureChain);
jsPropertyNameIterator->setCachedStructure(o->structure());
o->structure()->setEnumerationCache(exec->globalData(), jsPropertyNameIterator);
return jsPropertyNameIterator;
......@@ -86,7 +86,7 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject
JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
{
JSValue identifier = m_jsStrings[i].get();
if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec))
if (m_cachedStructure == base->structure() && m_cachedPrototypeChain.get() == base->structure()->prototypeChain(exec))
return identifier;
if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec))))
......@@ -97,6 +97,8 @@ JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
void JSPropertyNameIterator::markChildren(MarkStack& markStack)
{
markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
if (m_cachedPrototypeChain)
markStack.append(&m_cachedPrototypeChain);
}
#if !ASSERT_DISABLED
......
......@@ -73,7 +73,7 @@ namespace JSC {
}
Structure* cachedStructure() { return m_cachedStructure.get(); }
void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
void setCachedPrototypeChain(JSGlobalData& globalData, StructureChain* cachedPrototypeChain) { m_cachedPrototypeChain.set(globalData, this, cachedPrototypeChain); }
StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
private:
......@@ -84,7 +84,7 @@ namespace JSC {
#endif
RefPtr<Structure> m_cachedStructure;
RefPtr<StructureChain> m_cachedPrototypeChain;
WriteBarrier<StructureChain> m_cachedPrototypeChain;
uint32_t m_numCacheableSlots;
uint32_t m_jsStringsSize;
OwnArrayPtr<WriteBarrier<Unknown> > m_jsStrings;
......
......@@ -215,12 +215,12 @@ namespace JSC {
template <typename T> inline void MarkStack::append(DeprecatedPtr<T>* slot)
{
internalAppend(slot->get());
internalAppend(*slot->slot());
}
template <typename T> inline void MarkStack::append(WriteBarrierBase<T>* slot)
{
internalAppend(slot->get());
internalAppend(*slot->slot());
}
ALWAYS_INLINE void MarkStack::deprecatedAppend(JSCell** value)
......
......@@ -32,7 +32,6 @@
#include "PropertyMapHashTable.h"
#include "PropertyNameArray.h"
#include "Protect.h"
#include "StructureChain.h"
#include "StructureTransitionTable.h"
#include "JSTypeInfo.h"
#include "UString.h"
......@@ -46,6 +45,7 @@ namespace JSC {
class MarkStack;
class PropertyNameArray;
class PropertyNameArrayData;
class StructureChain;
struct ClassInfo;
......@@ -107,6 +107,7 @@ namespace JSC {
DeprecatedPtr<Unknown>* storedPrototypeSlot() { return &m_prototype; }
JSValue prototypeForLookup(ExecState*) const;
StructureChain* prototypeChain(ExecState*) const;
DeprecatedPtr<StructureChain>* cachedPrototypeChainSlot() { return &m_cachedPrototypeChain; }
Structure* previousID() const { return m_previous.get(); }
......@@ -210,7 +211,7 @@ namespace JSC {
TypeInfo m_typeInfo;
DeprecatedPtr<Unknown> m_prototype;
mutable RefPtr<StructureChain> m_cachedPrototypeChain;
mutable DeprecatedPtr<StructureChain> m_cachedPrototypeChain;
RefPtr<Structure> m_previous;
RefPtr<StringImpl> m_nameInPrevious;
......
......@@ -32,7 +32,8 @@
namespace JSC {
StructureChain::StructureChain(Structure* head)
StructureChain::StructureChain(NonNullPassRefPtr<Structure> structure, Structure* head)
: JSCell(structure.releaseRef())
{
size_t size = 0;
for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
......
......@@ -26,6 +26,8 @@
#ifndef StructureChain_h
#define StructureChain_h
#include "JSCell.h"
#include <wtf/OwnArrayPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
......@@ -35,15 +37,16 @@ namespace JSC {