summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/bytecode
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/bytecode')
-rw-r--r--JavaScriptCore/bytecode/CodeBlock.cpp98
-rw-r--r--JavaScriptCore/bytecode/CodeBlock.h93
-rw-r--r--JavaScriptCore/bytecode/EvalCodeCache.h36
-rw-r--r--JavaScriptCore/bytecode/SamplingTool.cpp2
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());
}