summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/parser/Nodes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/parser/Nodes.cpp')
-rw-r--r--JavaScriptCore/parser/Nodes.cpp186
1 files changed, 173 insertions, 13 deletions
diff --git a/JavaScriptCore/parser/Nodes.cpp b/JavaScriptCore/parser/Nodes.cpp
index 11a24b5..4324a06 100644
--- a/JavaScriptCore/parser/Nodes.cpp
+++ b/JavaScriptCore/parser/Nodes.cpp
@@ -138,7 +138,7 @@ RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d
RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring());
+ RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
if (!regExp->isValid())
return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
if (dst == generator.ignoredResult())
@@ -1205,13 +1205,7 @@ RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
return generator.emitNode(local, m_init);
}
-
- if (generator.codeType() != EvalCode) {
- if (m_init)
- return generator.emitNode(m_init);
- else
- return generator.emitResolve(generator.newTemporary(), m_ident);
- }
+
// FIXME: While this code should only be hit in eval code, it will potentially
// assign to the wrong base if m_ident exists in an intervening dynamic scope.
RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
@@ -1824,6 +1818,17 @@ ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* children, VarSt
children->releaseContentsIntoVector(m_children);
}
+void ScopeNodeData::markAggregate(MarkStack& markStack)
+{
+ FunctionStack::iterator end = m_functionStack.end();
+ for (FunctionStack::iterator ptr = m_functionStack.begin(); ptr != end; ++ptr) {
+ FunctionBodyNode* body = (*ptr)->body();
+ if (!body->isGenerated())
+ continue;
+ body->generatedBytecode().markAggregate(markStack);
+ }
+}
+
// ------------------------------ ScopeNode -----------------------------
ScopeNode::ScopeNode(JSGlobalData* globalData)
@@ -1881,6 +1886,30 @@ RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
return 0;
}
+void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode)
+{
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
+
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get()));
+ generator->generate();
+
+ destroyData();
+}
+
+#if ENABLE(JIT)
+void ProgramNode::generateJITCode(ScopeChainNode* scopeChainNode)
+{
+ bytecode(scopeChainNode);
+ ASSERT(m_code);
+ ASSERT(!m_jitCode);
+ JIT::compile(scopeChainNode->globalData, m_code.get());
+ ASSERT(m_jitCode);
+}
+#endif
+
// ------------------------------ EvalNode -----------------------------
inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
@@ -1912,6 +1941,54 @@ RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
return 0;
}
+void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode)
+{
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
+
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
+ generator->generate();
+
+ // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time,
+ // so the entire ScopeNodeData cannot be destoyed.
+ children().clear();
+}
+
+EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
+{
+ ASSERT(!m_code);
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
+
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
+ generator->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
+ generator->generate();
+
+ return *m_code;
+}
+
+void EvalNode::markAggregate(MarkStack& markStack)
+{
+ // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that
+ data()->markAggregate(markStack);
+}
+
+#if ENABLE(JIT)
+void EvalNode::generateJITCode(ScopeChainNode* scopeChainNode)
+{
+ bytecode(scopeChainNode);
+ ASSERT(m_code);
+ ASSERT(!m_jitCode);
+ JIT::compile(scopeChainNode->globalData, m_code.get());
+ ASSERT(m_jitCode);
+}
+#endif
+
// ------------------------------ FunctionBodyNode -----------------------------
inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
@@ -1935,7 +2012,7 @@ FunctionBodyNode::~FunctionBodyNode()
fastFree(m_parameters);
}
-void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident)
+void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
{
Vector<Identifier> parameters;
for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
@@ -1943,15 +2020,36 @@ void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* fi
size_t count = parameters.size();
setSource(source);
- finishParsing(parameters.releaseBuffer(), count, ident);
+ finishParsing(parameters.releaseBuffer(), count);
}
-void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount, const Identifier& ident)
+void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
{
ASSERT(!source().isNull());
m_parameters = parameters;
m_parameterCount = parameterCount;
- m_ident = ident;
+}
+
+void FunctionBodyNode::markAggregate(MarkStack& markStack)
+{
+ if (m_code)
+ m_code->markAggregate(markStack);
+}
+
+#if ENABLE(JIT)
+PassRefPtr<FunctionBodyNode> FunctionBodyNode::createNativeThunk(JSGlobalData* globalData)
+{
+ RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData);
+ globalData->parser->arena().reset();
+ body->m_code.set(new CodeBlock(body.get()));
+ body->m_jitCode = JITCode(JITCode::HostFunction(globalData->jitStubs.ctiNativeCallThunk()));
+ return body.release();
+}
+#endif
+
+bool FunctionBodyNode::isHostFunction() const
+{
+ return m_code && m_code->codeType() == NativeCode;
}
FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
@@ -1970,13 +2068,50 @@ PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData,
return node.release();
}
-void FunctionBodyNode::reparseDataIfNecessary(ScopeChainNode* scopeChainNode)
+void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode)
{
// This branch is only necessary since you can still create a non-stub FunctionBodyNode by
// calling Parser::parse<FunctionBodyNode>().
if (!data())
scopeChainNode->globalData->parser->reparseInPlace(scopeChainNode->globalData, this);
ASSERT(data());
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
+ generator->generate();
+
+ destroyData();
+}
+
+#if ENABLE(JIT)
+void FunctionBodyNode::generateJITCode(ScopeChainNode* scopeChainNode)
+{
+ bytecode(scopeChainNode);
+ ASSERT(m_code);
+ ASSERT(!m_jitCode);
+ JIT::compile(scopeChainNode->globalData, m_code.get());
+ ASSERT(m_jitCode);
+}
+#endif
+
+CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
+{
+ ASSERT(!m_code);
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
+ generator->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
+ generator->generate();
+
+ return *m_code;
}
RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
@@ -2016,6 +2151,11 @@ Identifier* FunctionBodyNode::copyParameters()
// ------------------------------ FuncDeclNode ---------------------------------
+JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
+{
+ return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
+}
+
RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
if (dst == generator.ignoredResult())
@@ -2030,4 +2170,24 @@ RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
}
+JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
+{
+ JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
+
+ /*
+ The Identifier in a FunctionExpression can be referenced from inside
+ the FunctionExpression's FunctionBody to allow the function to call
+ itself recursively. However, unlike in a FunctionDeclaration, the
+ Identifier in a FunctionExpression cannot be referenced from and
+ does not affect the scope enclosing the FunctionExpression.
+ */
+
+ if (!m_ident.isNull()) {
+ JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
+ func->scope().push(functionScopeObject);
+ }
+
+ return func;
+}
+
} // namespace JSC