summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/javascriptcore/JavaScriptCore/parser
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-03-15 12:06:11 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-03-15 12:06:11 (GMT)
commit22fd80b88e4d75b65d48403975ff0e7fb77d4ae5 (patch)
tree4e2d72720f3852d8dcdb6b7eb1ea5c85f6487b36 /src/3rdparty/javascriptcore/JavaScriptCore/parser
parent33c6983a19942c151fa0bcc878b5219e0b641ba9 (diff)
parent2ee0c797d9bb582073b53cb1f8348abaf2acc0db (diff)
downloadQt-22fd80b88e4d75b65d48403975ff0e7fb77d4ae5.zip
Qt-22fd80b88e4d75b65d48403975ff0e7fb77d4ae5.tar.gz
Qt-22fd80b88e4d75b65d48403975ff0e7fb77d4ae5.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1: (61 commits) Fix broken setCollectionFile (creating multiple models instead reusing) Enable the fast paths when converting to Rgb565 qdoc: ifdefed out all the debug code. Add missing QtScript API shims Further fix license whitespace. Remove NetworkManager test-bed application. Remove configure test for NetworkManager. Fix QDir::entryList regression Add DEFINES to mingw32/windres.exe command line. Fix up whitespace in license headers. Fix SetDialogPreference build error on Symbian. get known wifi networks a more complicated way, but without accessing Only enable BM by default in QNAM for appropriate platforms. fix crash on 10.6 with no wifi interface Fix creation of QNetworkSession. Make QNetworkConfigurationManager and QNetworkConfiguration threadsafe. remove qt_winQString2MB() and qt_winMB2QString() Fix include() path in qimportbase.pri Fix qmake crash on Windows Compile ...
Diffstat (limited to 'src/3rdparty/javascriptcore/JavaScriptCore/parser')
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/parser/Grammar.y6
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.cpp11
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.h6
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/parser/NodeConstructors.h1
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.cpp1877
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.h16
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/parser/Parser.h3
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/parser/ParserArena.h2
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/parser/SourceCode.h3
9 files changed, 27 insertions, 1898 deletions
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Grammar.y b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Grammar.y
index fa4ffd0..717a266 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Grammar.y
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Grammar.y
@@ -27,6 +27,7 @@
#include "JSObject.h"
#include "JSString.h"
+#include "Lexer.h"
#include "NodeConstructors.h"
#include "NodeInfo.h"
#include <stdlib.h>
@@ -42,13 +43,12 @@
// Default values for bison.
#define YYDEBUG 0 // Set to 1 to debug a parse error.
#define jscyydebug 0 // Set to 1 to debug a parse error.
-#if !PLATFORM(DARWIN)
+#if !OS(DARWIN)
// Avoid triggering warnings in older bison by not setting this on the Darwin platform.
// FIXME: Is this still needed?
#define YYERROR_VERBOSE
#endif
-int jscyylex(void* lvalp, void* llocp, void* globalPtr);
int jscyyerror(const char*);
static inline bool allowAutomaticSemicolon(JSC::Lexer&, int);
@@ -179,7 +179,7 @@ static inline void appendToVarDeclarationList(JSGlobalData* globalData, ParserAr
template <typename T> inline void setStatementLocation(StatementNode* statement, const T& start, const T& end)
{
- statement->setLoc(start.first_line, end.last_line, start.first_column);
+ statement->setLoc(start.first_line, end.last_line);
}
static inline void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end)
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.cpp
index a85ed3d..e616c7a 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.cpp
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.cpp
@@ -39,19 +39,10 @@ using namespace Unicode;
// We can't specify the namespace in yacc's C output, so do it here instead.
using namespace JSC;
-#ifndef KDE_USE_FINAL
#include "Grammar.h"
-#endif
-
#include "Lookup.h"
#include "Lexer.lut.h"
-// A bridge for yacc from the C world to the C++ world.
-int jscyylex(void* lvalp, void* llocp, void* globalData)
-{
- return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
-}
-
namespace JSC {
static const UChar byteOrderMark = 0xFEFF;
@@ -652,6 +643,8 @@ inStringEscapeSequence:
shiftLineTerminator();
goto inString;
}
+ if (m_current == -1)
+ goto returnError;
record16(singleEscape(m_current));
shift1();
goto inString;
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.h
index 174e05a..c76696c 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.h
@@ -136,6 +136,12 @@ namespace JSC {
return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
}
+ // A bridge for yacc from the C world to the C++ world.
+ inline int jscyylex(void* lvalp, void* llocp, void* globalData)
+ {
+ return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
+ }
+
} // namespace JSC
#endif // Lexer_h
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/NodeConstructors.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/NodeConstructors.h
index 5431e18..8c9135f 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/NodeConstructors.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/NodeConstructors.h
@@ -46,7 +46,6 @@ namespace JSC {
inline StatementNode::StatementNode(JSGlobalData* globalData)
: Node(globalData)
, m_lastLine(-1)
- , m_column(-1)
{
}
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.cpp
index 89bbc11..4b97e9a 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.cpp
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.cpp
@@ -49,71 +49,13 @@ using namespace WTF;
namespace JSC {
-/*
- Details of the emitBytecode function.
-
- Return value: The register holding the production's value.
- dst: An optional parameter specifying the most efficient destination at
- which to store the production's value. The callee must honor dst.
-
- The dst argument provides for a crude form of copy propagation. For example,
-
- x = 1
-
- becomes
-
- load r[x], 1
-
- instead of
-
- load r0, 1
- mov r[x], r0
-
- because the assignment node, "x =", passes r[x] as dst to the number node, "1".
-*/
-
-// ------------------------------ 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 type, const char* message)
-{
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
- generator.emitThrow(exception);
- return exception;
-}
-
-RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label)
-{
- UString message = messageTemplate;
- substitute(message, label);
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
- generator.emitThrow(exception);
- return exception;
-}
-
-inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label)
-{
- return emitThrowError(generator, type, messageTemplate, label.ustring());
-}
// ------------------------------ StatementNode --------------------------------
-void StatementNode::setLoc(int firstLine, int lastLine, int column)
+void StatementNode::setLoc(int firstLine, int lastLine)
{
m_line = firstLine;
m_lastLine = lastLine;
- m_column = column;
}
// ------------------------------ SourceElements --------------------------------
@@ -131,1754 +73,6 @@ inline StatementNode* SourceElements::singleStatement() const
return size == 1 ? m_statements[0] : 0;
}
-inline StatementNode* SourceElements::lastStatement() const
-{
- size_t size = m_statements.size();
- return size ? m_statements[size - 1] : 0;
-}
-
-// ------------------------------ 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_value);
-}
-
-// ------------------------------ 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 = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring());
- if (!regExp->isValid())
- return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage());
- 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);
-}
-
-// ------------------------------ ArrayNode ------------------------------------
-
-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; firstPutElement; firstPutElement = firstPutElement->next()) {
- if (firstPutElement->elision())
- break;
- ++length;
- }
-
- if (!firstPutElement && !m_elision)
- return generator.emitNewArray(generator.finalDestination(dst), m_element);
-
- RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element);
-
- 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());
-}
-
-bool ArrayNode::isSimpleArray() const
-{
- if (m_elision || m_optional)
- return false;
- for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
- if (ptr->elision())
- return false;
- }
- return true;
-}
-
-ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const
-{
- 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 ----------------------------
-
-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);
-}
-
-// ------------------------------ PropertyListNode -----------------------------
-
-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) {
- RegisterID* value = generator.emitNode(p->m_node->m_assign);
-
- 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 --------------------------------
-
-RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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 --------------------------------
-
-RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RegisterID* base = generator.emitNode(m_base);
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
-}
-
-// ------------------------------ ArgumentListNode -----------------------------
-
-RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- ASSERT(m_expr);
- return generator.emitNode(dst, m_expr);
-}
-
-// ------------------------------ NewExprNode ----------------------------------
-
-RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> func = generator.emitNode(m_expr);
- return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ EvalFunctionCallNode ----------------------------------
-
-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, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ FunctionCallValueNode ----------------------------------
-
-RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ FunctionCallResolveNode ----------------------------------
-
-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, 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<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, divot(), startOffset(), endOffset());
- }
-
- 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.emitResolveWithBase(thisRegister.get(), func.get(), m_ident);
- return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ FunctionCallBracketNode ----------------------------------
-
-RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ FunctionCallDotNode ----------------------------------
-
-RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> function = generator.tempDestination(dst);
- RefPtr<RegisterID> thisRegister = generator.newTemporary();
- generator.emitNode(thisRegister.get(), m_base);
- generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
- generator.emitMethodCheck();
- generator.emitGetById(function.get(), thisRegister.get(), m_ident);
- return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-}
-
-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)
-{
- 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* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- // 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> 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 ----------------------------------
-
-static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
-{
- return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
-}
-
-static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
-{
- if (srcDst == dst)
- return generator.emitToJSNumber(dst, srcDst);
- return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
-}
-
-RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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);
- }
-
- int index = 0;
- size_t depth = 0;
- JSObject* globalObject = 0;
- if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
- RefPtr<RegisterID> 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;
- }
-
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- RefPtr<RegisterID> value = generator.newTemporary();
- RefPtr<RegisterID> 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;
-}
-
-// ------------------------------ PostfixBracketNode ----------------------------------
-
-RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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());
- 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;
-}
-
-// ------------------------------ PostfixDotNode ----------------------------------
-
-RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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);
- 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 -----------------------------------
-
-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.");
-}
-
-// ------------------------------ DeleteResolveNode -----------------------------------
-
-RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (generator.registerFor(m_ident))
- return generator.emitLoad(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 -----------------------------------
-
-RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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);
-}
-
-// ------------------------------ DeleteDotNode -----------------------------------
-
-RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RegisterID* r0 = generator.emitNode(m_base);
-
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
-}
-
-// ------------------------------ DeleteValueNode -----------------------------------
-
-RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitNode(generator.ignoredResult(), m_expr);
-
- // delete on a non-location expression ignores the value and returns true
- return generator.emitLoad(generator.finalDestination(dst), true);
-}
-
-// ------------------------------ VoidNode -------------------------------------
-
-RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (dst == generator.ignoredResult()) {
- generator.emitNode(generator.ignoredResult(), m_expr);
- return 0;
- }
- RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
- 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<RegisterID> 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 -----------------------------------
-
-RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (dst == generator.ignoredResult()) {
- generator.emitNode(generator.ignoredResult(), m_expr);
- return 0;
- }
- RefPtr<RegisterID> src = generator.emitNode(m_expr);
- 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<RegisterID> r0 = generator.emitLoad(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<RegisterID> 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<RegisterID> propDst = generator.tempDestination(dst);
- RefPtr<RegisterID> 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 ----------------------------------
-
-RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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);
- 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 ----------------------------------
-
-RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNode(m_base);
- RefPtr<RegisterID> 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 -----------------------------------
-
-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 -----------------------------------
-
-RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RegisterID* src = generator.emitNode(m_expr);
- return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
-}
-
-// ------------------------------ Binary Operation Nodes -----------------------------------
-
-// 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;
- }
-
- 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 : m_expr1);
- return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.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()));
-}
-
-RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (m_expr1->isNull() || m_expr2->isNull()) {
- RefPtr<RegisterID> src = generator.tempDestination(dst);
- 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, 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, 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, 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, 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, m_rightHasAssignments, m_expr2->isPure(generator));
- RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
-
- 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 ----------------------------
-
-RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> temp = generator.tempDestination(dst);
- RefPtr<Label> target = generator.newLabel();
-
- 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);
- generator.emitLabel(target.get());
-
- return generator.moveToDestinationIfNeeded(dst, temp.get());
-}
-
-// ------------------------------ ConditionalNode ------------------------------
-
-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);
- generator.emitJumpIfFalse(cond, beforeElse.get());
-
- generator.emitNode(newDst.get(), m_expr1);
- generator.emitJump(afterElse.get());
-
- generator.emitLabel(beforeElse.get());
- generator.emitNode(newDst.get(), m_expr2);
-
- generator.emitLabel(afterElse.get());
-
- return newDst.get();
-}
-
-// ------------------------------ ReadModifyResolveNode -----------------------------------
-
-// FIXME: should this be moved to be a method on BytecodeGenerator?
-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) {
- case OpMultEq:
- opcodeID = op_mul;
- break;
- case OpDivEq:
- 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:
- opcodeID = op_sub;
- break;
- case OpLShift:
- opcodeID = op_lshift;
- break;
- case OpRShift:
- opcodeID = op_rshift;
- break;
- case OpURShift:
- opcodeID = op_urshift;
- break;
- case OpAndEq:
- opcodeID = op_bitand;
- break;
- case OpXOrEq:
- opcodeID = op_bitxor;
- break;
- case OpOrEq:
- opcodeID = op_bitor;
- break;
- case OpModEq:
- opcodeID = op_mod;
- break;
- default:
- 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);
-}
-
-RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (generator.isLocalConstant(m_ident)) {
- 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);
- 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* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
- return generator.moveToDestinationIfNeeded(dst, result);
- }
-
- int index = 0;
- size_t depth = 0;
- 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* 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;
- }
-
- 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* 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 -----------------------------------
-
-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);
-
- RegisterID* result = generator.emitNode(local, m_right);
- return generator.moveToDestinationIfNeeded(dst, result);
- }
-
- int index = 0;
- size_t depth = 0;
- JSObject* globalObject = 0;
- if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
- if (dst == generator.ignoredResult())
- dst = 0;
- RegisterID* value = generator.emitNode(dst, m_right);
- generator.emitPutScopedVar(depth, index, value, globalObject);
- return value;
- }
-
- RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
- if (dst == generator.ignoredResult())
- dst = 0;
- RegisterID* value = generator.emitNode(dst, m_right);
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- return generator.emitPutById(base.get(), m_ident, value);
-}
-
-// ------------------------------ AssignDotNode -----------------------------------
-
-RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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);
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- generator.emitPutById(base.get(), m_ident, result);
- return generator.moveToDestinationIfNeeded(dst, result);
-}
-
-// ------------------------------ ReadModifyDotNode -----------------------------------
-
-RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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* 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);
-}
-
-// ------------------------------ AssignErrorNode -----------------------------------
-
-RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
- return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
-}
-
-// ------------------------------ AssignBracketNode -----------------------------------
-
-RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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);
-
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- generator.emitPutByVal(base.get(), property.get(), result);
- return generator.moveToDestinationIfNeeded(dst, result);
-}
-
-// ------------------------------ ReadModifyBracketNode -----------------------------------
-
-RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- 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* 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);
-
- return updatedValue;
-}
-
-// ------------------------------ CommaNode ------------------------------------
-
-RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- ASSERT(m_expressions.size() > 1);
- for (size_t i = 0; i < m_expressions.size() - 1; i++)
- generator.emitNode(generator.ignoredResult(), m_expressions[i]);
- return generator.emitNode(dst, m_expressions.last());
-}
-
-// ------------------------------ ConstDeclNode ------------------------------------
-
-RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
-{
- if (RegisterID* local = generator.constRegisterFor(m_ident)) {
- if (!m_init)
- return local;
-
- return generator.emitNode(local, m_init);
- }
-
- if (generator.codeType() != EvalCode) {
- if (m_init)
- return generator.emitNode(m_init);
- else
- return generator.emitResolve(generator.newTemporary(), m_ident);
- }
- // FIXME: While this code should only be hit in eval code, it will potentially
- // assign to the wrong base if m_ident exists in an intervening dynamic scope.
- RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
- 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)
- result = n->emitCodeSingle(generator);
-
- return result;
-}
-
-// ------------------------------ ConstStatementNode -----------------------------
-
-RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
- return generator.emitNode(m_next);
-}
-
-// ------------------------------ SourceElements -------------------------------
-
-inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- size_t size = m_statements.size();
- for (size_t i = 0; i < size; ++i)
- generator.emitNode(dst, m_statements[i]);
-}
-
-// ------------------------------ BlockNode ------------------------------------
-
-inline StatementNode* BlockNode::lastStatement() const
-{
- return m_statements ? m_statements->lastStatement() : 0;
-}
-
-RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (m_statements)
- m_statements->emitBytecode(generator, dst);
- return 0;
-}
-
-// ------------------------------ EmptyStatementNode ---------------------------
-
-RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
- return dst;
-}
-
-// ------------------------------ DebuggerStatementNode ---------------------------
-
-RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine(), column());
- return dst;
-}
-
-// ------------------------------ ExprStatementNode ----------------------------
-
-RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- ASSERT(m_expr);
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
- return generator.emitNode(dst, m_expr);
-}
-
-// ------------------------------ VarStatementNode ----------------------------
-
-RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
- ASSERT(m_expr);
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
- return generator.emitNode(m_expr);
-}
-
-// ------------------------------ IfNode ---------------------------------------
-
-RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- RefPtr<Label> afterThen = generator.newLabel();
-
- RegisterID* cond = generator.emitNode(m_condition);
- generator.emitJumpIfFalse(cond, afterThen.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.
- return 0;
-}
-
-// ------------------------------ IfElseNode ---------------------------------------
-
-RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- RefPtr<Label> beforeElse = generator.newLabel();
- RefPtr<Label> afterElse = generator.newLabel();
-
- RegisterID* cond = generator.emitNode(m_condition);
- generator.emitJumpIfFalse(cond, beforeElse.get());
-
- generator.emitNode(dst, m_ifBlock);
- generator.emitJump(afterElse.get());
-
- generator.emitLabel(beforeElse.get());
-
- generator.emitNode(dst, m_elseBlock);
-
- generator.emitLabel(afterElse.get());
-
- // FIXME: This should return the last statement executed so that it can be returned as a Completion.
- return 0;
-}
-
-// ------------------------------ DoWhileNode ----------------------------------
-
-RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
- RefPtr<Label> topOfLoop = generator.newLabel();
- generator.emitLabel(topOfLoop.get());
-
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
-
- generator.emitLabel(scope->continueTarget());
-#ifndef QT_BUILD_SCRIPT_LIB
- generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), column());
-#endif
- RegisterID* cond = generator.emitNode(m_expr);
- generator.emitJumpIfTrue(cond, topOfLoop.get());
-
- generator.emitLabel(scope->breakTarget());
- return result.get();
-}
-
-// ------------------------------ WhileNode ------------------------------------
-
-RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-#ifdef QT_BUILD_SCRIPT_LIB
- generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), column());
-#endif
- generator.emitJump(scope->continueTarget());
-
- RefPtr<Label> topOfLoop = generator.newLabel();
- generator.emitLabel(topOfLoop.get());
-
- generator.emitNode(dst, m_statement);
-
- generator.emitLabel(scope->continueTarget());
-#ifndef QT_BUILD_SCRIPT_LIB
- generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), column());
-#endif
- RegisterID* cond = generator.emitNode(m_expr);
- generator.emitJumpIfTrue(cond, topOfLoop.get());
-
- generator.emitLabel(scope->breakTarget());
-
- // FIXME: This should return the last statement executed so that it can be returned as a Completion
- return 0;
-}
-
-// ------------------------------ ForNode --------------------------------------
-
-RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- if (m_expr1)
- generator.emitNode(generator.ignoredResult(), m_expr1);
-
- RefPtr<Label> condition = generator.newLabel();
- generator.emitJump(condition.get());
-
- RefPtr<Label> topOfLoop = generator.newLabel();
- generator.emitLabel(topOfLoop.get());
-
- RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
-
- generator.emitLabel(scope->continueTarget());
-#ifndef QT_BUILD_SCRIPT_LIB
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-#endif
- if (m_expr3)
- generator.emitNode(generator.ignoredResult(), m_expr3);
-
- generator.emitLabel(condition.get());
- if (m_expr2) {
- RegisterID* cond = generator.emitNode(m_expr2);
- generator.emitJumpIfTrue(cond, topOfLoop.get());
- } else
- generator.emitJump(topOfLoop.get());
-
- generator.emitLabel(scope->breakTarget());
- return result.get();
-}
-
-// ------------------------------ ForInNode ------------------------------------
-
-RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
- if (!m_lexpr->isLocation())
- return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
-
- RefPtr<Label> continueTarget = generator.newLabel();
-
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- if (m_init)
- generator.emitNode(generator.ignoredResult(), m_init);
- RegisterID* forInBase = generator.emitNode(m_expr);
- RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
- generator.emitJump(scope->continueTarget());
-
- RefPtr<Label> loopStart = generator.newLabel();
- generator.emitLabel(loopStart.get());
-
- RegisterID* propertyName;
- if (m_lexpr->isResolveNode()) {
- const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
- propertyName = generator.registerFor(ident);
- if (!propertyName) {
- propertyName = generator.newTemporary();
- RefPtr<RegisterID> protect = propertyName;
- RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
-
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- generator.emitPutById(base, ident, propertyName);
- }
- } else if (m_lexpr->isDotAccessorNode()) {
- DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
- const Identifier& ident = assignNode->identifier();
- propertyName = generator.newTemporary();
- RefPtr<RegisterID> protect = propertyName;
- RegisterID* base = generator.emitNode(assignNode->base());
-
- generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
- generator.emitPutById(base, ident, propertyName);
- } else {
- ASSERT(m_lexpr->isBracketAccessorNode());
- BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
- propertyName = generator.newTemporary();
- RefPtr<RegisterID> protect = propertyName;
- RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
- RegisterID* subscript = generator.emitNode(assignNode->subscript());
-
- generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
- generator.emitPutByVal(base.get(), subscript, propertyName);
- }
-
- generator.emitNode(dst, m_statement);
-
- generator.emitLabel(scope->continueTarget());
- generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
-#ifndef QT_BUILD_SCRIPT_LIB
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-#endif
- generator.emitLabel(scope->breakTarget());
- return dst;
-}
-
-// ------------------------------ ContinueNode ---------------------------------
-
-// ECMA 12.7
-RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- LabelScope* scope = generator.continueTarget(m_ident);
-
- if (!scope)
- return m_ident.isEmpty()
- ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
- : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
-
- generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
- return dst;
-}
-
-// ------------------------------ BreakNode ------------------------------------
-
-// ECMA 12.8
-RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- LabelScope* scope = generator.breakTarget(m_ident);
-
- if (!scope)
- return m_ident.isEmpty()
- ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
- : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
-
- generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
- return dst;
-}
-
-// ------------------------------ ReturnNode -----------------------------------
-
-RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
- 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) : 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());
- }
- generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine(), column());
- return generator.emitReturn(r0);
-}
-
-// ------------------------------ WithNode -------------------------------------
-
-RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- RefPtr<RegisterID> scope = generator.newTemporary();
- 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);
- generator.emitPopScope();
- return result;
-}
-
-// ------------------------------ CaseClauseNode --------------------------------
-
-inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (m_statements)
- m_statements->emitBytecode(generator, dst);
-}
-
-// ------------------------------ CaseBlockNode --------------------------------
-
-enum SwitchKind {
- SwitchUnset = 0,
- SwitchNumber = 1,
- SwitchString = 2,
- SwitchNeither = 3
-};
-
-static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
-{
- for (; list; list = list->getNext()) {
- ExpressionNode* clauseExpression = list->getClause()->expr();
- literalVector.append(clauseExpression);
- if (clauseExpression->isNumber()) {
- double value = static_cast<NumberNode*>(clauseExpression)->value();
- int32_t intVal = static_cast<int32_t>(value);
- if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
- typeForTable = SwitchNeither;
- break;
- }
- if (intVal < min_num)
- min_num = intVal;
- if (intVal > max_num)
- max_num = intVal;
- typeForTable = SwitchNumber;
- continue;
- }
- if (clauseExpression->isString()) {
- if (typeForTable & ~SwitchString) {
- typeForTable = SwitchNeither;
- break;
- }
- const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
- if (singleCharacterSwitch &= value.size() == 1) {
- int32_t intVal = value.rep()->data()[0];
- if (intVal < min_num)
- min_num = intVal;
- if (intVal > max_num)
- max_num = intVal;
- }
- typeForTable = SwitchString;
- continue;
- }
- typeForTable = SwitchNeither;
- break;
- }
-}
-
-SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
-{
- SwitchKind typeForTable = SwitchUnset;
- bool singleCharacterSwitch = true;
-
- 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;
-
- if (typeForTable == SwitchNumber) {
- int32_t range = max_num - min_num;
- if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
- return SwitchInfo::SwitchImmediate;
- return SwitchInfo::SwitchNone;
- }
-
- ASSERT(typeForTable == SwitchString);
-
- if (singleCharacterSwitch) {
- int32_t range = max_num - min_num;
- if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
- return SwitchInfo::SwitchCharacter;
- }
-
- return SwitchInfo::SwitchString;
-}
-
-RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
-{
- RefPtr<Label> defaultLabel;
- Vector<RefPtr<Label>, 8> labelVector;
- Vector<ExpressionNode*, 8> literalVector;
- int32_t min_num = std::numeric_limits<int32_t>::max();
- int32_t max_num = std::numeric_limits<int32_t>::min();
- SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
-
- if (switchType != SwitchInfo::SwitchNone) {
- // Prepare the various labels
- for (uint32_t i = 0; i < literalVector.size(); i++)
- labelVector.append(generator.newLabel());
- defaultLabel = generator.newLabel();
- generator.beginSwitch(switchExpression, switchType);
- } else {
- // Setup jumps
- 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());
- labelVector.append(generator.newLabel());
- generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
- }
-
- 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());
- labelVector.append(generator.newLabel());
- generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
- }
- defaultLabel = generator.newLabel();
- generator.emitJump(defaultLabel.get());
- }
-
- RegisterID* result = 0;
-
- size_t i = 0;
- for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
- generator.emitLabel(labelVector[i++].get());
- list->getClause()->emitBytecode(generator, dst);
- }
-
- if (m_defaultClause) {
- generator.emitLabel(defaultLabel.get());
- m_defaultClause->emitBytecode(generator, dst);
- }
-
- for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
- generator.emitLabel(labelVector[i++].get());
- list->getClause()->emitBytecode(generator, dst);
- }
- if (!m_defaultClause)
- generator.emitLabel(defaultLabel.get());
-
- ASSERT(i == labelVector.size());
- if (switchType != SwitchInfo::SwitchNone) {
- ASSERT(labelVector.size() == literalVector.size());
- generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
- }
- return result;
-}
-
-// ------------------------------ SwitchNode -----------------------------------
-
-RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
-
- RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
- RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
-
- generator.emitLabel(scope->breakTarget());
- return r1;
-}
-
-// ------------------------------ LabelNode ------------------------------------
-
-RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- 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);
-
- generator.emitLabel(scope->breakTarget());
- return r0;
-}
-
-// ------------------------------ ThrowNode ------------------------------------
-
-RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-
- if (dst == generator.ignoredResult())
- dst = 0;
- RefPtr<RegisterID> expr = generator.emitNode(m_expr);
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- generator.emitThrow(expr.get());
- return 0;
-}
-
-// ------------------------------ TryNode --------------------------------------
-
-RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- // NOTE: The catch and finally blocks must be labeled explicitly, so the
- // optimizer knows they may be jumped to from anywhere.
-
-#ifndef QT_BUILD_SCRIPT_LIB
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
-#endif
-
- RefPtr<Label> tryStartLabel = generator.newLabel();
- RefPtr<Label> finallyStart;
- RefPtr<RegisterID> finallyReturnAddr;
- if (m_finallyBlock) {
- finallyStart = generator.newLabel();
- finallyReturnAddr = generator.newTemporary();
- generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
- }
-
- generator.emitLabel(tryStartLabel.get());
- generator.emitNode(dst, m_tryBlock);
-
- if (m_catchBlock) {
- RefPtr<Label> catchEndLabel = generator.newLabel();
-
- // Normal path: jump over the catch block.
- generator.emitJump(catchEndLabel.get());
-
- // Uncaught exception path: the catch block.
- RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
- RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
- if (m_catchHasEval) {
- RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
- generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
- generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
- generator.emitPushScope(exceptionRegister.get());
- } else
- generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
- generator.emitNode(dst, m_catchBlock);
- generator.emitPopScope();
- generator.emitLabel(catchEndLabel.get());
- }
-
- if (m_finallyBlock) {
- generator.popFinallyContext();
- // there may be important registers live at the time we jump
- // to a finally block (such as for a return or throw) so we
- // ref the highest register ever used as a conservative
- // approach to not clobbering anything important
- RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
- RefPtr<Label> finallyEndLabel = generator.newLabel();
-
- // Normal path: invoke the finally block, then jump over it.
- generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
- generator.emitJump(finallyEndLabel.get());
-
- // Uncaught exception path: invoke the finally block, then re-throw the exception.
- RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
- RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
- generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
- generator.emitThrow(tempExceptionRegister.get());
-
- // The finally block.
- generator.emitLabel(finallyStart.get());
- generator.emitNode(dst, m_finallyBlock);
- generator.emitSubroutineReturn(finallyReturnAddr.get());
-
- generator.emitLabel(finallyEndLabel.get());
- }
-
- return dst;
-}
-
// -----------------------------ScopeNodeData ---------------------------
ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, int numConstants)
@@ -1910,12 +104,6 @@ ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceE
{
}
-inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (m_data->m_statements)
- m_data->m_statements->emitBytecode(generator, dst);
-}
-
StatementNode* ScopeNode::singleStatement() const
{
return m_data->m_statements ? m_data->m_statements->singleStatement() : 0;
@@ -1939,19 +127,6 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElem
return node.release();
}
-RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
- generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine(), column());
-
- RefPtr<RegisterID> dstRegister = generator.newTemporary();
- generator.emitLoad(dstRegister.get(), jsUndefined());
- emitStatementsBytecode(generator, dstRegister.get());
-
- generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine(), column());
- generator.emitEnd(dstRegister.get());
- return 0;
-}
-
// ------------------------------ EvalNode -----------------------------
inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
@@ -1970,19 +145,6 @@ PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements*
return node.release();
}
-RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
- generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine(), column());
-
- RefPtr<RegisterID> dstRegister = generator.newTemporary();
- generator.emitLoad(dstRegister.get(), jsUndefined());
- emitStatementsBytecode(generator, dstRegister.get());
-
- generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine(), column());
- generator.emitEnd(dstRegister.get());
- return 0;
-}
-
// ------------------------------ FunctionBodyNode -----------------------------
FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
@@ -2001,10 +163,6 @@ inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElemen
{
}
-FunctionBodyNode::~FunctionBodyNode()
-{
-}
-
void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident)
{
setSource(source);
@@ -2034,37 +192,4 @@ PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData,
return node.release();
}
-RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
- generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine(), column());
- emitStatementsBytecode(generator, generator.ignoredResult());
- StatementNode* singleStatement = this->singleStatement();
- if (singleStatement && singleStatement->isBlock()) {
- StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
- if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
- return 0;
- }
-
- RegisterID* r0 = generator.emitLoad(0, jsUndefined());
- generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine(), column());
- generator.emitReturn(r0);
- return 0;
-}
-
-// ------------------------------ FuncDeclNode ---------------------------------
-
-RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (dst == generator.ignoredResult())
- dst = 0;
- return dst;
-}
-
-// ------------------------------ FuncExprNode ---------------------------------
-
-RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
-}
-
} // namespace JSC
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.h
index 2f8d850..c216ea8 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.h
@@ -40,6 +40,7 @@ namespace JSC {
class ArgumentListNode;
class BytecodeGenerator;
class FunctionBodyNode;
+ class Label;
class PropertyListNode;
class ReadModifyResolveNode;
class RegisterID;
@@ -151,6 +152,9 @@ namespace JSC {
virtual bool isCommaNode() const { return false; }
virtual bool isSimpleArray() const { return false; }
virtual bool isAdd() const { return false; }
+ virtual bool hasConditionContextCodegen() const { return false; }
+
+ virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); }
virtual ExpressionNode* stripUnaryPlus() { return this; }
@@ -165,10 +169,9 @@ namespace JSC {
StatementNode(JSGlobalData*);
public:
- void setLoc(int firstLine, int lastLine, int column);
+ void setLoc(int firstLine, int lastLine);
int firstLine() const { return lineNo(); }
int lastLine() const { return m_lastLine; }
- int column() const { return m_column; }
virtual bool isEmptyStatement() const { return false; }
virtual bool isReturnNode() const { return false; }
@@ -178,7 +181,6 @@ namespace JSC {
private:
int m_lastLine;
- int m_column;
};
class NullNode : public ExpressionNode {
@@ -759,6 +761,7 @@ namespace JSC {
protected:
ExpressionNode* expr() { return m_expr; }
+ const ExpressionNode* expr() const { return m_expr; }
private:
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -790,6 +793,9 @@ namespace JSC {
class LogicalNotNode : public UnaryOpNode {
public:
LogicalNotNode(JSGlobalData*, ExpressionNode*);
+ private:
+ void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
+ virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); }
};
class BinaryOpNode : public ExpressionNode {
@@ -954,6 +960,8 @@ namespace JSC {
private:
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
+ virtual bool hasConditionContextCodegen() const { return true; }
ExpressionNode* m_expr1;
ExpressionNode* m_expr2;
@@ -1460,8 +1468,6 @@ namespace JSC {
static FunctionBodyNode* create(JSGlobalData*);
static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
- virtual ~FunctionBodyNode();
-
FunctionParameters* parameters() const { return m_parameters.get(); }
size_t parameterCount() const { return m_parameters->size(); }
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Parser.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Parser.h
index 7f20480..894f709 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Parser.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Parser.h
@@ -83,8 +83,7 @@ namespace JSC {
source,
m_features,
m_numConstants);
- int column = m_source->startOffset(); //is it good way to find column number?
- result->setLoc(m_source->firstLine(), m_lastLine, column);
+ result->setLoc(m_source->firstLine(), m_lastLine);
}
m_arena.reset();
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/ParserArena.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/ParserArena.h
index 2fd4fc1..eef8e93 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/ParserArena.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/ParserArena.h
@@ -34,7 +34,7 @@ namespace JSC {
class ParserArenaDeletable;
class ParserArenaRefCounted;
- class IdentifierArena {
+ class IdentifierArena : public FastAllocBase {
public:
ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const UChar* characters, size_t length);
const Identifier& makeNumericIdentifier(JSGlobalData*, double number);
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/SourceCode.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/SourceCode.h
index 305b804..bef8e78 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/SourceCode.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/SourceCode.h
@@ -37,7 +37,8 @@ namespace JSC {
class SourceCode {
public:
SourceCode()
- : m_startChar(0)
+ : m_provider(0)
+ , m_startChar(0)
, m_endChar(0)
, m_firstLine(0)
{