diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2009-06-15 09:06:43 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-06-15 09:31:31 (GMT) |
commit | c411f16870f112c3407c28c22b617f613a82cff4 (patch) | |
tree | 29a1bcd590c8b31af2aab445bfe8a978dc5bf582 /src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp | |
parent | 3d77b56b32a0c53ec0bbfaa07236fedb900ff336 (diff) | |
download | Qt-c411f16870f112c3407c28c22b617f613a82cff4.zip Qt-c411f16870f112c3407c28c22b617f613a82cff4.tar.gz Qt-c411f16870f112c3407c28c22b617f613a82cff4.tar.bz2 |
Updated WebKit from /home/shausman/src/webkit/trunk to qtwebkit-4.6-snapshot-15062009 ( 65232bf00dc494ebfd978f998c88f58d18ecce1e )
Diffstat (limited to 'src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp')
-rw-r--r-- | src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp | 1618 |
1 files changed, 539 insertions, 1079 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp index 201af28..4ddf13a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp @@ -25,24 +25,23 @@ #include "config.h" #include "Nodes.h" +#include "NodeConstructors.h" #include "BytecodeGenerator.h" #include "CallFrame.h" +#include "Debugger.h" +#include "JIT.h" +#include "JSFunction.h" #include "JSGlobalObject.h" #include "JSStaticScopeObject.h" #include "LabelScope.h" +#include "Lexer.h" +#include "Operations.h" #include "Parser.h" #include "PropertyNameArray.h" #include "RegExpObject.h" #include "SamplingTool.h" -#include "Debugger.h" -#include "Lexer.h" -#include "Operations.h" -#include <math.h> #include <wtf/Assertions.h> -#include <wtf/HashCountedSet.h> -#include <wtf/HashSet.h> -#include <wtf/MathExtras.h> #include <wtf/RefCountedLeakCounter.h> #include <wtf/Threading.h> @@ -50,173 +49,7 @@ using namespace WTF; namespace JSC { -static void substitute(UString& string, const UString& substring) JSC_FAST_CALL; - -// ------------------------------ NodeReleaser -------------------------------- - -class NodeReleaser : Noncopyable { -public: - // Call this function inside the destructor of a class derived from Node. - // This will traverse the tree below this node, destroying all of those nodes, - // but without relying on recursion. - static void releaseAllNodes(ParserRefCounted* root); - - // Call this on each node in a the releaseNodes virtual function. - // It gives the node to the NodeReleaser, which will then release the - // node later at the end of the releaseAllNodes process. - template <typename T> void release(RefPtr<T>& node) { if (node) adopt(node.release()); } - void release(RefPtr<FunctionBodyNode>& node) { if (node) adoptFunctionBodyNode(node); } - -private: - NodeReleaser() { } - ~NodeReleaser() { } - - void adopt(PassRefPtr<ParserRefCounted>); - void adoptFunctionBodyNode(RefPtr<FunctionBodyNode>&); - - typedef Vector<RefPtr<ParserRefCounted> > NodeReleaseVector; - OwnPtr<NodeReleaseVector> m_vector; -}; - -void NodeReleaser::releaseAllNodes(ParserRefCounted* root) -{ - ASSERT(root); - NodeReleaser releaser; - root->releaseNodes(releaser); - if (!releaser.m_vector) - return; - // Note: The call to release.m_vector->size() is intentionally inside - // the loop, since calls to releaseNodes are expected to increase the size. - for (size_t i = 0; i < releaser.m_vector->size(); ++i) { - ParserRefCounted* node = (*releaser.m_vector)[i].get(); - if (node->hasOneRef()) - node->releaseNodes(releaser); - } -} - -void NodeReleaser::adopt(PassRefPtr<ParserRefCounted> node) -{ - ASSERT(node); - if (!node->hasOneRef()) - return; - if (!m_vector) - m_vector.set(new NodeReleaseVector); - m_vector->append(node); -} - -void NodeReleaser::adoptFunctionBodyNode(RefPtr<FunctionBodyNode>& functionBodyNode) -{ - // This sidesteps a problem where if you assign a PassRefPtr<FunctionBodyNode> - // to a PassRefPtr<Node> we leave the two reference counts (FunctionBodyNode - // and ParserRefCounted) unbalanced. It would be nice to fix this problem in - // a cleaner way -- perhaps we could remove the FunctionBodyNode reference - // count at some point. - RefPtr<Node> node = functionBodyNode; - functionBodyNode = 0; - adopt(node.release()); -} - -// ------------------------------ ParserRefCounted ----------------------------------------- - -#ifndef NDEBUG -static RefCountedLeakCounter parserRefCountedCounter("JSC::Node"); -#endif - -ParserRefCounted::ParserRefCounted(JSGlobalData* globalData) - : m_globalData(globalData) -{ -#ifndef NDEBUG - parserRefCountedCounter.increment(); -#endif - if (!m_globalData->newParserObjects) - m_globalData->newParserObjects = new HashSet<ParserRefCounted*>; - m_globalData->newParserObjects->add(this); - ASSERT(m_globalData->newParserObjects->contains(this)); -} - -ParserRefCounted::~ParserRefCounted() -{ -#ifndef NDEBUG - parserRefCountedCounter.decrement(); -#endif -} - -void ParserRefCounted::releaseNodes(NodeReleaser&) -{ -} - -void ParserRefCounted::ref() -{ - // bumping from 0 to 1 is just removing from the new nodes set - if (m_globalData->newParserObjects) { - HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this); - if (it != m_globalData->newParserObjects->end()) { - m_globalData->newParserObjects->remove(it); - ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this)); - return; - } - } - - ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this)); - - if (!m_globalData->parserObjectExtraRefCounts) - m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>; - m_globalData->parserObjectExtraRefCounts->add(this); -} - -void ParserRefCounted::deref() -{ - ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this)); - - if (!m_globalData->parserObjectExtraRefCounts) { - delete this; - return; - } - - HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this); - if (it == m_globalData->parserObjectExtraRefCounts->end()) - delete this; - else - m_globalData->parserObjectExtraRefCounts->remove(it); -} - -bool ParserRefCounted::hasOneRef() -{ - if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) { - ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this)); - return false; - } - - ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this)); - - if (!m_globalData->parserObjectExtraRefCounts) - return true; - - return !m_globalData->parserObjectExtraRefCounts->contains(this); -} - -void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData) -{ - if (!globalData->newParserObjects) - return; - -#ifndef NDEBUG - HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end(); - for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it) - ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it)); -#endif - deleteAllValues(*globalData->newParserObjects); - delete globalData->newParserObjects; - globalData->newParserObjects = 0; -} - -// ------------------------------ Node -------------------------------- - -Node::Node(JSGlobalData* globalData) - : ParserRefCounted(globalData) -{ - m_line = globalData->lexer->lineNo(); -} +static void substitute(UString& string, const UString& substring); // ------------------------------ ThrowableExpressionData -------------------------------- @@ -247,14 +80,8 @@ RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator generator.emitThrow(exception); return exception; } - -// ------------------------------ StatementNode -------------------------------- -StatementNode::StatementNode(JSGlobalData* globalData) - : Node(globalData) - , m_lastLine(-1) -{ -} +// ------------------------------ StatementNode -------------------------------- void StatementNode::setLoc(int firstLine, int lastLine) { @@ -264,11 +91,10 @@ void StatementNode::setLoc(int firstLine, int lastLine) // ------------------------------ SourceElements -------------------------------- -void SourceElements::append(PassRefPtr<StatementNode> statement) +void SourceElements::append(StatementNode* statement) { if (statement->isEmptyStatement()) return; - m_statements.append(statement); } @@ -348,47 +174,24 @@ RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* return generator.emitResolve(generator.finalDestination(dst), m_ident); } -// ------------------------------ ElementNode ------------------------------------ - -ElementNode::~ElementNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ElementNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); - releaser.release(m_node); -} - // ------------------------------ ArrayNode ------------------------------------ -ArrayNode::~ArrayNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ArrayNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_element); -} - RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { // FIXME: Should we put all of this code into emitNewArray? unsigned length = 0; ElementNode* firstPutElement; - for (firstPutElement = m_element.get(); firstPutElement; firstPutElement = firstPutElement->next()) { + for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) { if (firstPutElement->elision()) break; ++length; } if (!firstPutElement && !m_elision) - return generator.emitNewArray(generator.finalDestination(dst), m_element.get()); + return generator.emitNewArray(generator.finalDestination(dst), m_element); - RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get()); + RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element); for (ElementNode* n = firstPutElement; n; n = n->next()) { RegisterID* value = generator.emitNode(n->value()); @@ -404,30 +207,35 @@ RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds return generator.moveToDestinationIfNeeded(dst, array.get()); } -// ------------------------------ PropertyNode ---------------------------- - -PropertyNode::~PropertyNode() +bool ArrayNode::isSimpleArray() const { - NodeReleaser::releaseAllNodes(this); + if (m_elision || m_optional) + return false; + for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) { + if (ptr->elision()) + return false; + } + return true; } -void PropertyNode::releaseNodes(NodeReleaser& releaser) +ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const { - releaser.release(m_assign); + ASSERT(!m_elision && !m_optional); + ElementNode* ptr = m_element; + if (!ptr) + return 0; + ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value()); + ArgumentListNode* tail = head; + ptr = ptr->next(); + for (; ptr; ptr = ptr->next()) { + ASSERT(!ptr->elision()); + tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value()); + } + return head; } // ------------------------------ ObjectLiteralNode ---------------------------- -ObjectLiteralNode::~ObjectLiteralNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ObjectLiteralNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_list); -} - RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (!m_list) { @@ -435,30 +243,19 @@ RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, Regist return 0; return generator.emitNewObject(generator.finalDestination(dst)); } - return generator.emitNode(dst, m_list.get()); + return generator.emitNode(dst, m_list); } // ------------------------------ PropertyListNode ----------------------------- -PropertyListNode::~PropertyListNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PropertyListNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_node); - releaser.release(m_next); -} - RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> newObj = generator.tempDestination(dst); generator.emitNewObject(newObj.get()); - for (PropertyListNode* p = this; p; p = p->m_next.get()) { - RegisterID* value = generator.emitNode(p->m_node->m_assign.get()); + for (PropertyListNode* p = this; p; p = p->m_next) { + RegisterID* value = generator.emitNode(p->m_node->m_assign); switch (p->m_node->m_type) { case PropertyNode::Constant: { @@ -483,152 +280,66 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe // ------------------------------ BracketAccessorNode -------------------------------- -BracketAccessorNode::~BracketAccessorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void BracketAccessorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); -} - RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator)); - RegisterID* property = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator)); + RegisterID* property = generator.emitNode(m_subscript); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); } // ------------------------------ DotAccessorNode -------------------------------- -DotAccessorNode::~DotAccessorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DotAccessorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); -} - RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RegisterID* base = generator.emitNode(m_base.get()); + RegisterID* base = generator.emitNode(m_base); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitGetById(generator.finalDestination(dst), base, m_ident); } // ------------------------------ ArgumentListNode ----------------------------- -ArgumentListNode::~ArgumentListNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ArgumentListNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); - releaser.release(m_expr); -} - RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { ASSERT(m_expr); - return generator.emitNode(dst, m_expr.get()); -} - -// ------------------------------ ArgumentsNode ----------------------------- - -ArgumentsNode::~ArgumentsNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ArgumentsNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_listNode); + return generator.emitNode(dst, m_expr); } // ------------------------------ NewExprNode ---------------------------------- -NewExprNode::~NewExprNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void NewExprNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_args); -} - RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); - return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), divot(), startOffset(), endOffset()); + RefPtr<RegisterID> func = generator.emitNode(m_expr); + return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ EvalFunctionCallNode ---------------------------------- -EvalFunctionCallNode::~EvalFunctionCallNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void EvalFunctionCallNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_args); -} - RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> func = generator.tempDestination(dst); RefPtr<RegisterID> thisRegister = generator.newTemporary(); generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0); generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval); - return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallValueNode ---------------------------------- -FunctionCallValueNode::~FunctionCallValueNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FunctionCallValueNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_args); -} - RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); + RefPtr<RegisterID> func = generator.emitNode(m_expr); RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallResolveNode ---------------------------------- -FunctionCallResolveNode::~FunctionCallResolveNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_args); -} - RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } int index = 0; @@ -637,61 +348,142 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } - RefPtr<RegisterID> func = generator.tempDestination(dst); + RefPtr<RegisterID> func = generator.newTemporary(); RefPtr<RegisterID> thisRegister = generator.newTemporary(); int identifierStart = divot() - startOffset(); generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0); generator.emitResolveFunction(thisRegister.get(), func.get(), m_ident); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallBracketNode ---------------------------------- -FunctionCallBracketNode::~FunctionCallBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); - releaser.release(m_args); -} - RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); - RegisterID* property = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); + RegisterID* property = generator.emitNode(m_subscript); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallDotNode ---------------------------------- -FunctionCallDotNode::~FunctionCallDotNode() +RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - NodeReleaser::releaseAllNodes(this); + RefPtr<RegisterID> base = generator.emitNode(m_base); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + generator.emitMethodCheck(); + RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } -void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser) +RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<Label> realCall = generator.newLabel(); + RefPtr<Label> end = generator.newLabel(); + RefPtr<RegisterID> base = generator.emitNode(m_base); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); + RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get()); + generator.emitJumpIfNotFunctionCall(function.get(), realCall.get()); + { + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + ArgumentListNode* oldList = m_args->m_listNode; + if (m_args->m_listNode && m_args->m_listNode->m_expr) { + generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + m_args->m_listNode = m_args->m_listNode->m_next; + } else + generator.emitLoad(thisRegister.get(), jsNull()); + + generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + generator.emitJump(end.get()); + m_args->m_listNode = oldList; + } + generator.emitLabel(realCall.get()); + { + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + } + generator.emitLabel(end.get()); + return finalDestination.get(); +} + +static bool areTrivialApplyArguments(ArgumentsNode* args) { - releaser.release(m_base); - releaser.release(m_args); + return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next + || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray()); } -RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); + // A few simple cases can be trivially handled as ordinary function calls. + // function.apply(), function.apply(arg) -> identical to function.call + // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation + bool mayBeCall = areTrivialApplyArguments(m_args); + + RefPtr<Label> realCall = generator.newLabel(); + RefPtr<Label> end = generator.newLabel(); + RefPtr<RegisterID> base = generator.emitNode(m_base); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); - RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get()); + generator.emitJumpIfNotFunctionApply(function.get(), realCall.get()); + { + if (mayBeCall) { + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + ArgumentListNode* oldList = m_args->m_listNode; + if (m_args->m_listNode && m_args->m_listNode->m_expr) { + generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + m_args->m_listNode = m_args->m_listNode->m_next; + if (m_args->m_listNode) { + ASSERT(m_args->m_listNode->m_expr->isSimpleArray()); + ASSERT(!m_args->m_listNode->m_next); + m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData()); + } + } else + generator.emitLoad(thisRegister.get(), jsNull()); + generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + m_args->m_listNode = oldList; + } else { + ASSERT(m_args->m_listNode && m_args->m_listNode->m_next); + RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get()); + RefPtr<RegisterID> argsCountRegister = generator.newTemporary(); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + RefPtr<RegisterID> argsRegister = generator.newTemporary(); + generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + ArgumentListNode* args = m_args->m_listNode->m_next; + bool isArgumentsApply = false; + if (args->m_expr->isResolveNode()) { + ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr); + isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier()); + if (isArgumentsApply) + generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments()); + } + if (!isArgumentsApply) + generator.emitNode(argsRegister.get(), args->m_expr); + while ((args = args->m_next)) + generator.emitNode(args->m_expr); + + generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get()); + generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset()); + } + generator.emitJump(end.get()); + } + generator.emitLabel(realCall.get()); + { + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + } + generator.emitLabel(end.get()); + return finalDestination.get(); } // ------------------------------ PostfixResolveNode ---------------------------------- @@ -752,21 +544,10 @@ RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, Regis // ------------------------------ PostfixBracketNode ---------------------------------- -PostfixBracketNode::~PostfixBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PostfixBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); -} - RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); - RefPtr<RegisterID> property = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); + RefPtr<RegisterID> property = generator.emitNode(m_subscript); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get()); @@ -787,19 +568,9 @@ RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, Regis // ------------------------------ PostfixDotNode ---------------------------------- -PostfixDotNode::~PostfixDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PostfixDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); -} - RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); @@ -820,16 +591,6 @@ RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterI // ------------------------------ PostfixErrorNode ----------------------------------- -PostfixErrorNode::~PostfixErrorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PostfixErrorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference."); @@ -849,21 +610,10 @@ RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ DeleteBracketNode ----------------------------------- -DeleteBracketNode::~DeleteBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DeleteBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); -} - RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> r0 = generator.emitNode(m_base.get()); - RegisterID* r1 = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> r0 = generator.emitNode(m_base); + RegisterID* r1 = generator.emitNode(m_subscript); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1); @@ -871,19 +621,9 @@ RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ DeleteDotNode ----------------------------------- -DeleteDotNode::~DeleteDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DeleteDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); -} - RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RegisterID* r0 = generator.emitNode(m_base.get()); + RegisterID* r0 = generator.emitNode(m_base); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident); @@ -891,19 +631,9 @@ RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ DeleteValueNode ----------------------------------- -DeleteValueNode::~DeleteValueNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DeleteValueNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitNode(generator.ignoredResult(), m_expr.get()); + generator.emitNode(generator.ignoredResult(), m_expr); // delete on a non-location expression ignores the value and returns true return generator.emitUnexpectedLoad(generator.finalDestination(dst), true); @@ -911,23 +641,13 @@ RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, Register // ------------------------------ VoidNode ------------------------------------- -VoidNode::~VoidNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void VoidNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (dst == generator.ignoredResult()) { - generator.emitNode(generator.ignoredResult(), m_expr.get()); + generator.emitNode(generator.ignoredResult(), m_expr); return 0; } - RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get()); + RefPtr<RegisterID> r0 = generator.emitNode(m_expr); return generator.emitLoad(dst, jsUndefined()); } @@ -950,23 +670,13 @@ RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ TypeOfValueNode ----------------------------------- -TypeOfValueNode::~TypeOfValueNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void TypeOfValueNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (dst == generator.ignoredResult()) { - generator.emitNode(generator.ignoredResult(), m_expr.get()); + generator.emitNode(generator.ignoredResult(), m_expr); return 0; } - RefPtr<RegisterID> src = generator.emitNode(m_expr.get()); + RefPtr<RegisterID> src = generator.emitNode(m_expr); return generator.emitTypeOf(generator.finalDestination(dst), src.get()); } @@ -1006,21 +716,10 @@ RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ PrefixBracketNode ---------------------------------- -PrefixBracketNode::~PrefixBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PrefixBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); -} - RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); - RefPtr<RegisterID> property = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); + RefPtr<RegisterID> property = generator.emitNode(m_subscript); RefPtr<RegisterID> propDst = generator.tempDestination(dst); generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); @@ -1036,19 +735,9 @@ RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ PrefixDotNode ---------------------------------- -PrefixDotNode::~PrefixDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PrefixDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); -} - RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); RefPtr<RegisterID> propDst = generator.tempDestination(dst); generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); @@ -1064,16 +753,6 @@ RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ PrefixErrorNode ----------------------------------- -PrefixErrorNode::~PrefixErrorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PrefixErrorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference."); @@ -1081,48 +760,149 @@ RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, Register // ------------------------------ Unary Operation Nodes ----------------------------------- -UnaryOpNode::~UnaryOpNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void UnaryOpNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RegisterID* src = generator.emitNode(m_expr.get()); + RegisterID* src = generator.emitNode(m_expr); return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); } // ------------------------------ Binary Operation Nodes ----------------------------------- -BinaryOpNode::~BinaryOpNode() -{ - NodeReleaser::releaseAllNodes(this); -} +// BinaryOpNode::emitStrcat: +// +// This node generates an op_strcat operation. This opcode can handle concatenation of three or +// more values, where we can determine a set of separate op_add operations would be operating on +// string values. +// +// This function expects to be operating on a graph of AST nodes looking something like this: +// +// (a)... (b) +// \ / +// (+) (c) +// \ / +// [d] ((+)) +// \ / +// [+=] +// +// The assignment operation is optional, if it exists the register holding the value on the +// lefthand side of the assignment should be passing as the optional 'lhs' argument. +// +// The method should be called on the node at the root of the tree of regular binary add +// operations (marked in the diagram with a double set of parentheses). This node must +// be performing a string concatenation (determined by statically detecting that at least +// one child must be a string). +// +// Since the minimum number of values being concatenated together is expected to be 3, if +// a lhs to a concatenating assignment is not provided then the root add should have at +// least one left child that is also an add that can be determined to be operating on strings. +// +RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe) +{ + ASSERT(isAdd()); + ASSERT(resultDescriptor().definitelyIsString()); + + // Create a list of expressions for all the adds in the tree of nodes we can convert into + // a string concatenation. The rightmost node (c) is added first. The rightmost node is + // added first, and the leftmost child is never added, so the vector produced for the + // example above will be [ c, b ]. + Vector<ExpressionNode*, 16> reverseExpressionList; + reverseExpressionList.append(m_expr2); + + // Examine the left child of the add. So long as this is a string add, add its right-child + // to the list, and keep processing along the left fork. + ExpressionNode* leftMostAddChild = m_expr1; + while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) { + reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2); + leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1; + } -void BinaryOpNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr1); - releaser.release(m_expr2); + Vector<RefPtr<RegisterID>, 16> temporaryRegisters; + + // If there is an assignment, allocate a temporary to hold the lhs after conversion. + // We could possibly avoid this (the lhs is converted last anyway, we could let the + // op_strcat node handle its conversion if required). + if (lhs) + temporaryRegisters.append(generator.newTemporary()); + + // Emit code for the leftmost node ((a) in the example). + temporaryRegisters.append(generator.newTemporary()); + RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get(); + generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild); + + // Note on ordering of conversions: + // + // We maintain the same ordering of conversions as we would see if the concatenations + // was performed as a sequence of adds (otherwise this optimization could change + // behaviour should an object have been provided a valueOf or toString method). + // + // Considering the above example, the sequnce of execution is: + // * evaluate operand (a) + // * evaluate operand (b) + // * convert (a) to primitive <- (this would be triggered by the first add) + // * convert (b) to primitive <- (ditto) + // * evaluate operand (c) + // * convert (c) to primitive <- (this would be triggered by the second add) + // And optionally, if there is an assignment: + // * convert (d) to primitive <- (this would be triggered by the assigning addition) + // + // As such we do not plant an op to convert the leftmost child now. Instead, use + // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion + // once the second node has been generated. However, if the leftmost child is an + // immediate we can trivially determine that no conversion will be required. + // If this is the case + if (leftMostAddChild->isString()) + leftMostAddChildTempRegister = 0; + + while (reverseExpressionList.size()) { + ExpressionNode* node = reverseExpressionList.last(); + reverseExpressionList.removeLast(); + + // Emit the code for the current node. + temporaryRegisters.append(generator.newTemporary()); + generator.emitNode(temporaryRegisters.last().get(), node); + + // On the first iteration of this loop, when we first reach this point we have just + // generated the second node, which means it is time to convert the leftmost operand. + if (leftMostAddChildTempRegister) { + generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister); + leftMostAddChildTempRegister = 0; // Only do this once. + } + // Plant a conversion for this node, if necessary. + if (!node->isString()) + generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get()); + } + ASSERT(temporaryRegisters.size() >= 3); + + // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. + // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. + if (emitExpressionInfoForMe) + generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); + + // If there is an assignment convert the lhs now. This will also copy lhs to + // the temporary register we allocated for it. + if (lhs) + generator.emitToPrimitive(temporaryRegisters[0].get(), lhs); + + return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size()); } RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { OpcodeID opcodeID = this->opcodeID(); + + if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) + return emitStrcat(generator, dst); + if (opcodeID == op_neq) { if (m_expr1->isNull() || m_expr2->isNull()) { RefPtr<RegisterID> src = generator.tempDestination(dst); - generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); + generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get()); } } - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); } @@ -1130,41 +910,41 @@ RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds { if (m_expr1->isNull() || m_expr2->isNull()) { RefPtr<RegisterID> src = generator.tempDestination(dst); - generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); + generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get()); } - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2); } RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2); } RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor())); } RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); } RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RefPtr<RegisterID> src2 = generator.emitNode(m_expr2); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitGetByIdExceptionInfo(op_instanceof); @@ -1176,28 +956,17 @@ RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterI // ------------------------------ LogicalOpNode ---------------------------- -LogicalOpNode::~LogicalOpNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void LogicalOpNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr1); - releaser.release(m_expr2); -} - RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> temp = generator.tempDestination(dst); RefPtr<Label> target = generator.newLabel(); - generator.emitNode(temp.get(), m_expr1.get()); + generator.emitNode(temp.get(), m_expr1); if (m_operator == OpLogicalAnd) generator.emitJumpIfFalse(temp.get(), target.get()); else generator.emitJumpIfTrue(temp.get(), target.get()); - generator.emitNode(temp.get(), m_expr2.get()); + generator.emitNode(temp.get(), m_expr2); generator.emitLabel(target.get()); return generator.moveToDestinationIfNeeded(dst, temp.get()); @@ -1205,32 +974,20 @@ RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ ConditionalNode ------------------------------ -ConditionalNode::~ConditionalNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ConditionalNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_logical); - releaser.release(m_expr1); - releaser.release(m_expr2); -} - RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> newDst = generator.finalDestination(dst); RefPtr<Label> beforeElse = generator.newLabel(); RefPtr<Label> afterElse = generator.newLabel(); - RegisterID* cond = generator.emitNode(m_logical.get()); + RegisterID* cond = generator.emitNode(m_logical); generator.emitJumpIfFalse(cond, beforeElse.get()); - generator.emitNode(newDst.get(), m_expr1.get()); + generator.emitNode(newDst.get(), m_expr1); generator.emitJump(afterElse.get()); generator.emitLabel(beforeElse.get()); - generator.emitNode(newDst.get(), m_expr2.get()); + generator.emitNode(newDst.get(), m_expr2); generator.emitLabel(afterElse.get()); @@ -1239,18 +996,8 @@ RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, Register // ------------------------------ ReadModifyResolveNode ----------------------------------- -ReadModifyResolveNode::~ReadModifyResolveNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ReadModifyResolveNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_right); -} - // FIXME: should this be moved to be a method on BytecodeGenerator? -static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types) +static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0) { OpcodeID opcodeID; switch (oper) { @@ -1261,6 +1008,8 @@ static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& gen opcodeID = op_div; break; case OpPlusEq: + if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString()) + return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe); opcodeID = op_add; break; case OpMinusEq: @@ -1291,7 +1040,14 @@ static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& gen ASSERT_NOT_REACHED(); return dst; } - + + RegisterID* src2 = generator.emitNode(m_right); + + // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. + // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. + if (emitExpressionInfoForMe) + generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); + return generator.emitBinaryOp(opcodeID, dst, src1, src2, types); } @@ -1299,21 +1055,18 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re { if (RegisterID* local = generator.registerFor(m_ident)) { if (generator.isLocalConstant(m_ident)) { - RegisterID* src2 = generator.emitNode(m_right.get()); - return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); } if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { RefPtr<RegisterID> result = generator.newTemporary(); generator.emitMove(result.get(), local); - RegisterID* src2 = generator.emitNode(m_right.get()); - emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitMove(local, result.get()); return generator.moveToDestinationIfNeeded(dst, result.get()); } - RegisterID* src2 = generator.emitNode(m_right.get()); - RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); return generator.moveToDestinationIfNeeded(dst, result); } @@ -1322,8 +1075,7 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re JSObject* globalObject = 0; if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); - RegisterID* src2 = generator.emitNode(m_right.get()); - RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitPutScopedVar(depth, index, result, globalObject); return result; } @@ -1331,31 +1083,19 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re RefPtr<RegisterID> src1 = generator.tempDestination(dst); generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0); RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident); - RegisterID* src2 = generator.emitNode(m_right.get()); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); return generator.emitPutById(base.get(), m_ident, result); } // ------------------------------ AssignResolveNode ----------------------------------- -AssignResolveNode::~AssignResolveNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void AssignResolveNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_right); -} - RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RegisterID* local = generator.registerFor(m_ident)) { if (generator.isLocalConstant(m_ident)) - return generator.emitNode(dst, m_right.get()); + return generator.emitNode(dst, m_right); - RegisterID* result = generator.emitNode(local, m_right.get()); + RegisterID* result = generator.emitNode(local, m_right); return generator.moveToDestinationIfNeeded(dst, result); } @@ -1365,7 +1105,7 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { if (dst == generator.ignoredResult()) dst = 0; - RegisterID* value = generator.emitNode(dst, m_right.get()); + RegisterID* value = generator.emitNode(dst, m_right); generator.emitPutScopedVar(depth, index, value, globalObject); return value; } @@ -1373,29 +1113,18 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); if (dst == generator.ignoredResult()) dst = 0; - RegisterID* value = generator.emitNode(dst, m_right.get()); + RegisterID* value = generator.emitNode(dst, m_right); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitPutById(base.get(), m_ident, value); } // ------------------------------ AssignDotNode ----------------------------------- -AssignDotNode::~AssignDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void AssignDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_right); -} - RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); - RegisterID* result = generator.emitNode(value.get(), m_right.get()); + RegisterID* result = generator.emitNode(value.get(), m_right); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutById(base.get(), m_ident, result); return generator.moveToDestinationIfNeeded(dst, result); @@ -1403,25 +1132,13 @@ RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ ReadModifyDotNode ----------------------------------- -ReadModifyDotNode::~ReadModifyDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ReadModifyDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_right); -} - RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); - RegisterID* change = generator.emitNode(m_right.get()); - RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitPutById(base.get(), m_ident, updatedValue); @@ -1429,17 +1146,6 @@ RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ AssignErrorNode ----------------------------------- -AssignErrorNode::~AssignErrorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void AssignErrorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_left); - releaser.release(m_right); -} - RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference."); @@ -1447,24 +1153,12 @@ RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, Register // ------------------------------ AssignBracketNode ----------------------------------- -AssignBracketNode::~AssignBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void AssignBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); - releaser.release(m_right); -} - RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); - RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); + RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); - RegisterID* result = generator.emitNode(value.get(), m_right.get()); + RegisterID* result = generator.emitNode(value.get(), m_right); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutByVal(base.get(), property.get(), result); @@ -1473,27 +1167,14 @@ RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ ReadModifyBracketNode ----------------------------------- -ReadModifyBracketNode::~ReadModifyBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ReadModifyBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); - releaser.release(m_right); -} - RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); - RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); + RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); - RegisterID* change = generator.emitNode(m_right.get()); - RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutByVal(base.get(), property.get(), updatedValue); @@ -1503,63 +1184,34 @@ RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, Re // ------------------------------ CommaNode ------------------------------------ -CommaNode::~CommaNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void CommaNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr1); - releaser.release(m_expr2); -} - RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitNode(generator.ignoredResult(), m_expr1.get()); - return generator.emitNode(dst, m_expr2.get()); + generator.emitNode(generator.ignoredResult(), m_expr1); + return generator.emitNode(dst, m_expr2); } // ------------------------------ ConstDeclNode ------------------------------------ -ConstDeclNode::~ConstDeclNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ConstDeclNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); - releaser.release(m_init); -} - -ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init) - : ExpressionNode(globalData) - , m_ident(ident) - , m_init(init) -{ -} - RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) { if (RegisterID* local = generator.constRegisterFor(m_ident)) { if (!m_init) return local; - return generator.emitNode(local, m_init.get()); + return generator.emitNode(local, m_init); } // 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); - RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined()); + RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined()); return generator.emitPutById(base.get(), m_ident, value); } RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { RegisterID* result = 0; - for (ConstDeclNode* n = this; n; n = n->m_next.get()) + for (ConstDeclNode* n = this; n; n = n->m_next) result = n->emitCodeSingle(generator); return result; @@ -1567,65 +1219,34 @@ RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ ConstStatementNode ----------------------------- -ConstStatementNode::~ConstStatementNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ConstStatementNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); -} - RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - return generator.emitNode(m_next.get()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + return generator.emitNode(m_next); } // ------------------------------ Helper functions for handling Vectors of StatementNode ------------------------------- -static inline RegisterID* statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst) -{ - StatementVector::const_iterator end = statements.end(); - for (StatementVector::const_iterator it = statements.begin(); it != end; ++it) { - StatementNode* n = it->get(); - if (!n->isLoop()) - generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine()); - generator.emitNode(dst, n); - } - return 0; -} - -// ------------------------------ BlockNode ------------------------------------ - -BlockNode::~BlockNode() +static inline void statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst) { - NodeReleaser::releaseAllNodes(this); -} - -void BlockNode::releaseNodes(NodeReleaser& releaser) -{ - size_t size = m_children.size(); + size_t size = statements.size(); for (size_t i = 0; i < size; ++i) - releaser.release(m_children[i]); + generator.emitNode(dst, statements[i]); } -BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children) - : StatementNode(globalData) -{ - if (children) - children->releaseContentsIntoVector(m_children); -} +// ------------------------------ BlockNode ------------------------------------ RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - return statementListEmitCode(m_children, generator, dst); + statementListEmitCode(m_children, generator, dst); + return 0; } // ------------------------------ EmptyStatementNode --------------------------- -RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID* dst) +RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); return dst; } @@ -1642,51 +1263,31 @@ RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, Re RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { ASSERT(m_expr); - return generator.emitNode(dst, m_expr.get()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + return generator.emitNode(dst, m_expr); } // ------------------------------ VarStatementNode ---------------------------- -VarStatementNode::~VarStatementNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void VarStatementNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { ASSERT(m_expr); - return generator.emitNode(m_expr.get()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + return generator.emitNode(m_expr); } // ------------------------------ IfNode --------------------------------------- -IfNode::~IfNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void IfNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_condition); - releaser.release(m_ifBlock); -} - RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + RefPtr<Label> afterThen = generator.newLabel(); - RegisterID* cond = generator.emitNode(m_condition.get()); + RegisterID* cond = generator.emitNode(m_condition); generator.emitJumpIfFalse(cond, afterThen.get()); - if (!m_ifBlock->isBlock()) - generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine()); - - generator.emitNode(dst, m_ifBlock.get()); + generator.emitNode(dst, m_ifBlock); generator.emitLabel(afterThen.get()); // FIXME: This should return the last statement executed so that it can be returned as a Completion. @@ -1695,37 +1296,22 @@ RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) // ------------------------------ IfElseNode --------------------------------------- -IfElseNode::~IfElseNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void IfElseNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_elseBlock); - IfNode::releaseNodes(releaser); -} - RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + RefPtr<Label> beforeElse = generator.newLabel(); RefPtr<Label> afterElse = generator.newLabel(); - RegisterID* cond = generator.emitNode(m_condition.get()); + RegisterID* cond = generator.emitNode(m_condition); generator.emitJumpIfFalse(cond, beforeElse.get()); - if (!m_ifBlock->isBlock()) - generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine()); - - generator.emitNode(dst, m_ifBlock.get()); + generator.emitNode(dst, m_ifBlock); generator.emitJump(afterElse.get()); generator.emitLabel(beforeElse.get()); - if (!m_elseBlock->isBlock()) - generator.emitDebugHook(WillExecuteStatement, m_elseBlock->firstLine(), m_elseBlock->lastLine()); - - generator.emitNode(dst, m_elseBlock.get()); + generator.emitNode(dst, m_elseBlock); generator.emitLabel(afterElse.get()); @@ -1735,17 +1321,6 @@ RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d // ------------------------------ DoWhileNode ---------------------------------- -DoWhileNode::~DoWhileNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DoWhileNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_statement); - releaser.release(m_expr); -} - RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); @@ -1754,15 +1329,12 @@ RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* generator.emitLabel(topOfLoop.get()); generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); - - if (!m_statement->isBlock()) - generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine()); - - RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get()); + + RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); - RegisterID* cond = generator.emitNode(m_expr.get()); + RegisterID* cond = generator.emitNode(m_expr); generator.emitJumpIfTrue(cond, topOfLoop.get()); generator.emitLabel(scope->breakTarget()); @@ -1771,17 +1343,6 @@ RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* // ------------------------------ WhileNode ------------------------------------ -WhileNode::~WhileNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void WhileNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_statement); -} - RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); @@ -1790,15 +1351,12 @@ RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RefPtr<Label> topOfLoop = generator.newLabel(); generator.emitLabel(topOfLoop.get()); - - if (!m_statement->isBlock()) - generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine()); - - generator.emitNode(dst, m_statement.get()); + + generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); - RegisterID* cond = generator.emitNode(m_expr.get()); + RegisterID* cond = generator.emitNode(m_expr); generator.emitJumpIfTrue(cond, topOfLoop.get()); generator.emitLabel(scope->breakTarget()); @@ -1809,19 +1367,6 @@ RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ------------------------------ ForNode -------------------------------------- -ForNode::~ForNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ForNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr1); - releaser.release(m_expr2); - releaser.release(m_expr3); - releaser.release(m_statement); -} - RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (dst == generator.ignoredResult()) @@ -1832,7 +1377,7 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (m_expr1) - generator.emitNode(generator.ignoredResult(), m_expr1.get()); + generator.emitNode(generator.ignoredResult(), m_expr1); RefPtr<Label> condition = generator.newLabel(); generator.emitJump(condition.get()); @@ -1840,17 +1385,16 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) RefPtr<Label> topOfLoop = generator.newLabel(); generator.emitLabel(topOfLoop.get()); - if (!m_statement->isBlock()) - generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine()); - RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get()); + RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (m_expr3) - generator.emitNode(generator.ignoredResult(), m_expr3.get()); + generator.emitNode(generator.ignoredResult(), m_expr3); generator.emitLabel(condition.get()); if (m_expr2) { - RegisterID* cond = generator.emitNode(m_expr2.get()); + RegisterID* cond = generator.emitNode(m_expr2); generator.emitJumpIfTrue(cond, topOfLoop.get()); } else generator.emitJump(topOfLoop.get()); @@ -1861,45 +1405,6 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) // ------------------------------ ForInNode ------------------------------------ -ForInNode::~ForInNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ForInNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_init); - releaser.release(m_lexpr); - releaser.release(m_expr); - releaser.release(m_statement); -} - -ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement) - : StatementNode(globalData) - , m_init(0L) - , m_lexpr(l) - , m_expr(expr) - , m_statement(statement) - , m_identIsVarDecl(false) -{ -} - -ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset) - : StatementNode(globalData) - , m_ident(ident) - , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset)) - , m_expr(expr) - , m_statement(statement) - , m_identIsVarDecl(true) -{ - if (in) { - AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true); - node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot); - m_init = node; - } - // for( var foo = bar in baz ) -} - RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); @@ -1912,8 +1417,8 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (m_init) - generator.emitNode(generator.ignoredResult(), m_init.get()); - RegisterID* forInBase = generator.emitNode(m_expr.get()); + generator.emitNode(generator.ignoredResult(), m_init); + RegisterID* forInBase = generator.emitNode(m_expr); RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase); generator.emitJump(scope->continueTarget()); @@ -1922,7 +1427,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* propertyName; if (m_lexpr->isResolveNode()) { - const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier(); + const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); propertyName = generator.registerFor(ident); if (!propertyName) { propertyName = generator.newTemporary(); @@ -1933,7 +1438,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitPutById(base, ident, propertyName); } } else if (m_lexpr->isDotAccessorNode()) { - DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get()); + DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr); const Identifier& ident = assignNode->identifier(); propertyName = generator.newTemporary(); RefPtr<RegisterID> protect = propertyName; @@ -1943,7 +1448,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitPutById(base, ident, propertyName); } else { ASSERT(m_lexpr->isBracketAccessorNode()); - BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get()); + BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr); propertyName = generator.newTemporary(); RefPtr<RegisterID> protect = propertyName; RefPtr<RegisterID> base = generator.emitNode(assignNode->base()); @@ -1953,12 +1458,11 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitPutByVal(base.get(), subscript, propertyName); } - if (!m_statement->isBlock()) - generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine()); - generator.emitNode(dst, m_statement.get()); + generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); generator.emitLabel(scope->breakTarget()); return dst; } @@ -1968,6 +1472,8 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ECMA 12.7 RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + LabelScope* scope = generator.continueTarget(m_ident); if (!scope) @@ -1984,6 +1490,8 @@ RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* // ECMA 12.8 RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + LabelScope* scope = generator.breakTarget(m_ident); if (!scope) @@ -1997,26 +1505,22 @@ RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ------------------------------ ReturnNode ----------------------------------- -ReturnNode::~ReturnNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ReturnNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_value); -} - RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (generator.codeType() != FunctionCode) return emitThrowError(generator, SyntaxError, "Invalid return statement."); if (dst == generator.ignoredResult()) dst = 0; - RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined()); + RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined()); + RefPtr<RegisterID> returnRegister; if (generator.scopeDepth()) { RefPtr<Label> l0 = generator.newLabel(); + if (generator.hasFinaliser() && !r0->isTemporary()) { + returnRegister = generator.emitMove(generator.newTemporary(), r0); + r0 = returnRegister.get(); + } generator.emitJumpScopes(l0.get(), 0); generator.emitLabel(l0.get()); } @@ -2026,67 +1530,21 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d // ------------------------------ WithNode ------------------------------------- -WithNode::~WithNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void WithNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_statement); -} - RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + RefPtr<RegisterID> scope = generator.newTemporary(); - generator.emitNode(scope.get(), m_expr.get()); // scope must be protected until popped + generator.emitNode(scope.get(), m_expr); // scope must be protected until popped generator.emitExpressionInfo(m_divot, m_expressionLength, 0); generator.emitPushScope(scope.get()); - RegisterID* result = generator.emitNode(dst, m_statement.get()); + RegisterID* result = generator.emitNode(dst, m_statement); generator.emitPopScope(); return result; } -// ------------------------------ CaseClauseNode -------------------------------- - -CaseClauseNode::~CaseClauseNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void CaseClauseNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - -// ------------------------------ ClauseListNode -------------------------------- - -ClauseListNode::~ClauseListNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ClauseListNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_clause); - releaser.release(m_next); -} - // ------------------------------ CaseBlockNode -------------------------------- -CaseBlockNode::~CaseBlockNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void CaseBlockNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_list1); - releaser.release(m_defaultClause); - releaser.release(m_list2); -} - enum SwitchKind { SwitchUnset = 0, SwitchNumber = 1, @@ -2101,7 +1559,8 @@ static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector.append(clauseExpression); if (clauseExpression->isNumber()) { double value = static_cast<NumberNode*>(clauseExpression)->value(); - if ((typeForTable & ~SwitchNumber) || !JSImmediate::from(value)) { + JSValue jsValue = JSValue::makeInt32Fast(static_cast<int32_t>(value)); + if ((typeForTable & ~SwitchNumber) || !jsValue || (jsValue.getInt32Fast() != value)) { typeForTable = SwitchNeither; break; } @@ -2140,8 +1599,8 @@ SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, SwitchKind typeForTable = SwitchUnset; bool singleCharacterSwitch = true; - processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); - processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); + processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); + processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); if (typeForTable == SwitchUnset || typeForTable == SwitchNeither) return SwitchInfo::SwitchNone; @@ -2181,7 +1640,7 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re generator.beginSwitch(switchExpression, switchType); } else { // Setup jumps - for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) { + for (ClauseListNode* list = m_list1; list; list = list->getNext()) { RefPtr<RegisterID> clauseVal = generator.newTemporary(); generator.emitNode(clauseVal.get(), list->getClause()->expr()); generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); @@ -2189,7 +1648,7 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); } - for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) { + for (ClauseListNode* list = m_list2; list; list = list->getNext()) { RefPtr<RegisterID> clauseVal = generator.newTemporary(); generator.emitNode(clauseVal.get(), list->getClause()->expr()); generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); @@ -2203,19 +1662,19 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re RegisterID* result = 0; size_t i = 0; - for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) { + for (ClauseListNode* list = m_list1; list; list = list->getNext()) { generator.emitLabel(labelVector[i++].get()); - result = statementListEmitCode(list->getClause()->children(), generator, dst); + statementListEmitCode(list->getClause()->children(), generator, dst); } if (m_defaultClause) { generator.emitLabel(defaultLabel.get()); - result = statementListEmitCode(m_defaultClause->children(), generator, dst); + statementListEmitCode(m_defaultClause->children(), generator, dst); } - for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) { + for (ClauseListNode* list = m_list2; list; list = list->getNext()) { generator.emitLabel(labelVector[i++].get()); - result = statementListEmitCode(list->getClause()->children(), generator, dst); + statementListEmitCode(list->getClause()->children(), generator, dst); } if (!m_defaultClause) generator.emitLabel(defaultLabel.get()); @@ -2230,22 +1689,13 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re // ------------------------------ SwitchNode ----------------------------------- -SwitchNode::~SwitchNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void SwitchNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_block); -} - RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch); - RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get()); + RefPtr<RegisterID> r0 = generator.emitNode(m_expr); RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst); generator.emitLabel(scope->breakTarget()); @@ -2254,23 +1704,15 @@ RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d // ------------------------------ LabelNode ------------------------------------ -LabelNode::~LabelNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void LabelNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_statement); -} - RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + if (generator.breakTarget(m_name)) return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name); RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name); - RegisterID* r0 = generator.emitNode(dst, m_statement.get()); + RegisterID* r0 = generator.emitNode(dst, m_statement); generator.emitLabel(scope->breakTarget()); return r0; @@ -2278,42 +1720,24 @@ RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ------------------------------ ThrowNode ------------------------------------ -ThrowNode::~ThrowNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ThrowNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + if (dst == generator.ignoredResult()) dst = 0; - RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get()); + RefPtr<RegisterID> expr = generator.emitNode(m_expr); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitThrow(expr.get()); - return dst; + return 0; } // ------------------------------ TryNode -------------------------------------- -TryNode::~TryNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void TryNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_tryBlock); - releaser.release(m_catchBlock); - releaser.release(m_finallyBlock); -} - RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + RefPtr<Label> tryStartLabel = generator.newLabel(); RefPtr<Label> tryEndLabel = generator.newLabel(); RefPtr<Label> finallyStart; @@ -2324,7 +1748,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get()); } generator.emitLabel(tryStartLabel.get()); - generator.emitNode(dst, m_tryBlock.get()); + generator.emitNode(dst, m_tryBlock); generator.emitLabel(tryEndLabel.get()); if (m_catchBlock) { @@ -2338,7 +1762,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) generator.emitPushScope(exceptionRegister.get()); } else generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); - generator.emitNode(dst, m_catchBlock.get()); + generator.emitNode(dst, m_catchBlock); generator.emitPopScope(); generator.emitLabel(handlerEndLabel.get()); } @@ -2367,7 +1791,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) // emit the finally block itself generator.emitLabel(finallyStart.get()); - generator.emitNode(dst, m_finallyBlock.get()); + generator.emitNode(dst, m_finallyBlock); generator.emitSubroutineReturn(finallyReturnAddr.get()); generator.emitLabel(finallyEndLabel.get()); @@ -2376,77 +1800,73 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) return dst; } -// ------------------------------ ParameterNode ----------------------------- - -ParameterNode::~ParameterNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ParameterNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); -} - // -----------------------------ScopeNodeData --------------------------- -ScopeNodeData::ScopeNodeData(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants) +ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants) : m_numConstants(numConstants) { + m_arena.swap(arena); if (varStack) - m_varStack = *varStack; + m_varStack.swap(*varStack); if (funcStack) - m_functionStack = *funcStack; + m_functionStack.swap(*funcStack); if (children) children->releaseContentsIntoVector(m_children); } +void ScopeNodeData::mark() +{ + 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().mark(); + } +} + // ------------------------------ ScopeNode ----------------------------- ScopeNode::ScopeNode(JSGlobalData* globalData) : StatementNode(globalData) + , ParserArenaRefCounted(globalData) , m_features(NoFeatures) { -#if ENABLE(OPCODE_SAMPLING) - globalData->interpreter->sampler()->notifyOfScope(this); +#if ENABLE(CODEBLOCK_SAMPLING) + if (SamplingTool* sampler = globalData->interpreter->sampler()) + sampler->notifyOfScope(this); #endif } ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants) : StatementNode(globalData) - , m_data(new ScopeNodeData(children, varStack, funcStack, numConstants)) + , ParserArenaRefCounted(globalData) + , m_data(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants)) , m_features(features) , m_source(source) { -#if ENABLE(OPCODE_SAMPLING) - globalData->interpreter->sampler()->notifyOfScope(this); +#if ENABLE(CODEBLOCK_SAMPLING) + if (SamplingTool* sampler = globalData->interpreter->sampler()) + sampler->notifyOfScope(this); #endif } -ScopeNode::~ScopeNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ScopeNode::releaseNodes(NodeReleaser& releaser) -{ - if (!m_data) - return; - size_t size = m_data->m_children.size(); - for (size_t i = 0; i < size; ++i) - releaser.release(m_data->m_children[i]); -} - // ------------------------------ ProgramNode ----------------------------- -ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants) { } -ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) { - return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants); + RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants); + + ASSERT(node->data()->m_arena.last() == node); + node->data()->m_arena.removeLast(); + ASSERT(!node->data()->m_arena.contains(node.get())); + + return node.release(); } RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) @@ -2475,16 +1895,33 @@ void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode) 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 ----------------------------- -EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants) { } -EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) { - return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants); + RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants); + + ASSERT(node->data()->m_arena.last() == node); + node->data()->m_arena.removeLast(); + ASSERT(!node->data()->m_arena.contains(node.get())); + + return node.release(); } RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) @@ -2505,7 +1942,7 @@ void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode) ScopeChain scopeChain(scopeChainNode); JSGlobalObject* globalObject = scopeChain.globalObject(); - m_code.set(new EvalCodeBlock(this, globalObject, source().provider())); + m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())); BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); generator.generate(); @@ -2515,43 +1952,57 @@ void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode) children().clear(); } -EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode) +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())); + m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())); BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); - generator.setRegeneratingForExceptionInfo(); + generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom); generator.generate(); return *m_code; } +void EvalNode::mark() +{ + // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that + data()->mark(); +} + +#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 ----------------------------- -FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData) : ScopeNode(globalData) , m_parameters(0) , m_parameterCount(0) - , m_refCount(0) { } -FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants) , m_parameters(0) , m_parameterCount(0) - , m_refCount(0) { } FunctionBodyNode::~FunctionBodyNode() { - ASSERT(!m_refCount); for (size_t i = 0; i < m_parameterCount; ++i) m_parameters[i].~Identifier(); fastFree(m_parameters); @@ -2581,14 +2032,30 @@ void FunctionBodyNode::mark() m_code->mark(); } +#if ENABLE(JIT) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::createNativeThunk(JSGlobalData* globalData) +{ + RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData); + globalData->parser->arena().reset(); + body->m_jitCode = JITCode(JITCode::HostFunction(globalData->jitStubs.ctiNativeCallThunk())); + return body.release(); +} +#endif + FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData) { return new FunctionBodyNode(globalData); } -FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) { - return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants); + RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants); + + ASSERT(node->data()->m_arena.last() == node); + node->data()->m_arena.removeLast(); + ASSERT(!node->data()->m_arena.contains(node.get())); + + return node.release(); } void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode) @@ -2610,7 +2077,18 @@ void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode) destroyData(); } -CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode) +#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); @@ -2620,7 +2098,7 @@ CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* sco m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset())); BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); - generator.setRegeneratingForExceptionInfo(); + generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom); generator.generate(); return *m_code; @@ -2630,11 +2108,15 @@ RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, Registe { generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); statementListEmitCode(children(), generator, generator.ignoredResult()); - if (!children().size() || !children().last()->isReturnNode()) { - RegisterID* r0 = generator.emitLoad(0, jsUndefined()); - generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); - generator.emitReturn(r0); + if (children().size() && children().last()->isBlock()) { + BlockNode* blockNode = static_cast<BlockNode*>(children().last()); + if (blockNode->children().size() && blockNode->children().last()->isReturnNode()) + return 0; } + + RegisterID* r0 = generator.emitLoad(0, jsUndefined()); + generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); + generator.emitReturn(r0); return 0; } @@ -2659,17 +2141,6 @@ Identifier* FunctionBodyNode::copyParameters() // ------------------------------ FuncDeclNode --------------------------------- -FuncDeclNode::~FuncDeclNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FuncDeclNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_parameter); - releaser.release(m_body); -} - JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain) { return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain); @@ -2684,17 +2155,6 @@ RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* // ------------------------------ FuncExprNode --------------------------------- -FuncExprNode::~FuncExprNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FuncExprNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_parameter); - releaser.release(m_body); -} - RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { return generator.emitNewFunctionExpression(generator.finalDestination(dst), this); |