diff options
Diffstat (limited to 'Source/JavaScriptCore/bytecode')
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlock.cpp | 73 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlock.h | 131 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/EvalCodeCache.h | 16 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/Instruction.h | 45 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/SamplingTool.h | 9 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/StructureStubInfo.cpp | 39 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/StructureStubInfo.h | 3 |
7 files changed, 162 insertions, 154 deletions
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 2d235df..98bbb3c 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -364,7 +364,7 @@ void CodeBlock::dump(ExecState* exec) const unsigned registerIndex = m_numVars; size_t i = 0; do { - printf(" k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).utf8().data()); + printf(" k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data()); ++i; ++registerIndex; } while (i < m_constantRegisters.size()); @@ -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); @@ -1360,13 +1360,13 @@ void CodeBlock::dumpStatistics() } CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor) - : m_globalObject(globalObject) + : m_globalObject(globalObject->globalData(), ownerExecutable, globalObject) , m_heap(&m_globalObject->globalData().heap) , m_numCalleeRegisters(0) , m_numVars(0) , m_numParameters(0) , m_isConstructor(isConstructor) - , m_ownerExecutable(ownerExecutable) + , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable) , m_globalData(0) #ifndef NDEBUG , m_instructionCount(0) @@ -1406,12 +1406,6 @@ CodeBlock::~CodeBlock() for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) m_structureStubInfos[i].deref(); - for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) { - CallLinkInfo* callLinkInfo = &m_callLinkInfos[i]; - if (callLinkInfo->isLinked()) - callLinkInfo->callee->removeCaller(callLinkInfo); - } - for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) { if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) { structure->deref(); @@ -1421,10 +1415,6 @@ CodeBlock::~CodeBlock() } } -#if ENABLE(JIT_OPTIMIZE_CALL) - unlinkCallers(); -#endif - #endif // ENABLE(JIT) #if DUMP_CODE_BLOCK_STATISTICS @@ -1432,19 +1422,6 @@ CodeBlock::~CodeBlock() #endif } -#if ENABLE(JIT_OPTIMIZE_CALL) -void CodeBlock::unlinkCallers() -{ - size_t size = m_linkedCallerList.size(); - for (size_t i = 0; i < size; ++i) { - CallLinkInfo* currentCaller = m_linkedCallerList[i]; - JIT::unlinkCallOrConstruct(currentCaller); - currentCaller->setUnlinked(); - } - m_linkedCallerList.clear(); -} -#endif - void CodeBlock::derefStructures(Instruction* vPC) const { Interpreter* interpreter = m_globalData->interpreter; @@ -1460,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)) { @@ -1509,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,14 +1500,43 @@ void CodeBlock::refStructures(Instruction* vPC) const ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic)); } +void EvalCodeCache::markAggregate(MarkStack& markStack) +{ + EvalCacheMap::iterator end = m_cacheMap.end(); + for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr) + markStack.append(&ptr->second); +} + void CodeBlock::markAggregate(MarkStack& markStack) { - for (size_t i = 0; i < m_constantRegisters.size(); ++i) - markStack.deprecatedAppend(&m_constantRegisters[i]); + markStack.append(&m_globalObject); + markStack.append(&m_ownerExecutable); + if (m_rareData) + m_rareData->m_evalCodeCache.markAggregate(markStack); + markStack.appendValues(m_constantRegisters.data(), m_constantRegisters.size()); for (size_t i = 0; i < m_functionExprs.size(); ++i) - m_functionExprs[i]->markAggregate(markStack); + markStack.append(&m_functionExprs[i]); for (size_t i = 0; i < m_functionDecls.size(); ++i) - m_functionDecls[i]->markAggregate(markStack); + markStack.append(&m_functionDecls[i]); +#if ENABLE(JIT_OPTIMIZE_CALL) + for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) + 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) @@ -1671,7 +1673,6 @@ void CodeBlock::shrinkToFit() m_structureStubInfos.shrinkToFit(); m_globalResolveInfos.shrinkToFit(); m_callLinkInfos.shrinkToFit(); - m_linkedCallerList.shrinkToFit(); #endif m_identifiers.shrinkToFit(); diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index bef4561..25e65f4 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -96,21 +96,17 @@ namespace JSC { #if ENABLE(JIT) struct CallLinkInfo { CallLinkInfo() - : callee(0) - , position(0) - , hasSeenShouldRepatch(0) + : hasSeenShouldRepatch(false) { } CodeLocationNearCall callReturnLocation; CodeLocationDataLabelPtr hotPathBegin; CodeLocationNearCall hotPathOther; - CodeBlock* ownerCodeBlock; - CodeBlock* callee; - unsigned position : 31; - unsigned hasSeenShouldRepatch : 1; + WriteBarrier<JSFunction> callee; + bool hasSeenShouldRepatch; - void setUnlinked() { callee = 0; } + void setUnlinked() { callee.clear(); } bool isLinked() { return callee; } bool seenOnce() @@ -183,7 +179,7 @@ namespace JSC { unsigned bytecodeOffset; }; - // valueAtPosition helpers for the binaryChop algorithm below. + // valueAtPosition helpers for the binarySearch algorithm. inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo) { @@ -204,42 +200,6 @@ namespace JSC { { return pc->callReturnOffset; } - - // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array, - // compares result with key (KeyTypes should be comparable with '--', '<', '>'). - // Optimized for cases where the array contains the key, checked by assertions. - template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)> - inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key) - { - // The array must contain at least one element (pre-condition, array does conatin key). - // If the array only contains one element, no need to do the comparison. - while (size > 1) { - // Pick an element to check, half way through the array, and read the value. - int pos = (size - 1) >> 1; - KeyType val = valueAtPosition(&array[pos]); - - // If the key matches, success! - if (val == key) - return &array[pos]; - // The item we are looking for is smaller than the item being check; reduce the value of 'size', - // chopping off the right hand half of the array. - else if (key < val) - size = pos; - // Discard all values in the left hand half of the array, up to and including the item at pos. - else { - size -= (pos + 1); - array += (pos + 1); - } - - // 'size' should never reach zero. - ASSERT(size); - } - - // If we reach this point we've chopped down to one element, no need to check it matches - ASSERT(size == 1); - ASSERT(key == valueAtPosition(&array[0])); - return &array[0]; - } #endif class CodeBlock { @@ -248,7 +208,7 @@ namespace JSC { protected: CodeBlock(ScriptExecutable* ownerExecutable, CodeType, JSGlobalObject*, PassRefPtr<SourceProvider>, unsigned sourceOffset, SymbolTable* symbolTable, bool isConstructor); - DeprecatedPtr<JSGlobalObject> m_globalObject; + WriteBarrier<JSGlobalObject> m_globalObject; Heap* m_heap; public: @@ -257,9 +217,6 @@ namespace JSC { void markAggregate(MarkStack&); void refStructures(Instruction* vPC) const; void derefStructures(Instruction* vPC) const; -#if ENABLE(JIT_OPTIMIZE_CALL) - void unlinkCallers(); -#endif static void dumpStatistics(); @@ -292,38 +249,20 @@ namespace JSC { void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset); #if ENABLE(JIT) - void addCaller(CallLinkInfo* caller) - { - caller->callee = this; - caller->position = m_linkedCallerList.size(); - m_linkedCallerList.append(caller); - } - - void removeCaller(CallLinkInfo* caller) - { - unsigned pos = caller->position; - unsigned lastPos = m_linkedCallerList.size() - 1; - - if (pos != lastPos) { - m_linkedCallerList[pos] = m_linkedCallerList[lastPos]; - m_linkedCallerList[pos]->position = pos; - } - m_linkedCallerList.shrink(lastPos); - } StructureStubInfo& getStubInfo(ReturnAddressPtr returnAddress) { - return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value())); + return *(binarySearch<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value())); } CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress) { - return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value())); + return *(binarySearch<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value())); } MethodCallLinkInfo& getMethodCallLinkInfo(ReturnAddressPtr returnAddress) { - return *(binaryChop<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value())); + return *(binarySearch<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value())); } unsigned bytecodeOffset(ReturnAddressPtr returnAddress) @@ -333,7 +272,7 @@ namespace JSC { Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector; if (!callIndices.size()) return 1; - return binaryChop<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset; + return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset; } #endif #if ENABLE(INTERPRETER) @@ -359,7 +298,7 @@ namespace JSC { ExecutablePool* executablePool() { return getJITCode().getExecutablePool(); } #endif - ScriptExecutable* ownerExecutable() const { return m_ownerExecutable; } + ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); } void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; } @@ -451,6 +390,8 @@ namespace JSC { bool hasExpressionInfo() { return m_rareData && m_rareData->m_expressionInfo.size(); } bool hasLineInfo() { return m_rareData && m_rareData->m_lineInfo.size(); } + // We only generate exception handling info if the user is debugging + // (and may want line number info), or if the function contains exception handler. bool needsCallReturnIndices() { return m_rareData && @@ -472,18 +413,34 @@ namespace JSC { Identifier& identifier(int index) { return m_identifiers[index]; } size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); } - void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); } - Register& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; } + void addConstant(JSValue v) + { + m_constantRegisters.append(WriteBarrier<Unknown>()); + m_constantRegisters.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), v); + } + WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; } ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; } - ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); } + ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); } - unsigned addFunctionDecl(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionDecls.size(); m_functionDecls.append(n); return size; } + unsigned addFunctionDecl(FunctionExecutable* n) + { + unsigned size = m_functionDecls.size(); + m_functionDecls.append(WriteBarrier<FunctionExecutable>()); + m_functionDecls.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), n); + return size; + } FunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); } int numberOfFunctionDecls() { return m_functionDecls.size(); } - unsigned addFunctionExpr(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionExprs.size(); m_functionExprs.append(n); return size; } + unsigned addFunctionExpr(FunctionExecutable* n) + { + unsigned size = m_functionExprs.size(); + m_functionExprs.append(WriteBarrier<FunctionExecutable>()); + m_functionExprs.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), n); + return size; + } FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); } - unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; } + unsigned addRegExp(PassRefPtr<RegExp> r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; } RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); } JSGlobalObject* globalObject() { return m_globalObject.get(); } @@ -536,7 +493,7 @@ namespace JSC { m_rareData = adoptPtr(new RareData); } - ScriptExecutable* m_ownerExecutable; + WriteBarrier<ScriptExecutable> m_ownerExecutable; JSGlobalData* m_globalData; Vector<Instruction> m_instructions; @@ -567,16 +524,16 @@ namespace JSC { Vector<GlobalResolveInfo> m_globalResolveInfos; Vector<CallLinkInfo> m_callLinkInfos; Vector<MethodCallLinkInfo> m_methodCallLinkInfos; - Vector<CallLinkInfo*> m_linkedCallerList; #endif Vector<unsigned> m_jumpTargets; // Constant Pool Vector<Identifier> m_identifiers; - Vector<Register> m_constantRegisters; - Vector<RefPtr<FunctionExecutable> > m_functionDecls; - Vector<RefPtr<FunctionExecutable> > m_functionExprs; + COMPILE_ASSERT(sizeof(Register) == sizeof(WriteBarrier<Unknown>), Register_must_be_same_size_as_WriteBarrier_Unknown); + Vector<WriteBarrier<Unknown> > m_constantRegisters; + Vector<WriteBarrier<FunctionExecutable> > m_functionDecls; + Vector<WriteBarrier<FunctionExecutable> > m_functionExprs; SymbolTable* m_symbolTable; @@ -617,12 +574,6 @@ namespace JSC { GlobalCodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, &m_unsharedSymbolTable, false) { - m_heap->codeBlocks().add(this); - } - - ~GlobalCodeBlock() - { - m_heap->codeBlocks().remove(this); } private: @@ -680,7 +631,7 @@ namespace JSC { { CodeBlock* codeBlock = this->codeBlock(); if (codeBlock->isConstantRegisterIndex(index)) - return codeBlock->constantRegister(index); + return *reinterpret_cast<Register*>(&codeBlock->constantRegister(index)); return this[index]; } diff --git a/Source/JavaScriptCore/bytecode/EvalCodeCache.h b/Source/JavaScriptCore/bytecode/EvalCodeCache.h index edd575f..3e450b1 100644 --- a/Source/JavaScriptCore/bytecode/EvalCodeCache.h +++ b/Source/JavaScriptCore/bytecode/EvalCodeCache.h @@ -41,14 +41,16 @@ namespace JSC { + class MarkStack; + class EvalCodeCache { public: - PassRefPtr<EvalExecutable> get(ExecState* exec, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue) + EvalExecutable* get(ExecState* exec, ScriptExecutable* owner, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue) { - RefPtr<EvalExecutable> evalExecutable; + EvalExecutable* evalExecutable = 0; if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject()) - evalExecutable = m_cacheMap.get(evalSource.impl()); + evalExecutable = m_cacheMap.get(evalSource.impl()).get(); if (!evalExecutable) { evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext); @@ -57,19 +59,21 @@ namespace JSC { return 0; if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries) - m_cacheMap.set(evalSource.impl(), evalExecutable); + m_cacheMap.set(evalSource.impl(), WriteBarrier<EvalExecutable>(exec->globalData(), owner, evalExecutable)); } - return evalExecutable.release(); + return evalExecutable; } bool isEmpty() const { return m_cacheMap.isEmpty(); } + void markAggregate(MarkStack&); + private: static const unsigned maxCacheableSourceLength = 256; static const int maxCacheEntries = 64; - typedef HashMap<RefPtr<StringImpl>, RefPtr<EvalExecutable> > EvalCacheMap; + typedef HashMap<RefPtr<StringImpl>, WriteBarrier<EvalExecutable> > EvalCacheMap; EvalCacheMap m_cacheMap; }; diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h index f077cbf..da0821d 100644 --- a/Source/JavaScriptCore/bytecode/Instruction.h +++ b/Source/JavaScriptCore/bytecode/Instruction.h @@ -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; diff --git a/Source/JavaScriptCore/bytecode/SamplingTool.h b/Source/JavaScriptCore/bytecode/SamplingTool.h index 9ca54da..a0696b1 100644 --- a/Source/JavaScriptCore/bytecode/SamplingTool.h +++ b/Source/JavaScriptCore/bytecode/SamplingTool.h @@ -95,8 +95,8 @@ namespace JSC { struct Instruction; struct ScriptSampleRecord { - ScriptSampleRecord(ScriptExecutable* executable) - : m_executable(executable) + ScriptSampleRecord(JSGlobalData& globalData, ScriptExecutable* executable) + : m_executable(globalData, executable) , m_codeBlock(0) , m_sampleCount(0) , m_opcodeSampleCount(0) @@ -113,7 +113,7 @@ namespace JSC { void sample(CodeBlock*, Instruction*); - RefPtr<ScriptExecutable> m_executable; + Global<ScriptExecutable> m_executable; CodeBlock* m_codeBlock; int m_sampleCount; int m_opcodeSampleCount; @@ -280,7 +280,6 @@ namespace JSC { // Implements a named set of counters, printed on exit if ENABLE(SAMPLING_COUNTERS). // See subclasses below, SamplingCounter, GlobalSamplingCounter and DeletableSamplingCounter. class AbstractSamplingCounter { - friend class JIT; friend class DeletableSamplingCounter; public: void count(uint32_t count = 1) @@ -290,6 +289,8 @@ namespace JSC { static void dump(); + int64_t* addressOfCounter() { return &m_counter; } + protected: // Effectively the contructor, however called lazily in the case of GlobalSamplingCounter. void init(const char* name) diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp index 5ec2a3f..4d59ac1 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "StructureStubInfo.h" +#include "JSObject.h" #include "ScopeChain.h" namespace JSC { @@ -43,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; @@ -60,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(); @@ -77,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 diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h index 8e2c489..28202f9 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h @@ -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() { |