X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/9dae56ea45a0f5f8136a5c93d6f3a7f99399ca73..4be4e30906bcb8ee30b4d189205cb70bad6707ce:/parser/Nodes.cpp diff --git a/parser/Nodes.cpp b/parser/Nodes.cpp index 8aa1788..97ffaa1 100644 --- a/parser/Nodes.cpp +++ b/parser/Nodes.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) -* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. +* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel @@ -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 "JSNameScope.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 #include -#include -#include -#include #include #include @@ -50,2701 +49,175 @@ 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 void release(RefPtr& node) { if (node) adopt(node.release()); } - void release(RefPtr& node) { if (node) adoptFunctionBodyNode(node); } - -private: - NodeReleaser() { } - ~NodeReleaser() { } - - void adopt(PassRefPtr); - void adoptFunctionBodyNode(RefPtr&); - - typedef Vector > NodeReleaseVector; - OwnPtr 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 node) -{ - ASSERT(node); - if (!node->hasOneRef()) - return; - if (!m_vector) - m_vector.set(new NodeReleaseVector); - m_vector->append(node); -} - -void NodeReleaser::adoptFunctionBodyNode(RefPtr& functionBodyNode) -{ - // This sidesteps a problem where if you assign a PassRefPtr - // to a PassRefPtr 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 = 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; - 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::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; - 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::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::iterator end = globalData->newParserObjects->end(); - for (HashSet::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(); -} - -// ------------------------------ ThrowableExpressionData -------------------------------- - -static void substitute(UString& string, const UString& substring) -{ - int position = string.find("%s"); - ASSERT(position != -1); - UString newString = string.substr(0, position); - newString.append(substring); - newString.append(string.substr(position + 2)); - string = newString; -} - -RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg) -{ - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg)); - generator.emitThrow(exception); - return exception; -} -RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label) -{ - UString message = msg; - substitute(message, label.ustring()); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message)); - generator.emitThrow(exception); - return exception; -} - // ------------------------------ StatementNode -------------------------------- -StatementNode::StatementNode(JSGlobalData* globalData) - : Node(globalData) - , m_lastLine(-1) -{ -} - -void StatementNode::setLoc(int firstLine, int lastLine) +void StatementNode::setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset) { - m_line = firstLine; + m_lineNumber = firstLine; m_lastLine = lastLine; + m_startOffset = startOffset; + m_lineStartOffset = lineStartOffset; + ASSERT(m_startOffset >= m_lineStartOffset); } // ------------------------------ SourceElements -------------------------------- -void SourceElements::append(PassRefPtr statement) +void SourceElements::append(StatementNode* statement) { if (statement->isEmptyStatement()) return; - m_statements.append(statement); } -// ------------------------------ NullNode ------------------------------------- - -RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.emitLoad(dst, jsNull()); -} - -// ------------------------------ BooleanNode ---------------------------------- - -RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.emitLoad(dst, m_value); -} - -// ------------------------------ NumberNode ----------------------------------- - -RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.emitLoad(dst, m_double); -} - -// ------------------------------ StringNode ----------------------------------- - -RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.emitLoad(dst, m_value); -} - -// ------------------------------ RegExpNode ----------------------------------- - -RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr regExp = RegExp::create(generator.globalData(), m_pattern, m_flags); - if (!regExp->isValid()) - return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str()); - if (dst == generator.ignoredResult()) - return 0; - return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get()); -} - -// ------------------------------ ThisNode ------------------------------------- - -RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.moveToDestinationIfNeeded(dst, generator.thisRegister()); -} - -// ------------------------------ ResolveNode ---------------------------------- - -bool ResolveNode::isPure(BytecodeGenerator& generator) const -{ - return generator.isLocal(m_ident); -} - -RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RegisterID* local = generator.registerFor(m_ident)) { - if (dst == generator.ignoredResult()) - return 0; - return generator.moveToDestinationIfNeeded(dst, local); - } - - generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0); - 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()) { - if (firstPutElement->elision()) - break; - ++length; - } - - if (!firstPutElement && !m_elision) - return generator.emitNewArray(generator.finalDestination(dst), m_element.get()); - - RefPtr array = generator.emitNewArray(generator.tempDestination(dst), m_element.get()); - - for (ElementNode* n = firstPutElement; n; n = n->next()) { - RegisterID* value = generator.emitNode(n->value()); - length += n->elision(); - generator.emitPutByIndex(array.get(), length++, value); - } - - if (m_elision) { - RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length)); - generator.emitPutById(array.get(), generator.propertyNames().length, value); - } - - return generator.moveToDestinationIfNeeded(dst, array.get()); -} - -// ------------------------------ PropertyNode ---------------------------- - -PropertyNode::~PropertyNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PropertyNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_assign); -} - -// ------------------------------ 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) { - if (dst == generator.ignoredResult()) - return 0; - return generator.emitNewObject(generator.finalDestination(dst)); - } - return generator.emitNode(dst, m_list.get()); -} - -// ------------------------------ 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 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()); - - switch (p->m_node->m_type) { - case PropertyNode::Constant: { - generator.emitPutById(newObj.get(), p->m_node->name(), value); - break; - } - case PropertyNode::Getter: { - generator.emitPutGetter(newObj.get(), p->m_node->name(), value); - break; - } - case PropertyNode::Setter: { - generator.emitPutSetter(newObj.get(), p->m_node->name(), value); - break; - } - default: - ASSERT_NOT_REACHED(); - } - } - - return generator.moveToDestinationIfNeeded(dst, newObj.get()); -} - -// ------------------------------ 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 base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator)); - RegisterID* property = generator.emitNode(m_subscript.get()); - 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()); - 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); -} - -// ------------------------------ 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 func = generator.emitNode(m_expr.get()); - return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), 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) +StatementNode* SourceElements::singleStatement() const { - RefPtr func = generator.tempDestination(dst); - RefPtr 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()); + size_t size = m_statements.size(); + return size == 1 ? m_statements[0] : 0; } -// ------------------------------ 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 func = generator.emitNode(m_expr.get()); - RefPtr thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); -} - -// ------------------------------ FunctionCallResolveNode ---------------------------------- - -FunctionCallResolveNode::~FunctionCallResolveNode() -{ - NodeReleaser::releaseAllNodes(this); -} +// ------------------------------ ScopeNode ----------------------------- -void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser) +ScopeNode::ScopeNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, bool inStrictContext) + : StatementNode(endLocation) + , ParserArenaRefCounted(vm) + , m_startLineNumber(startLocation.line) + , m_startStartOffset(startLocation.startOffset) + , m_startLineStartOffset(startLocation.lineStartOffset) + , m_features(inStrictContext ? StrictModeFeature : NoFeatures) + , m_numConstants(0) + , m_statements(0) { - releaser.release(m_args); } -RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +ScopeNode::ScopeNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants) + : StatementNode(endLocation) + , ParserArenaRefCounted(vm) + , m_startLineNumber(startLocation.line) + , m_startStartOffset(startLocation.startOffset) + , m_startLineStartOffset(startLocation.lineStartOffset) + , m_features(features) + , m_source(source) + , m_numConstants(numConstants) + , m_statements(children) { - if (RefPtr local = generator.registerFor(m_ident)) { - RefPtr thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); - } - - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { - RefPtr func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); - RefPtr thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); - } - - RefPtr func = generator.tempDestination(dst); - RefPtr 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()); + m_arena.swap(*vm->parserArena); + if (varStack) + m_varStack.swap(*varStack); + if (funcStack) + m_functionStack.swap(*funcStack); + m_capturedVariables.swap(capturedVariables); } -// ------------------------------ FunctionCallBracketNode ---------------------------------- - -FunctionCallBracketNode::~FunctionCallBracketNode() +StatementNode* ScopeNode::singleStatement() const { - NodeReleaser::releaseAllNodes(this); + return m_statements ? m_statements->singleStatement() : 0; } -void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); - releaser.release(m_args); -} +// ------------------------------ ProgramNode ----------------------------- -RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +inline ProgramNode::ProgramNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) + : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants) + , m_startColumn(startColumn) { - RefPtr base = generator.emitNode(m_base.get()); - RegisterID* property = generator.emitNode(m_subscript.get()); - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); - RefPtr 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()); } -// ------------------------------ FunctionCallDotNode ---------------------------------- - -FunctionCallDotNode::~FunctionCallDotNode() +PassRefPtr ProgramNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - NodeReleaser::releaseAllNodes(this); -} + RefPtr node = new ProgramNode(vm, startLocation, endLocation, startColumn, children, varStack, funcStack, capturedVariables, source, features, numConstants); -void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_args); -} + ASSERT(node->m_arena.last() == node); + node->m_arena.removeLast(); + ASSERT(!node->m_arena.contains(node.get())); -RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr base = generator.emitNode(m_base.get()); - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); - RefPtr 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 node.release(); } -// ------------------------------ PostfixResolveNode ---------------------------------- - -static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper) -{ - return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst); -} +// ------------------------------ EvalNode ----------------------------- -static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper) +inline EvalNode::EvalNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) + : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants) { - return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst); } -RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +PassRefPtr EvalNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - if (RegisterID* local = generator.registerFor(m_ident)) { - if (generator.isLocalConstant(m_ident)) { - if (dst == generator.ignoredResult()) - return 0; - return generator.emitToJSNumber(generator.finalDestination(dst), local); - } - - if (dst == generator.ignoredResult()) - return emitPreIncOrDec(generator, local, m_operator); - return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator); - } + RefPtr node = new EvalNode(vm, startLocation, endLocation, children, varStack, funcStack, capturedVariables, source, features, numConstants); - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { - RefPtr value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); - RegisterID* oldValue; - if (dst == generator.ignoredResult()) { - oldValue = 0; - emitPreIncOrDec(generator, value.get(), m_operator); - } else { - oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); - } - generator.emitPutScopedVar(depth, index, value.get(), globalObject); - return oldValue; - } + ASSERT(node->m_arena.last() == node); + node->m_arena.removeLast(); + ASSERT(!node->m_arena.contains(node.get())); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RefPtr value = generator.newTemporary(); - RefPtr base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident); - RegisterID* oldValue; - if (dst == generator.ignoredResult()) { - oldValue = 0; - emitPreIncOrDec(generator, value.get(), m_operator); - } else { - oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); - } - generator.emitPutById(base.get(), m_ident, value.get()); - return oldValue; + return node.release(); } -// ------------------------------ PostfixBracketNode ---------------------------------- +// ------------------------------ FunctionBodyNode ----------------------------- -PostfixBracketNode::~PostfixBracketNode() +PassRefPtr FunctionParameters::create(ParameterNode* firstParameter) { - NodeReleaser::releaseAllNodes(this); -} + unsigned parameterCount = 0; + for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam()) + ++parameterCount; -void PostfixBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); + size_t objectSize = sizeof(FunctionParameters) - sizeof(void*) + sizeof(StringImpl*) * parameterCount; + void* slot = fastMalloc(objectSize); + return adoptRef(new (slot) FunctionParameters(firstParameter, parameterCount)); } -RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +FunctionParameters::FunctionParameters(ParameterNode* firstParameter, unsigned size) + : m_size(size) { - RefPtr base = generator.emitNode(m_base.get()); - RefPtr property = generator.emitNode(m_subscript.get()); - - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get()); - RegisterID* oldValue; - if (dst == generator.ignoredResult()) { - oldValue = 0; - if (m_operator == OpPlusPlus) - generator.emitPreInc(value.get()); - else - generator.emitPreDec(value.get()); - } else { - oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); - } - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutByVal(base.get(), property.get(), value.get()); - return oldValue; + unsigned i = 0; + for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam()) + new (&identifiers()[i++]) Identifier(parameter->ident()); } -// ------------------------------ PostfixDotNode ---------------------------------- - -PostfixDotNode::~PostfixDotNode() +FunctionParameters::~FunctionParameters() { - NodeReleaser::releaseAllNodes(this); + for (unsigned i = 0; i < m_size; ++i) + identifiers()[i].~Identifier(); } -void PostfixDotNode::releaseNodes(NodeReleaser& releaser) +inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext) + : ScopeNode(vm, startLocation, endLocation, inStrictContext) + , m_startColumn(startColumn) { - releaser.release(m_base); } -RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) + : ScopeNode(vm, startLocation, endLocation, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants) + , m_startColumn(startColumn) { - RefPtr base = generator.emitNode(m_base.get()); - - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); - RegisterID* oldValue; - if (dst == generator.ignoredResult()) { - oldValue = 0; - if (m_operator == OpPlusPlus) - generator.emitPreInc(value.get()); - else - generator.emitPreDec(value.get()); - } else { - oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); - } - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutById(base.get(), m_ident, value.get()); - return oldValue; } -// ------------------------------ PostfixErrorNode ----------------------------------- - -PostfixErrorNode::~PostfixErrorNode() +void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident, FunctionNameIsInScopeToggle functionNameIsInScopeToggle) { - NodeReleaser::releaseAllNodes(this); + setSource(source); + finishParsing(FunctionParameters::create(firstParameter), ident, functionNameIsInScopeToggle); } -void PostfixErrorNode::releaseNodes(NodeReleaser& releaser) +void FunctionBodyNode::finishParsing(PassRefPtr parameters, const Identifier& ident, FunctionNameIsInScopeToggle functionNameIsInScopeToggle) { - releaser.release(m_expr); + ASSERT(!source().isNull()); + m_parameters = parameters; + m_ident = ident; + m_functionNameIsInScopeToggle = functionNameIsInScopeToggle; } -RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +FunctionBodyNode* FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext) { - 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."); + return new FunctionBodyNode(vm, startLocation, endLocation, startColumn, inStrictContext); } -// ------------------------------ DeleteResolveNode ----------------------------------- - -RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +PassRefPtr FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) { - if (generator.registerFor(m_ident)) - return generator.emitUnexpectedLoad(generator.finalDestination(dst), false); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident); - return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident); -} - -// ------------------------------ 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 r0 = generator.emitNode(m_base.get()); - RegisterID* r1 = generator.emitNode(m_subscript.get()); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1); -} - -// ------------------------------ 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()); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident); -} - -// ------------------------------ 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()); - - // delete on a non-location expression ignores the value and returns true - return generator.emitUnexpectedLoad(generator.finalDestination(dst), true); -} - -// ------------------------------ 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()); - return 0; - } - RefPtr r0 = generator.emitNode(m_expr.get()); - return generator.emitLoad(dst, jsUndefined()); -} - -// ------------------------------ TypeOfValueNode ----------------------------------- - -RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RegisterID* local = generator.registerFor(m_ident)) { - if (dst == generator.ignoredResult()) - return 0; - return generator.emitTypeOf(generator.finalDestination(dst), local); - } - - RefPtr scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident); - generator.emitGetById(scratch.get(), scratch.get(), m_ident); - if (dst == generator.ignoredResult()) - return 0; - return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get()); -} - -// ------------------------------ 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()); - return 0; - } - RefPtr src = generator.emitNode(m_expr.get()); - return generator.emitTypeOf(generator.finalDestination(dst), src.get()); -} - -// ------------------------------ PrefixResolveNode ---------------------------------- - -RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RegisterID* local = generator.registerFor(m_ident)) { - if (generator.isLocalConstant(m_ident)) { - if (dst == generator.ignoredResult()) - return 0; - RefPtr r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0); - return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes()); - } - - emitPreIncOrDec(generator, local, m_operator); - return generator.moveToDestinationIfNeeded(dst, local); - } - - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { - RefPtr propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); - emitPreIncOrDec(generator, propDst.get(), m_operator); - generator.emitPutScopedVar(depth, index, propDst.get(), globalObject); - return generator.moveToDestinationIfNeeded(dst, propDst.get()); - } - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RefPtr propDst = generator.tempDestination(dst); - RefPtr base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident); - emitPreIncOrDec(generator, propDst.get(), m_operator); - generator.emitPutById(base.get(), m_ident, propDst.get()); - return generator.moveToDestinationIfNeeded(dst, propDst.get()); -} - -// ------------------------------ 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 base = generator.emitNode(m_base.get()); - RefPtr property = generator.emitNode(m_subscript.get()); - RefPtr propDst = generator.tempDestination(dst); - - generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); - RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get()); - if (m_operator == OpPlusPlus) - generator.emitPreInc(value); - else - generator.emitPreDec(value); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutByVal(base.get(), property.get(), value); - return generator.moveToDestinationIfNeeded(dst, propDst.get()); -} - -// ------------------------------ PrefixDotNode ---------------------------------- - -PrefixDotNode::~PrefixDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PrefixDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); -} - -RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr base = generator.emitNode(m_base.get()); - RefPtr propDst = generator.tempDestination(dst); - - generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); - RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident); - if (m_operator == OpPlusPlus) - generator.emitPreInc(value); - else - generator.emitPreDec(value); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutById(base.get(), m_ident, value); - return generator.moveToDestinationIfNeeded(dst, propDst.get()); -} - -// ------------------------------ 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."); -} - -// ------------------------------ 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()); - return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); -} - -// ------------------------------ Binary Operation Nodes ----------------------------------- - -BinaryOpNode::~BinaryOpNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void BinaryOpNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr1); - releaser.release(m_expr2); -} - -RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - OpcodeID opcodeID = this->opcodeID(); - if (opcodeID == op_neq) { - if (m_expr1->isNull() || m_expr2->isNull()) { - RefPtr src = generator.tempDestination(dst); - generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); - return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get()); - } - } - - RefPtr src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); - return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); -} - -RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (m_expr1->isNull() || m_expr2->isNull()) { - RefPtr src = generator.tempDestination(dst); - generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); - return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get()); - } - - RefPtr src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); - return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2); -} - -RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); - return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2); -} - -RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); - 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 src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); - 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 src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RefPtr src2 = generator.emitNode(m_expr2.get()); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitGetByIdExceptionInfo(op_instanceof); - RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype); -} - -// ------------------------------ 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 temp = generator.tempDestination(dst); - RefPtr