diff options
Diffstat (limited to 'JavaScriptCore/bytecode')
-rw-r--r-- | JavaScriptCore/bytecode/CodeBlock.cpp | 98 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/CodeBlock.h | 93 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/EvalCodeCache.h | 36 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/SamplingTool.cpp | 2 |
4 files changed, 138 insertions, 91 deletions
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp index b63e826..e22f25a 100644 --- a/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/JavaScriptCore/bytecode/CodeBlock.cpp @@ -33,8 +33,6 @@ #include "JIT.h" #include "JSValue.h" #include "Interpreter.h" -#include "JSFunction.h" -#include "JSStaticScopeObject.h" #include "Debugger.h" #include "BytecodeGenerator.h" #include <stdio.h> @@ -1248,11 +1246,11 @@ void CodeBlock::dumpStatistics() #endif } -CodeBlock::CodeBlock(ExecutableBase* ownerExecutable) +CodeBlock::CodeBlock(ScopeNode* ownerNode) : m_numCalleeRegisters(0) , m_numVars(0) , m_numParameters(0) - , m_ownerExecutable(ownerExecutable) + , m_ownerNode(ownerNode) , m_globalData(0) #ifndef NDEBUG , m_instructionCount(0) @@ -1270,17 +1268,17 @@ CodeBlock::CodeBlock(ExecutableBase* ownerExecutable) #endif } -CodeBlock::CodeBlock(ExecutableBase* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) +CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) : m_numCalleeRegisters(0) , m_numVars(0) , m_numParameters(0) - , m_ownerExecutable(ownerExecutable) + , m_ownerNode(ownerNode) , m_globalData(0) #ifndef NDEBUG , m_instructionCount(0) #endif - , m_needsFullScopeChain(ownerExecutable->needsActivation()) - , m_usesEval(ownerExecutable->usesEval()) + , m_needsFullScopeChain(ownerNode->needsActivation()) + , m_usesEval(ownerNode->usesEval()) , m_isNumericCompareFunction(false) , m_codeType(codeType) , m_source(sourceProvider) @@ -1437,10 +1435,15 @@ void CodeBlock::markAggregate(MarkStack& markStack) markStack.append(m_constantRegisters[i].jsValue()); } - for (size_t i = 0; i < m_functionExprs.size(); ++i) - m_functionExprs[i]->markAggregate(markStack); - for (size_t i = 0; i < m_functionDecls.size(); ++i) - m_functionDecls[i]->markAggregate(markStack); + for (size_t i = 0; i < m_functionExpressions.size(); ++i) + m_functionExpressions[i]->body()->markAggregate(markStack); + + if (m_rareData) { + for (size_t i = 0; i < m_rareData->m_functions.size(); ++i) + m_rareData->m_functions[i]->body()->markAggregate(markStack); + + m_rareData->m_evalCodeCache.markAggregate(markStack); + } } void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) @@ -1462,7 +1465,56 @@ void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) scopeChain = scopeChain->next; } - m_exceptionInfo.set(m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this)); + switch (m_codeType) { + case FunctionCode: { + FunctionBodyNode* ownerFunctionBodyNode = static_cast<FunctionBodyNode*>(m_ownerNode); + RefPtr<FunctionBodyNode> newFunctionBody = m_globalData->parser->reparse<FunctionBodyNode>(m_globalData, ownerFunctionBodyNode); + ASSERT(newFunctionBody); + newFunctionBody->finishParsing(ownerFunctionBodyNode->copyParameters(), ownerFunctionBodyNode->parameterCount()); + + m_globalData->scopeNodeBeingReparsed = newFunctionBody.get(); + + CodeBlock& newCodeBlock = newFunctionBody->bytecodeForExceptionInfoReparse(scopeChain, this); + ASSERT(newCodeBlock.m_exceptionInfo); + ASSERT(newCodeBlock.m_instructionCount == m_instructionCount); + +#if ENABLE(JIT) + JIT::compile(m_globalData, &newCodeBlock); + ASSERT(newFunctionBody->generatedJITCode().size() == ownerNode()->generatedJITCode().size()); +#endif + + m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release()); + + m_globalData->scopeNodeBeingReparsed = 0; + + break; + } + case EvalCode: { + EvalNode* ownerEvalNode = static_cast<EvalNode*>(m_ownerNode); + RefPtr<EvalNode> newEvalBody = m_globalData->parser->reparse<EvalNode>(m_globalData, ownerEvalNode); + + m_globalData->scopeNodeBeingReparsed = newEvalBody.get(); + + EvalCodeBlock& newCodeBlock = newEvalBody->bytecodeForExceptionInfoReparse(scopeChain, this); + ASSERT(newCodeBlock.m_exceptionInfo); + ASSERT(newCodeBlock.m_instructionCount == m_instructionCount); + +#if ENABLE(JIT) + JIT::compile(m_globalData, &newCodeBlock); + ASSERT(newEvalBody->generatedJITCode().size() == ownerNode()->generatedJITCode().size()); +#endif + + m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release()); + + m_globalData->scopeNodeBeingReparsed = 0; + + break; + } + default: + // CodeBlocks for Global code blocks are transient and therefore to not gain from + // from throwing out there exception information. + ASSERT_NOT_REACHED(); + } } HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) @@ -1493,7 +1545,7 @@ int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned byteco ASSERT(m_exceptionInfo); if (!m_exceptionInfo->m_lineInfo.size()) - return m_ownerExecutable->source().firstLine(); // Empty function + return m_ownerNode->source().firstLine(); // Empty function int low = 0; int high = m_exceptionInfo->m_lineInfo.size(); @@ -1506,7 +1558,7 @@ int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned byteco } if (!low) - return m_ownerExecutable->source().firstLine(); + return m_ownerNode->source().firstLine(); return m_exceptionInfo->m_lineInfo[low - 1].lineNumber; } @@ -1649,6 +1701,18 @@ bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) } #endif +#if ENABLE(JIT) +void CodeBlock::setJITCode(JITCode jitCode) +{ + ASSERT(m_codeType != NativeCode); + ownerNode()->setJITCode(jitCode); +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + m_instructions.clear(); +#endif +} +#endif + void CodeBlock::shrinkToFit() { m_instructions.shrinkToFit(); @@ -1664,8 +1728,7 @@ void CodeBlock::shrinkToFit() #endif m_identifiers.shrinkToFit(); - m_functionDecls.shrinkToFit(); - m_functionExprs.shrinkToFit(); + m_functionExpressions.shrinkToFit(); m_constantRegisters.shrinkToFit(); if (m_exceptionInfo) { @@ -1676,6 +1739,7 @@ void CodeBlock::shrinkToFit() if (m_rareData) { m_rareData->m_exceptionHandlers.shrinkToFit(); + m_rareData->m_functions.shrinkToFit(); m_rareData->m_regexps.shrinkToFit(); m_rareData->m_immediateSwitchJumpTables.shrinkToFit(); m_rareData->m_characterSwitchJumpTables.shrinkToFit(); diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h index fdeb4db..39b1db3 100644 --- a/JavaScriptCore/bytecode/CodeBlock.h +++ b/JavaScriptCore/bytecode/CodeBlock.h @@ -248,22 +248,11 @@ namespace JSC { } #endif - struct ExceptionInfo : FastAllocBase { - Vector<ExpressionRangeInfo> m_expressionInfo; - Vector<LineInfo> m_lineInfo; - Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo; - -#if ENABLE(JIT) - Vector<CallReturnOffsetToBytecodeIndex> m_callReturnIndexVector; -#endif - }; - class CodeBlock : public FastAllocBase { friend class JIT; - protected: - CodeBlock(ExecutableBase* ownerExecutable); - CodeBlock(ExecutableBase* ownerExecutable, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset); public: + CodeBlock(ScopeNode* ownerNode); + CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset); ~CodeBlock(); void markAggregate(MarkStack&); @@ -340,7 +329,7 @@ namespace JSC { unsigned getBytecodeIndex(CallFrame* callFrame, ReturnAddressPtr returnAddress) { reparseForExceptionInfoIfNecessary(callFrame); - return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(callReturnIndexVector().begin(), callReturnIndexVector().size(), ownerExecutable()->generatedJITCode().offsetOf(returnAddress.value()))->bytecodeIndex; + return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(callReturnIndexVector().begin(), callReturnIndexVector().size(), ownerNode()->generatedJITCode().offsetOf(returnAddress.value()))->bytecodeIndex; } bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex); @@ -350,19 +339,17 @@ namespace JSC { bool isNumericCompareFunction() { return m_isNumericCompareFunction; } Vector<Instruction>& instructions() { return m_instructions; } - void discardBytecode() { m_instructions.clear(); } - #ifndef NDEBUG - unsigned instructionCount() { return m_instructionCount; } void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; } #endif #if ENABLE(JIT) - JITCode& getJITCode() { return ownerExecutable()->generatedJITCode(); } - ExecutablePool* executablePool() { return ownerExecutable()->getExecutablePool(); } + JITCode& getJITCode() { return ownerNode()->generatedJITCode(); } + void setJITCode(JITCode); + ExecutablePool* executablePool() { return ownerNode()->getExecutablePool(); } #endif - ExecutableBase* ownerExecutable() const { return m_ownerExecutable; } + ScopeNode* ownerNode() const { return m_ownerNode; } void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; } @@ -417,7 +404,6 @@ namespace JSC { bool hasExceptionInfo() const { return m_exceptionInfo; } void clearExceptionInfo() { m_exceptionInfo.clear(); } - ExceptionInfo* extractExceptionInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo.release(); } void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); } void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); } @@ -442,11 +428,13 @@ namespace JSC { ALWAYS_INLINE bool isConstantRegisterIndex(int index) { return index >= FirstConstantRegisterIndex; } ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); } - unsigned addFunctionDecl(PassRefPtr<FunctionExecutable> n) { unsigned size = m_functionDecls.size(); m_functionDecls.append(n); return size; } - FunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); } - int numberOfFunctionDecls() { return m_functionDecls.size(); } - unsigned addFunctionExpr(PassRefPtr<FunctionExecutable> n) { unsigned size = m_functionExprs.size(); m_functionExprs.append(n); return size; } - FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); } + unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; } + FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); } + + unsigned addFunction(FuncDeclNode* n) { createRareDataIfNecessary(); unsigned size = m_rareData->m_functions.size(); m_rareData->m_functions.append(n); return size; } + FuncDeclNode* function(int index) const { ASSERT(m_rareData); return m_rareData->m_functions[index].get(); } + + bool hasFunctions() const { return m_functionExpressions.size() || (m_rareData && m_rareData->m_functions.size()); } unsigned addRegExp(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(); } @@ -493,7 +481,7 @@ namespace JSC { m_rareData.set(new RareData); } - ExecutableBase* m_ownerExecutable; + ScopeNode* m_ownerNode; JSGlobalData* m_globalData; Vector<Instruction> m_instructions; @@ -529,17 +517,26 @@ namespace JSC { // Constant Pool Vector<Identifier> m_identifiers; Vector<Register> m_constantRegisters; - Vector<RefPtr<FunctionExecutable> > m_functionDecls; - Vector<RefPtr<FunctionExecutable> > m_functionExprs; + Vector<RefPtr<FuncExprNode> > m_functionExpressions; SymbolTable m_symbolTable; + struct ExceptionInfo : FastAllocBase { + Vector<ExpressionRangeInfo> m_expressionInfo; + Vector<LineInfo> m_lineInfo; + Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo; + +#if ENABLE(JIT) + Vector<CallReturnOffsetToBytecodeIndex> m_callReturnIndexVector; +#endif + }; OwnPtr<ExceptionInfo> m_exceptionInfo; struct RareData : FastAllocBase { Vector<HandlerInfo> m_exceptionHandlers; // Rare Constants + Vector<RefPtr<FuncDeclNode> > m_functions; Vector<RefPtr<RegExp> > m_regexps; // Jump Tables @@ -559,16 +556,16 @@ namespace JSC { // Program code is not marked by any function, so we make the global object // responsible for marking it. - class GlobalCodeBlock : public CodeBlock { + class ProgramCodeBlock : public CodeBlock { public: - GlobalCodeBlock(ExecutableBase* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, JSGlobalObject* globalObject) - : CodeBlock(ownerExecutable, codeType, sourceProvider, sourceOffset) + ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider) + : CodeBlock(ownerNode, codeType, sourceProvider, 0) , m_globalObject(globalObject) { m_globalObject->codeBlocks().add(this); } - ~GlobalCodeBlock() + ~ProgramCodeBlock() { if (m_globalObject) m_globalObject->codeBlocks().remove(this); @@ -580,18 +577,10 @@ namespace JSC { JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool. }; - class ProgramCodeBlock : public GlobalCodeBlock { + class EvalCodeBlock : public ProgramCodeBlock { public: - ProgramCodeBlock(ProgramExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider) - : GlobalCodeBlock(ownerExecutable, codeType, sourceProvider, 0, globalObject) - { - } - }; - - class EvalCodeBlock : public GlobalCodeBlock { - public: - EvalCodeBlock(EvalExecutable* ownerExecutable, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth) - : GlobalCodeBlock(ownerExecutable, EvalCode, sourceProvider, 0, globalObject) + EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth) + : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider) , m_baseScopeDepth(baseScopeDepth) { } @@ -602,22 +591,6 @@ namespace JSC { int m_baseScopeDepth; }; - class FunctionCodeBlock : public CodeBlock { - public: - FunctionCodeBlock(FunctionExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) - : CodeBlock(ownerExecutable, codeType, sourceProvider, sourceOffset) - { - } - }; - - class NativeCodeBlock : public CodeBlock { - public: - NativeCodeBlock(FunctionExecutable* ownerExecutable) - : CodeBlock(ownerExecutable) - { - } - }; - inline Register& ExecState::r(int index) { CodeBlock* codeBlock = this->codeBlock(); diff --git a/JavaScriptCore/bytecode/EvalCodeCache.h b/JavaScriptCore/bytecode/EvalCodeCache.h index c486e42..986525c 100644 --- a/JavaScriptCore/bytecode/EvalCodeCache.h +++ b/JavaScriptCore/bytecode/EvalCodeCache.h @@ -29,7 +29,6 @@ #ifndef EvalCodeCache_h #define EvalCodeCache_h -#include "Executable.h" #include "JSGlobalObject.h" #include "Nodes.h" #include "Parser.h" @@ -42,33 +41,44 @@ namespace JSC { class EvalCodeCache { public: - PassRefPtr<CacheableEvalExecutable> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue) + PassRefPtr<EvalNode> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue) { - RefPtr<CacheableEvalExecutable> evalExecutable; + RefPtr<EvalNode> evalNode; if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject()) - evalExecutable = m_cacheMap.get(evalSource.rep()); + evalNode = m_cacheMap.get(evalSource.rep()); - if (!evalExecutable) { - evalExecutable = CacheableEvalExecutable::create(makeSource(evalSource)); - exceptionValue = evalExecutable->parse(exec); - if (exceptionValue) + if (!evalNode) { + int errorLine; + UString errorMessage; + + SourceCode source = makeSource(evalSource); + evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errorLine, &errorMessage); + if (evalNode) { + if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries) + m_cacheMap.set(evalSource.rep(), evalNode); + } else { + exceptionValue = Error::create(exec, SyntaxError, errorMessage, errorLine, source.provider()->asID(), 0); return 0; - - if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries) - m_cacheMap.set(evalSource.rep(), evalExecutable); + } } - return evalExecutable.release(); + return evalNode.release(); } bool isEmpty() const { return m_cacheMap.isEmpty(); } + void markAggregate(MarkStack& markStack) + { + EvalCacheMap::iterator end = m_cacheMap.end(); + for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr) + ptr->second->markAggregate(markStack); + } private: static const int maxCacheableSourceLength = 256; static const int maxCacheEntries = 64; - typedef HashMap<RefPtr<UString::Rep>, RefPtr<CacheableEvalExecutable> > EvalCacheMap; + typedef HashMap<RefPtr<UString::Rep>, RefPtr<EvalNode> > EvalCacheMap; EvalCacheMap m_cacheMap; }; diff --git a/JavaScriptCore/bytecode/SamplingTool.cpp b/JavaScriptCore/bytecode/SamplingTool.cpp index 8d0faa1..8651723 100644 --- a/JavaScriptCore/bytecode/SamplingTool.cpp +++ b/JavaScriptCore/bytecode/SamplingTool.cpp @@ -197,7 +197,7 @@ void SamplingTool::doRun() #if ENABLE(CODEBLOCK_SAMPLING) if (CodeBlock* codeBlock = sample.codeBlock()) { MutexLocker locker(m_scopeSampleMapMutex); - ScopeSampleRecord* record = m_scopeSampleMap->get(codeBlock->ownerExecutable()); + ScopeSampleRecord* record = m_scopeSampleMap->get(codeBlock->ownerNode()); ASSERT(record); record->sample(codeBlock, sample.vPC()); } |