summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/kjs
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:41 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:41 -0800
commit648161bb0edfc3d43db63caed5cc5213bc6cb78f (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /JavaScriptCore/kjs
parenta65af38181ac7d34544586bdb5cd004de93897ad (diff)
downloadexternal_webkit-648161bb0edfc3d43db63caed5cc5213bc6cb78f.zip
external_webkit-648161bb0edfc3d43db63caed5cc5213bc6cb78f.tar.gz
external_webkit-648161bb0edfc3d43db63caed5cc5213bc6cb78f.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'JavaScriptCore/kjs')
-rw-r--r--JavaScriptCore/kjs/LabelScope.h92
-rw-r--r--JavaScriptCore/kjs/NodeInfo.h63
-rw-r--r--JavaScriptCore/kjs/Parser.cpp77
-rw-r--r--JavaScriptCore/kjs/Parser.h97
-rw-r--r--JavaScriptCore/kjs/ResultType.h169
-rw-r--r--JavaScriptCore/kjs/Shell.cpp501
-rw-r--r--JavaScriptCore/kjs/SourceCode.h90
-rw-r--r--JavaScriptCore/kjs/SourceProvider.h79
-rw-r--r--JavaScriptCore/kjs/TypeInfo.h63
-rw-r--r--JavaScriptCore/kjs/collector.cpp1094
-rw-r--r--JavaScriptCore/kjs/collector.h279
-rw-r--r--JavaScriptCore/kjs/completion.h56
-rw-r--r--JavaScriptCore/kjs/config.h71
-rwxr-xr-xJavaScriptCore/kjs/create_hash_table242
-rw-r--r--JavaScriptCore/kjs/dtoa.cpp2438
-rw-r--r--JavaScriptCore/kjs/dtoa.h38
-rw-r--r--JavaScriptCore/kjs/grammar.y1511
-rw-r--r--JavaScriptCore/kjs/identifier.cpp263
-rw-r--r--JavaScriptCore/kjs/identifier.h140
-rw-r--r--JavaScriptCore/kjs/interpreter.cpp78
-rw-r--r--JavaScriptCore/kjs/interpreter.h68
-rw-r--r--JavaScriptCore/kjs/jsc.pro35
-rw-r--r--JavaScriptCore/kjs/keywords.table72
-rw-r--r--JavaScriptCore/kjs/lexer.cpp920
-rw-r--r--JavaScriptCore/kjs/lexer.h164
-rw-r--r--JavaScriptCore/kjs/lookup.cpp68
-rw-r--r--JavaScriptCore/kjs/lookup.h238
-rw-r--r--JavaScriptCore/kjs/nodes.cpp1882
-rw-r--r--JavaScriptCore/kjs/nodes.h2493
-rw-r--r--JavaScriptCore/kjs/nodes2string.cpp936
-rw-r--r--JavaScriptCore/kjs/operations.cpp75
-rw-r--r--JavaScriptCore/kjs/operations.h137
-rw-r--r--JavaScriptCore/kjs/protect.h154
-rw-r--r--JavaScriptCore/kjs/regexp.cpp182
-rw-r--r--JavaScriptCore/kjs/regexp.h76
-rw-r--r--JavaScriptCore/kjs/ustring.cpp1638
-rw-r--r--JavaScriptCore/kjs/ustring.h385
37 files changed, 0 insertions, 16964 deletions
diff --git a/JavaScriptCore/kjs/LabelScope.h b/JavaScriptCore/kjs/LabelScope.h
deleted file mode 100644
index 8c30be5..0000000
--- a/JavaScriptCore/kjs/LabelScope.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LabelScope_h
-#define LabelScope_h
-
-#include <wtf/PassRefPtr.h>
-#include "LabelID.h"
-
-namespace JSC {
-
- class Identifier;
-
- class LabelScope {
- public:
- enum Type { Loop, Switch, NamedLabel };
-
- LabelScope(Type type, const Identifier* name, int scopeDepth, PassRefPtr<LabelID> breakTarget, PassRefPtr<LabelID> continueTarget)
- : m_refCount(0)
- , m_type(type)
- , m_name(name)
- , m_scopeDepth(scopeDepth)
- , m_breakTarget(breakTarget)
- , m_continueTarget(continueTarget)
- {
- }
-
- // It doesn't really make sense to copy a LabelScope, but we need this copy
- // constructor to support moving LabelScopes in a Vector.
-
- LabelScope(const LabelScope& other)
- : m_refCount(other.m_refCount)
- , m_type(other.m_type)
- , m_name(other.m_name)
- , m_scopeDepth(other.m_scopeDepth)
- , m_breakTarget(other.m_breakTarget)
- , m_continueTarget(other.m_continueTarget)
- {
- }
-
- void ref() { ++m_refCount; }
- void deref()
- {
- --m_refCount;
- ASSERT(m_refCount >= 0);
- }
- int refCount() const { return m_refCount; }
-
- LabelID* breakTarget() const { return m_breakTarget.get(); }
- LabelID* continueTarget() const { return m_continueTarget.get(); }
-
- Type type() const { return m_type; }
- const Identifier* name() const { return m_name; }
- int scopeDepth() const { return m_scopeDepth; }
-
- private:
- int m_refCount;
- Type m_type;
- const Identifier* m_name;
- int m_scopeDepth;
- RefPtr<LabelID> m_breakTarget;
- RefPtr<LabelID> m_continueTarget;
- };
-
-} // namespace JSC
-
-#endif // LabelScope_h
diff --git a/JavaScriptCore/kjs/NodeInfo.h b/JavaScriptCore/kjs/NodeInfo.h
deleted file mode 100644
index 2d11dc2..0000000
--- a/JavaScriptCore/kjs/NodeInfo.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef NodeInfo_h
-#define NodeInfo_h
-
-#include "nodes.h"
-#include "Parser.h"
-
-namespace JSC {
-
- template <typename T> struct NodeInfo {
- T m_node;
- CodeFeatures m_features;
- int m_numConstants;
- };
-
- typedef NodeInfo<FuncDeclNode*> FuncDeclNodeInfo;
- typedef NodeInfo<FuncExprNode*> FuncExprNodeInfo;
- typedef NodeInfo<ExpressionNode*> ExpressionNodeInfo;
- typedef NodeInfo<ArgumentsNode*> ArgumentsNodeInfo;
- typedef NodeInfo<ConstDeclNode*> ConstDeclNodeInfo;
- typedef NodeInfo<PropertyNode*> PropertyNodeInfo;
- typedef NodeInfo<PropertyList> PropertyListInfo;
- typedef NodeInfo<ElementList> ElementListInfo;
- typedef NodeInfo<ArgumentList> ArgumentListInfo;
-
- template <typename T> struct NodeDeclarationInfo {
- T m_node;
- ParserRefCountedData<DeclarationStacks::VarStack>* m_varDeclarations;
- ParserRefCountedData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
- CodeFeatures m_features;
- int m_numConstants;
- };
-
- typedef NodeDeclarationInfo<StatementNode*> StatementNodeInfo;
- typedef NodeDeclarationInfo<CaseBlockNode*> CaseBlockNodeInfo;
- typedef NodeDeclarationInfo<CaseClauseNode*> CaseClauseNodeInfo;
- typedef NodeDeclarationInfo<SourceElements*> SourceElementsInfo;
- typedef NodeDeclarationInfo<ClauseList> ClauseListInfo;
- typedef NodeDeclarationInfo<ExpressionNode*> VarDeclListInfo;
- typedef NodeDeclarationInfo<ConstDeclList> ConstDeclListInfo;
- typedef NodeDeclarationInfo<ParameterList> ParameterListInfo;
-
-} // namespace JSC
-
-#endif // NodeInfo_h
diff --git a/JavaScriptCore/kjs/Parser.cpp b/JavaScriptCore/kjs/Parser.cpp
deleted file mode 100644
index 26773e8..0000000
--- a/JavaScriptCore/kjs/Parser.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "Parser.h"
-
-#include "Debugger.h"
-#include "lexer.h"
-#include <wtf/HashSet.h>
-#include <wtf/Vector.h>
-
-extern int kjsyyparse(void*);
-
-namespace JSC {
-
-void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
-{
- ASSERT(!m_sourceElements);
-
- int defaultErrLine;
- UString defaultErrMsg;
-
- if (!errLine)
- errLine = &defaultErrLine;
- if (!errMsg)
- errMsg = &defaultErrMsg;
-
- *errLine = -1;
- *errMsg = 0;
-
- Lexer& lexer = *globalData->lexer;
- lexer.setCode(*m_source);
-
- int parseError = kjsyyparse(globalData);
- bool lexError = lexer.sawError();
- lexer.clear();
-
- ParserRefCounted::deleteNewObjects(globalData);
-
- if (parseError || lexError) {
- *errLine = lexer.lineNo();
- *errMsg = "Parse error";
- m_sourceElements.clear();
- }
-}
-
-void Parser::didFinishParsing(SourceElements* sourceElements, ParserRefCountedData<DeclarationStacks::VarStack>* varStack,
- ParserRefCountedData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants)
-{
- m_sourceElements = sourceElements;
- m_varDeclarations = varStack;
- m_funcDeclarations = funcStack;
- m_features = features;
- m_lastLine = lastLine;
- m_numConstants = numConstants;
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/Parser.h b/JavaScriptCore/kjs/Parser.h
deleted file mode 100644
index c2f55d7..0000000
--- a/JavaScriptCore/kjs/Parser.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef Parser_h
-#define Parser_h
-
-#include "SourceProvider.h"
-#include "Debugger.h"
-#include "nodes.h"
-#include <wtf/Forward.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/RefPtr.h>
-
-namespace JSC {
-
- class FunctionBodyNode;
- class ProgramNode;
- class UString;
-
- template <typename T>
- struct ParserRefCountedData : ParserRefCounted {
- ParserRefCountedData(JSGlobalData* globalData)
- : ParserRefCounted(globalData)
- {
- }
-
- T data;
- };
-
- class Parser : Noncopyable {
- public:
- template <class ParsedNode> PassRefPtr<ParsedNode> parse(ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
-
- void didFinishParsing(SourceElements*, ParserRefCountedData<DeclarationStacks::VarStack>*,
- ParserRefCountedData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
-
- private:
- void parse(JSGlobalData*, int* errLine, UString* errMsg);
-
- const SourceCode* m_source;
- RefPtr<SourceElements> m_sourceElements;
- RefPtr<ParserRefCountedData<DeclarationStacks::VarStack> > m_varDeclarations;
- RefPtr<ParserRefCountedData<DeclarationStacks::FunctionStack> > m_funcDeclarations;
- CodeFeatures m_features;
- int m_lastLine;
- int m_numConstants;
- };
-
- template <class ParsedNode> PassRefPtr<ParsedNode> Parser::parse(ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
- {
- m_source = &source;
- parse(&exec->globalData(), errLine, errMsg);
- RefPtr<ParsedNode> result;
- if (m_sourceElements) {
- result = ParsedNode::create(&exec->globalData(),
- m_sourceElements.get(),
- m_varDeclarations ? &m_varDeclarations->data : 0,
- m_funcDeclarations ? &m_funcDeclarations->data : 0,
- *m_source,
- m_features,
- m_numConstants);
- result->setLoc(m_source->firstLine(), m_lastLine);
- }
-
- m_source = 0;
- m_sourceElements = 0;
- m_varDeclarations = 0;
- m_funcDeclarations = 0;
-
- if (debugger)
- debugger->sourceParsed(exec, source, *errLine, *errMsg);
- return result.release();
- }
-
-} // namespace JSC
-
-#endif // Parser_h
diff --git a/JavaScriptCore/kjs/ResultType.h b/JavaScriptCore/kjs/ResultType.h
deleted file mode 100644
index f838ce0..0000000
--- a/JavaScriptCore/kjs/ResultType.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ResultType_h
-#define ResultType_h
-
-namespace JSC {
-
- struct ResultType {
- friend struct OperandTypes;
-
- typedef char Type;
- static const Type TypeReusable = 1;
-
- static const Type TypeMaybeNumber = 2;
- static const Type TypeMaybeString = 4;
- static const Type TypeMaybeNull = 8;
- static const Type TypeMaybeBool = 16;
- static const Type TypeMaybeOther = 32;
-
- static const Type TypeReusableNumber = 3;
- static const Type TypeStringOrReusableNumber = 4;
-
- explicit ResultType(Type type)
- : m_type(type)
- {
- }
-
- bool isReusable()
- {
- return (m_type & TypeReusable);
- }
-
- bool isReusableNumber()
- {
- return isReusable() && definitelyIsNumber();
- }
-
- bool definitelyIsNumber()
- {
- return ((m_type & ~TypeReusable) == TypeMaybeNumber);
- }
-
- bool isNotNumber()
- {
- return ((m_type & TypeMaybeNumber) == 0);
- }
-
- bool mightBeNumber()
- {
- return !isNotNumber();
- }
-
- int toInt()
- {
- return static_cast<int>(m_type);
- }
-
- static ResultType nullType()
- {
- return ResultType(TypeMaybeNull);
- }
-
- static ResultType boolean()
- {
- return ResultType(TypeMaybeBool);
- }
-
- static ResultType constNumber()
- {
- return ResultType(TypeMaybeNumber);
- }
-
- static ResultType reusableNumber()
- {
- return ResultType(TypeReusable | TypeMaybeNumber);
- }
-
- static ResultType reusableNumberOrString()
- {
- return ResultType(TypeReusable | TypeMaybeNumber | TypeMaybeString);
- }
-
- static ResultType string()
- {
- return ResultType(TypeMaybeString);
- }
-
- static ResultType unknown()
- {
- return ResultType(TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther);
- }
-
- static ResultType forAdd(ResultType op1, ResultType op2)
- {
- if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
- return reusableNumber();
- if (op1.isNotNumber() || op2.isNotNumber())
- return string();
- return reusableNumberOrString();
- }
-
- private:
- Type m_type;
- };
-
- struct OperandTypes
- {
- OperandTypes(ResultType first = ResultType::unknown(), ResultType second = ResultType::unknown())
- {
- m_u.rds.first = first.m_type;
- m_u.rds.second = second.m_type;
- }
-
- union {
- struct {
- ResultType::Type first;
- ResultType::Type second;
- } rds;
- int i;
- } m_u;
-
- ResultType first()
- {
- return ResultType(m_u.rds.first);
- }
-
- ResultType second()
- {
- return ResultType(m_u.rds.second);
- }
-
- int toInt()
- {
- return m_u.i;
- }
- static OperandTypes fromInt(int value)
- {
- OperandTypes types;
- types.m_u.i = value;
- return types;
- }
- };
-
-} // namespace JSC
-
-#endif // ResultType_h
diff --git a/JavaScriptCore/kjs/Shell.cpp b/JavaScriptCore/kjs/Shell.cpp
deleted file mode 100644
index f35679e..0000000
--- a/JavaScriptCore/kjs/Shell.cpp
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-
-#include "CodeGenerator.h"
-#include "InitializeThreading.h"
-#include "JSArray.h"
-#include "JSLock.h"
-#include "PrototypeFunction.h"
-#include "SamplingTool.h"
-#include "completion.h"
-#include "interpreter.h"
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
-#if !PLATFORM(WIN_OS)
-#include <unistd.h>
-#endif
-
-#if HAVE(READLINE)
-#include <readline/history.h>
-#include <readline/readline.h>
-#endif
-
-#if HAVE(SYS_TIME_H)
-#include <sys/time.h>
-#endif
-
-#if PLATFORM(UNIX)
-#include <signal.h>
-#endif
-
-#if COMPILER(MSVC)
-#include <crtdbg.h>
-#include <windows.h>
-#endif
-
-#if PLATFORM(QT)
-#include <QCoreApplication>
-#include <QDateTime>
-#endif
-
-using namespace JSC;
-using namespace WTF;
-
-static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
-
-static JSValue* functionPrint(ExecState*, JSObject*, JSValue*, const ArgList&);
-static JSValue* functionDebug(ExecState*, JSObject*, JSValue*, const ArgList&);
-static JSValue* functionGC(ExecState*, JSObject*, JSValue*, const ArgList&);
-static JSValue* functionVersion(ExecState*, JSObject*, JSValue*, const ArgList&);
-static JSValue* functionRun(ExecState*, JSObject*, JSValue*, const ArgList&);
-static JSValue* functionLoad(ExecState*, JSObject*, JSValue*, const ArgList&);
-static JSValue* functionReadline(ExecState*, JSObject*, JSValue*, const ArgList&);
-static JSValue* functionQuit(ExecState*, JSObject*, JSValue*, const ArgList&);
-
-struct Options {
- Options()
- : interactive(false)
- , prettyPrint(false)
- , dump(false)
- {
- }
-
- bool interactive;
- bool prettyPrint;
- bool dump;
- Vector<UString> fileNames;
- Vector<UString> arguments;
-};
-
-static const char interactivePrompt[] = "> ";
-static const UString interpreterName("Interpreter");
-
-class StopWatch {
-public:
- void start();
- void stop();
- long getElapsedMS(); // call stop() first
-
-private:
-#if PLATFORM(QT)
- uint m_startTime;
- uint m_stopTime;
-#elif PLATFORM(WIN_OS)
- DWORD m_startTime;
- DWORD m_stopTime;
-#else
- // Windows does not have timeval, disabling this class for now (bug 7399)
- timeval m_startTime;
- timeval m_stopTime;
-#endif
-};
-
-void StopWatch::start()
-{
-#if PLATFORM(QT)
- QDateTime t = QDateTime::currentDateTime();
- m_startTime = t.toTime_t() * 1000 + t.time().msec();
-#elif PLATFORM(WIN_OS)
- m_startTime = timeGetTime();
-#else
- gettimeofday(&m_startTime, 0);
-#endif
-}
-
-void StopWatch::stop()
-{
-#if PLATFORM(QT)
- QDateTime t = QDateTime::currentDateTime();
- m_stopTime = t.toTime_t() * 1000 + t.time().msec();
-#elif PLATFORM(WIN_OS)
- m_stopTime = timeGetTime();
-#else
- gettimeofday(&m_stopTime, 0);
-#endif
-}
-
-long StopWatch::getElapsedMS()
-{
-#if PLATFORM(WIN_OS) || PLATFORM(QT)
- return m_stopTime - m_startTime;
-#else
- timeval elapsedTime;
- timersub(&m_stopTime, &m_startTime, &elapsedTime);
-
- return elapsedTime.tv_sec * 1000 + lroundf(elapsedTime.tv_usec / 1000.0f);
-#endif
-}
-
-class GlobalObject : public JSGlobalObject {
-public:
- GlobalObject(const Vector<UString>& arguments);
- virtual UString className() const { return "global"; }
-};
-COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
-ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
-
-GlobalObject::GlobalObject(const Vector<UString>& arguments)
- : JSGlobalObject()
-{
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
- putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
-
- JSObject* array = constructEmptyArray(globalExec());
- for (size_t i = 0; i < arguments.size(); ++i)
- array->put(globalExec(), i, jsString(globalExec(), arguments[i]));
- putDirect(Identifier(globalExec(), "arguments"), array);
-}
-
-JSValue* functionPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
-{
- for (unsigned i = 0; i < args.size(); ++i) {
- if (i != 0)
- putchar(' ');
-
- printf("%s", args.at(exec, i)->toString(exec).UTF8String().c_str());
- }
-
- putchar('\n');
- fflush(stdout);
- return jsUndefined();
-}
-
-JSValue* functionDebug(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
-{
- fprintf(stderr, "--> %s\n", args.at(exec, 0)->toString(exec).UTF8String().c_str());
- return jsUndefined();
-}
-
-JSValue* functionGC(ExecState* exec, JSObject*, JSValue*, const ArgList&)
-{
- JSLock lock(false);
- exec->heap()->collect();
- return jsUndefined();
-}
-
-JSValue* functionVersion(ExecState*, JSObject*, JSValue*, const ArgList&)
-{
- // We need this function for compatibility with the Mozilla JS tests but for now
- // we don't actually do any version-specific handling
- return jsUndefined();
-}
-
-JSValue* functionRun(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
-{
- StopWatch stopWatch;
- UString fileName = args.at(exec, 0)->toString(exec);
- Vector<char> script;
- if (!fillBufferWithContentsOfFile(fileName, script))
- return throwError(exec, GeneralError, "Could not open file.");
-
- JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-
- stopWatch.start();
- Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
- stopWatch.stop();
-
- return jsNumber(globalObject->globalExec(), stopWatch.getElapsedMS());
-}
-
-JSValue* functionLoad(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
-{
- UString fileName = args.at(exec, 0)->toString(exec);
- Vector<char> script;
- if (!fillBufferWithContentsOfFile(fileName, script))
- return throwError(exec, GeneralError, "Could not open file.");
-
- JSGlobalObject* globalObject = exec->lexicalGlobalObject();
- Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
-
- return jsUndefined();
-}
-
-JSValue* functionReadline(ExecState* exec, JSObject*, JSValue*, const ArgList&)
-{
- Vector<char, 256> line;
- int c;
- while ((c = getchar()) != EOF) {
- // FIXME: Should we also break on \r?
- if (c == '\n')
- break;
- line.append(c);
- }
- line.append('\0');
- return jsString(exec, line.data());
-}
-
-JSValue* functionQuit(ExecState*, JSObject*, JSValue*, const ArgList&)
-{
- exit(0);
-#if !COMPILER(MSVC)
- // MSVC knows that exit(0) never returns, so it flags this return statement as unreachable.
- return jsUndefined();
-#endif
-}
-
-// Use SEH for Release builds only to get rid of the crash report dialog
-// (luckily the same tests fail in Release and Debug builds so far). Need to
-// be in a separate main function because the jscmain function requires object
-// unwinding.
-
-#if COMPILER(MSVC) && !defined(_DEBUG)
-#define TRY __try {
-#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
-#else
-#define TRY
-#define EXCEPT(x)
-#endif
-
-int jscmain(int argc, char** argv, JSGlobalData*);
-
-int main(int argc, char** argv)
-{
-#if defined(_DEBUG) && PLATFORM(WIN_OS)
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
-#endif
-
-#if PLATFORM(QT)
- QCoreApplication app(argc, argv);
-#endif
-
- int res = 0;
- TRY
- res = jscmain(argc, argv, JSGlobalData::create().releaseRef());
- EXCEPT(res = 3)
- return res;
-}
-
-static bool prettyPrintScript(ExecState* exec, const UString& fileName, const Vector<char>& script)
-{
- int errLine = 0;
- UString errMsg;
- RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), makeSource(script.data(), fileName), &errLine, &errMsg);
- if (!programNode) {
- fprintf(stderr, "%s:%d: %s.\n", fileName.UTF8String().c_str(), errLine, errMsg.UTF8String().c_str());
- return false;
- }
-
- printf("%s\n", programNode->toString().UTF8String().c_str());
- return true;
-}
-
-static bool runWithScripts(GlobalObject* globalObject, const Vector<UString>& fileNames, bool prettyPrint, bool dump)
-{
- Vector<char> script;
-
- if (dump)
- CodeGenerator::setDumpsGeneratedCode(true);
-
-#if ENABLE(OPCODE_SAMPLING)
- Machine* machine = globalObject->globalData()->machine;
- machine->setSampler(new SamplingTool(machine));
-#endif
-
- bool success = true;
- for (size_t i = 0; i < fileNames.size(); i++) {
- UString fileName = fileNames[i];
-
- if (!fillBufferWithContentsOfFile(fileName, script))
- return false; // fail early so we can catch missing files
-
- if (prettyPrint)
- prettyPrintScript(globalObject->globalExec(), fileName, script);
- else {
-#if ENABLE(OPCODE_SAMPLING)
- machine->sampler()->start();
-#endif
- Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
- success = success && completion.complType() != Throw;
- if (dump) {
- if (completion.complType() == Throw)
- printf("Exception: %s\n", completion.value()->toString(globalObject->globalExec()).ascii());
- else
- printf("End: %s\n", completion.value()->toString(globalObject->globalExec()).ascii());
- }
-
- globalObject->globalExec()->clearException();
-
-#if ENABLE(OPCODE_SAMPLING)
- machine->sampler()->stop();
-#endif
- }
- }
-
-#if ENABLE(OPCODE_SAMPLING)
- machine->sampler()->dump(globalObject->globalExec());
- delete machine->sampler();
-#endif
- return success;
-}
-
-static void runInteractive(GlobalObject* globalObject)
-{
- while (true) {
-#if HAVE(READLINE)
- char* line = readline(interactivePrompt);
- if (!line)
- break;
- if (line[0])
- add_history(line);
- Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName));
- free(line);
-#else
- puts(interactivePrompt);
- Vector<char, 256> line;
- int c;
- while ((c = getchar()) != EOF) {
- // FIXME: Should we also break on \r?
- if (c == '\n')
- break;
- line.append(c);
- }
- line.append('\0');
- Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName));
-#endif
- if (completion.complType() == Throw)
- printf("Exception: %s\n", completion.value()->toString(globalObject->globalExec()).ascii());
- else
- printf("%s\n", completion.value()->toString(globalObject->globalExec()).UTF8String().c_str());
-
- globalObject->globalExec()->clearException();
- }
- printf("\n");
-}
-
-static void printUsageStatement()
-{
- fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
- fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
- fprintf(stderr, " -f Specifies a source file (deprecated)\n");
- fprintf(stderr, " -h|--help Prints this help message\n");
- fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
- fprintf(stderr, " -p Prints formatted source code\n");
- fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
- exit(-1);
-}
-
-static void parseArguments(int argc, char** argv, Options& options)
-{
- int i = 1;
- for (; i < argc; ++i) {
- const char* arg = argv[i];
- if (strcmp(arg, "-f") == 0) {
- if (++i == argc)
- printUsageStatement();
- options.fileNames.append(argv[i]);
- continue;
- }
- if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
- printUsageStatement();
- }
- if (strcmp(arg, "-i") == 0) {
- options.interactive = true;
- continue;
- }
- if (strcmp(arg, "-p") == 0) {
- options.prettyPrint = true;
- continue;
- }
- if (strcmp(arg, "-d") == 0) {
- options.dump = true;
- continue;
- }
- if (strcmp(arg, "-s") == 0) {
-#if PLATFORM(UNIX)
- signal(SIGILL, _exit);
- signal(SIGFPE, _exit);
- signal(SIGBUS, _exit);
- signal(SIGSEGV, _exit);
-#endif
- continue;
- }
- if (strcmp(arg, "--") == 0) {
- ++i;
- break;
- }
- options.fileNames.append(argv[i]);
- }
-
- if (options.fileNames.isEmpty())
- options.interactive = true;
-
- for (; i < argc; ++i)
- options.arguments.append(argv[i]);
-}
-
-int jscmain(int argc, char** argv, JSGlobalData* globalData)
-{
- JSC::initializeThreading();
-
- JSLock lock(false);
-
- Options options;
- parseArguments(argc, argv, options);
-
- GlobalObject* globalObject = new (globalData) GlobalObject(options.arguments);
- bool success = runWithScripts(globalObject, options.fileNames, options.prettyPrint, options.dump);
- if (options.interactive && success)
- runInteractive(globalObject);
-
- return success ? 0 : 3;
-}
-
-static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer)
-{
- FILE* f = fopen(fileName.UTF8String().c_str(), "r");
- if (!f) {
- fprintf(stderr, "Could not open file: %s\n", fileName.UTF8String().c_str());
- return false;
- }
-
- size_t buffer_size = 0;
- size_t buffer_capacity = 1024;
-
- buffer.resize(buffer_capacity);
-
- while (!feof(f) && !ferror(f)) {
- buffer_size += fread(buffer.data() + buffer_size, 1, buffer_capacity - buffer_size, f);
- if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
- buffer_capacity *= 2;
- buffer.resize(buffer_capacity);
- }
- }
- fclose(f);
- buffer[buffer_size] = '\0';
-
- return true;
-}
diff --git a/JavaScriptCore/kjs/SourceCode.h b/JavaScriptCore/kjs/SourceCode.h
deleted file mode 100644
index 2840161..0000000
--- a/JavaScriptCore/kjs/SourceCode.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SourceCode_h
-#define SourceCode_h
-
-#include "SourceProvider.h"
-#include <wtf/RefPtr.h>
-
-namespace JSC {
-
- class SourceCode {
- public:
- SourceCode()
- : m_startChar(0)
- , m_endChar(0)
- , m_firstLine(0)
- {
- }
-
- SourceCode(PassRefPtr<SourceProvider> provider, int firstLine = 1)
- : m_provider(provider)
- , m_startChar(0)
- , m_endChar(m_provider->length())
- , m_firstLine(std::max(firstLine, 1))
- {
- }
-
- SourceCode(PassRefPtr<SourceProvider> provider, int start, int end, int firstLine)
- : m_provider(provider)
- , m_startChar(start)
- , m_endChar(end)
- , m_firstLine(std::max(firstLine, 1))
- {
- }
-
- UString toString() const
- {
- if (!m_provider)
- return UString();
- return m_provider->getRange(m_startChar, m_endChar);
- }
-
- bool isNull() const { return !m_provider; }
- SourceProvider* provider() const { return m_provider.get(); }
- int firstLine() const { return m_firstLine; }
- int startOffset() const { return m_startChar; }
- const UChar* data() const { return m_provider->data() + m_startChar; }
- int length() const { return m_endChar - m_startChar; }
-
- private:
- RefPtr<SourceProvider> m_provider;
- int m_startChar;
- int m_endChar;
- int m_firstLine;
- };
-
- inline SourceCode makeSource(const UString& source, const UString& url = UString(), int firstLine = 1)
- {
- return SourceCode(UStringSourceProvider::create(source, url), firstLine);
- }
-
-} // namespace JSC
-
-#endif // SourceCode_h
diff --git a/JavaScriptCore/kjs/SourceProvider.h b/JavaScriptCore/kjs/SourceProvider.h
deleted file mode 100644
index 755a10f..0000000
--- a/JavaScriptCore/kjs/SourceProvider.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SourceProvider_h
-#define SourceProvider_h
-
-#include "ustring.h"
-#include <wtf/RefCounted.h>
-
-namespace JSC {
-
- class SourceProvider : public RefCounted<SourceProvider> {
- public:
- SourceProvider(const UString& url)
- : m_url(url)
- {
- }
- virtual ~SourceProvider() { }
-
- virtual UString getRange(int start, int end) const = 0;
- virtual const UChar* data() const = 0;
- virtual int length() const = 0;
-
- const UString& url() { return m_url; }
- intptr_t asID() { return reinterpret_cast<intptr_t>(this); }
-
- private:
- UString m_url;
- };
-
- class UStringSourceProvider : public SourceProvider {
- public:
- static PassRefPtr<UStringSourceProvider> create(const UString& source, const UString& url)
- {
- return adoptRef(new UStringSourceProvider(source, url));
- }
-
- UString getRange(int start, int end) const { return m_source.substr(start, end - start); }
- const UChar* data() const { return m_source.data(); }
- int length() const { return m_source.size(); }
-
- private:
- UStringSourceProvider(const UString& source, const UString& url)
- : SourceProvider(url)
- , m_source(source)
- {
- }
-
- UString m_source;
- };
-
-} // namespace JSC
-
-#endif // SourceProvider_h
diff --git a/JavaScriptCore/kjs/TypeInfo.h b/JavaScriptCore/kjs/TypeInfo.h
deleted file mode 100644
index 4f0b16c..0000000
--- a/JavaScriptCore/kjs/TypeInfo.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TypeInfo_h
-#define TypeInfo_h
-
-#include "JSType.h"
-
-namespace JSC {
-
- // WebCore uses MasqueradesAsUndefined to make document.all and style.filter undetectable.
- static const unsigned MasqueradesAsUndefined = 1;
- static const unsigned ImplementsHasInstance = 1 << 1;
- static const unsigned OverridesHasInstance = 1 << 2;
- static const unsigned NeedsThisConversion = 1 << 3;
- static const unsigned HasStandardGetOwnPropertySlot = 1 << 4;
-
- class TypeInfo {
- friend class CTI;
- public:
- TypeInfo(JSType type, unsigned flags = 0) : m_type(type), m_flags(flags) { }
-
- JSType type() const { return m_type; }
-
- bool masqueradesAsUndefined() const { return m_flags & MasqueradesAsUndefined; }
- bool implementsHasInstance() const { return m_flags & ImplementsHasInstance; }
- bool overridesHasInstance() const { return m_flags & OverridesHasInstance; }
- bool needsThisConversion() const { return m_flags & NeedsThisConversion; }
- bool hasStandardGetOwnPropertySlot() const { return m_flags & HasStandardGetOwnPropertySlot; }
-
- unsigned flags() const { return m_flags; }
-
- private:
- JSType m_type;
- unsigned m_flags;
- };
-
-}
-
-#endif // TypeInfo_h
diff --git a/JavaScriptCore/kjs/collector.cpp b/JavaScriptCore/kjs/collector.cpp
deleted file mode 100644
index 53e889e..0000000
--- a/JavaScriptCore/kjs/collector.cpp
+++ /dev/null
@@ -1,1094 +0,0 @@
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "collector.h"
-
-#include "ArgList.h"
-#include "CollectorHeapIterator.h"
-#include "ExecState.h"
-#include "JSGlobalObject.h"
-#include "JSLock.h"
-#include "JSString.h"
-#include "JSValue.h"
-#include "Machine.h"
-#include "Tracing.h"
-#include <algorithm>
-#include <setjmp.h>
-#include <stdlib.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/UnusedParam.h>
-
-#if PLATFORM(DARWIN)
-
-#include <mach/mach_port.h>
-#include <mach/mach_init.h>
-#include <mach/task.h>
-#include <mach/thread_act.h>
-#include <mach/vm_map.h>
-
-#elif PLATFORM(WIN_OS)
-
-#include <windows.h>
-
-#elif PLATFORM(UNIX)
-
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#if PLATFORM(SOLARIS)
-#include <thread.h>
-#endif
-
-#if PLATFORM(LINUX)
-#include <pthread.h>
-#endif
-
-#if PLATFORM(OPENBSD)
-#include <pthread.h>
-#endif
-
-#if HAVE(PTHREAD_NP_H)
-#include <pthread_np.h>
-#endif
-
-#endif
-
-#define DEBUG_COLLECTOR 0
-#define COLLECT_ON_EVERY_ALLOCATION 0
-
-using std::max;
-
-namespace JSC {
-
-// tunable parameters
-
-const size_t SPARE_EMPTY_BLOCKS = 2;
-const size_t GROWTH_FACTOR = 2;
-const size_t LOW_WATER_FACTOR = 4;
-const size_t ALLOCATIONS_PER_COLLECTION = 4000;
-// This value has to be a macro to be used in max() without introducing
-// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
-#define MIN_ARRAY_SIZE (static_cast<size_t>(14))
-
-static void freeHeap(CollectorHeap*);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-#if PLATFORM(DARWIN)
-typedef mach_port_t PlatformThread;
-#elif PLATFORM(WIN_OS)
-struct PlatformThread {
- PlatformThread(DWORD _id, HANDLE _handle) : id(_id), handle(_handle) {}
- DWORD id;
- HANDLE handle;
-};
-#endif
-
-class Heap::Thread {
-public:
- Thread(pthread_t pthread, const PlatformThread& platThread, void* base)
- : posixThread(pthread)
- , platformThread(platThread)
- , stackBase(base)
- {
- }
-
- Thread* next;
- pthread_t posixThread;
- PlatformThread platformThread;
- void* stackBase;
-};
-
-#endif
-
-Heap::Heap(JSGlobalData* globalData)
- : m_markListSet(0)
-#if ENABLE(JSC_MULTIPLE_THREADS)
- , m_registeredThreads(0)
-#endif
- , m_globalData(globalData)
-{
- ASSERT(globalData);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
- int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread);
- if (error)
- CRASH();
-#endif
-
- memset(&primaryHeap, 0, sizeof(CollectorHeap));
- memset(&numberHeap, 0, sizeof(CollectorHeap));
-}
-
-Heap::~Heap()
-{
- // The destroy function must already have been called, so assert this.
- ASSERT(!m_globalData);
-}
-
-void Heap::destroy()
-{
- JSLock lock(false);
-
- if (!m_globalData)
- return;
-
- // The global object is not GC protected at this point, so sweeping may delete it
- // (and thus the global data) before other objects that may use the global data.
- RefPtr<JSGlobalData> protect(m_globalData);
-
- delete m_markListSet;
- m_markListSet = 0;
-
- sweep<PrimaryHeap>();
- // No need to sweep number heap, because the JSNumber destructor doesn't do anything.
-
- ASSERT(!primaryHeap.numLiveObjects);
-
- freeHeap(&primaryHeap);
- freeHeap(&numberHeap);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#ifndef NDEBUG
- int error =
-#endif
- pthread_key_delete(m_currentThreadRegistrar);
- ASSERT(!error);
-
- MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
- for (Heap::Thread* t = m_registeredThreads; t;) {
- Heap::Thread* next = t->next;
- delete t;
- t = next;
- }
-#endif
-
- m_globalData = 0;
-}
-
-template <HeapType heapType>
-static NEVER_INLINE CollectorBlock* allocateBlock()
-{
-#if PLATFORM(DARWIN)
- vm_address_t address = 0;
- // FIXME: tag the region as a JavaScriptCore heap when we get a registered VM tag: <rdar://problem/6054788>.
- vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
-#elif PLATFORM(WIN_OS)
- // windows virtual address granularity is naturally 64k
- LPVOID address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
-#elif HAVE(POSIX_MEMALIGN)
- void* address;
- posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE);
- memset(address, 0, BLOCK_SIZE);
-#else
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#error Need to initialize pagesize safely.
-#endif
- static size_t pagesize = getpagesize();
-
- size_t extra = 0;
- if (BLOCK_SIZE > pagesize)
- extra = BLOCK_SIZE - pagesize;
-
- void* mmapResult = mmap(NULL, BLOCK_SIZE + extra, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
- uintptr_t address = reinterpret_cast<uintptr_t>(mmapResult);
-
- size_t adjust = 0;
- if ((address & BLOCK_OFFSET_MASK) != 0)
- adjust = BLOCK_SIZE - (address & BLOCK_OFFSET_MASK);
-
- if (adjust > 0)
- munmap(reinterpret_cast<char*>(address), adjust);
-
- if (adjust < extra)
- munmap(reinterpret_cast<char*>(address + adjust + BLOCK_SIZE), extra - adjust);
-
- address += adjust;
- memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
-#endif
- reinterpret_cast<CollectorBlock*>(address)->type = heapType;
- return reinterpret_cast<CollectorBlock*>(address);
-}
-
-static void freeBlock(CollectorBlock* block)
-{
-#if PLATFORM(DARWIN)
- vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
-#elif PLATFORM(WIN_OS)
- VirtualFree(block, 0, MEM_RELEASE);
-#elif HAVE(POSIX_MEMALIGN)
- free(block);
-#else
- munmap(reinterpret_cast<char*>(block), BLOCK_SIZE);
-#endif
-}
-
-static void freeHeap(CollectorHeap* heap)
-{
- for (size_t i = 0; i < heap->usedBlocks; ++i)
- if (heap->blocks[i])
- freeBlock(heap->blocks[i]);
- fastFree(heap->blocks);
- memset(heap, 0, sizeof(CollectorHeap));
-}
-
-void Heap::recordExtraCost(size_t cost)
-{
- // Our frequency of garbage collection tries to balance memory use against speed
- // by collecting based on the number of newly created values. However, for values
- // that hold on to a great deal of memory that's not in the form of other JS values,
- // that is not good enough - in some cases a lot of those objects can pile up and
- // use crazy amounts of memory without a GC happening. So we track these extra
- // memory costs. Only unusually large objects are noted, and we only keep track
- // of this extra cost until the next GC. In garbage collected languages, most values
- // are either very short lived temporaries, or have extremely long lifetimes. So
- // if a large value survives one garbage collection, there is not much point to
- // collecting more frequently as long as it stays alive.
- // NOTE: we target the primaryHeap unconditionally as JSNumber doesn't modify cost
-
- primaryHeap.extraCost += cost;
-}
-
-template <HeapType heapType> ALWAYS_INLINE void* Heap::heapAllocate(size_t s)
-{
- typedef typename HeapConstants<heapType>::Block Block;
- typedef typename HeapConstants<heapType>::Cell Cell;
-
- CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
- ASSERT(s <= HeapConstants<heapType>::cellSize);
- UNUSED_PARAM(s); // s is now only used for the above assert
-
- ASSERT(heap.operationInProgress == NoOperation);
- ASSERT(heapType == PrimaryHeap || heap.extraCost == 0);
- // FIXME: If another global variable access here doesn't hurt performance
- // too much, we could abort() in NDEBUG builds, which could help ensure we
- // don't spend any time debugging cases where we allocate inside an object's
- // deallocation code.
-
- size_t numLiveObjects = heap.numLiveObjects;
- size_t usedBlocks = heap.usedBlocks;
- size_t i = heap.firstBlockWithPossibleSpace;
-
-#if COLLECT_ON_EVERY_ALLOCATION
- collect();
-#endif
-
- // if we have a huge amount of extra cost, we'll try to collect even if we still have
- // free cells left.
- if (heapType == PrimaryHeap && heap.extraCost > ALLOCATIONS_PER_COLLECTION) {
- size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
- size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
- const size_t newCost = numNewObjects + heap.extraCost;
- if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect)
- goto collect;
- }
-
- ASSERT(heap.operationInProgress == NoOperation);
-#ifndef NDEBUG
- // FIXME: Consider doing this in NDEBUG builds too (see comment above).
- heap.operationInProgress = Allocation;
-#endif
-
-scan:
- Block* targetBlock;
- size_t targetBlockUsedCells;
- if (i != usedBlocks) {
- targetBlock = reinterpret_cast<Block*>(heap.blocks[i]);
- targetBlockUsedCells = targetBlock->usedCells;
- ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
- while (targetBlockUsedCells == HeapConstants<heapType>::cellsPerBlock) {
- if (++i == usedBlocks)
- goto collect;
- targetBlock = reinterpret_cast<Block*>(heap.blocks[i]);
- targetBlockUsedCells = targetBlock->usedCells;
- ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
- }
- heap.firstBlockWithPossibleSpace = i;
- } else {
-
-collect:
- size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
- size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
- const size_t newCost = numNewObjects + heap.extraCost;
-
- if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect) {
-#ifndef NDEBUG
- heap.operationInProgress = NoOperation;
-#endif
- bool collected = collect();
-#ifndef NDEBUG
- heap.operationInProgress = Allocation;
-#endif
- if (collected) {
- numLiveObjects = heap.numLiveObjects;
- usedBlocks = heap.usedBlocks;
- i = heap.firstBlockWithPossibleSpace;
- goto scan;
- }
- }
-
- // didn't find a block, and GC didn't reclaim anything, need to allocate a new block
- size_t numBlocks = heap.numBlocks;
- if (usedBlocks == numBlocks) {
- numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
- heap.numBlocks = numBlocks;
- heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));
- }
-
- targetBlock = reinterpret_cast<Block*>(allocateBlock<heapType>());
- targetBlock->freeList = targetBlock->cells;
- targetBlock->heap = this;
- targetBlockUsedCells = 0;
- heap.blocks[usedBlocks] = reinterpret_cast<CollectorBlock*>(targetBlock);
- heap.usedBlocks = usedBlocks + 1;
- heap.firstBlockWithPossibleSpace = usedBlocks;
- }
-
- // find a free spot in the block and detach it from the free list
- Cell* newCell = targetBlock->freeList;
-
- // "next" field is a cell offset -- 0 means next cell, so a zeroed block is already initialized
- targetBlock->freeList = (newCell + 1) + newCell->u.freeCell.next;
-
- targetBlock->usedCells = static_cast<uint32_t>(targetBlockUsedCells + 1);
- heap.numLiveObjects = numLiveObjects + 1;
-
-#ifndef NDEBUG
- // FIXME: Consider doing this in NDEBUG builds too (see comment above).
- heap.operationInProgress = NoOperation;
-#endif
-
- return newCell;
-}
-
-void* Heap::allocate(size_t s)
-{
- return heapAllocate<PrimaryHeap>(s);
-}
-
-void* Heap::allocateNumber(size_t s)
-{
- return heapAllocate<NumberHeap>(s);
-}
-
-static inline void* currentThreadStackBase()
-{
-#if PLATFORM(DARWIN)
- pthread_t thread = pthread_self();
- return pthread_get_stackaddr_np(thread);
-#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(MSVC)
- // offset 0x18 from the FS segment register gives a pointer to
- // the thread information block for the current thread
- NT_TIB* pTib;
- __asm {
- MOV EAX, FS:[18h]
- MOV pTib, EAX
- }
- return static_cast<void*>(pTib->StackBase);
-#elif PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC)
- PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
- return reinterpret_cast<void*>(pTib->StackBase);
-#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(GCC)
- // offset 0x18 from the FS segment register gives a pointer to
- // the thread information block for the current thread
- NT_TIB* pTib;
- asm ( "movl %%fs:0x18, %0\n"
- : "=r" (pTib)
- );
- return static_cast<void*>(pTib->StackBase);
-#elif PLATFORM(SOLARIS)
- stack_t s;
- thr_stksegment(&s);
- return s.ss_sp;
-#elif PLATFORM(OPENBSD)
- pthread_t thread = pthread_self();
- stack_t stack;
- pthread_stackseg_np(thread, &stack);
- return stack.ss_sp;
-#elif PLATFORM(UNIX)
- static void* stackBase = 0;
- static size_t stackSize = 0;
- static pthread_t stackThread;
- pthread_t thread = pthread_self();
- if (stackBase == 0 || thread != stackThread) {
- pthread_attr_t sattr;
- pthread_attr_init(&sattr);
-#if HAVE(PTHREAD_NP_H)
- // e.g. on FreeBSD 5.4, neundorf@kde.org
- pthread_attr_get_np(thread, &sattr);
-#else
- // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
- pthread_getattr_np(thread, &sattr);
-#endif
- int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
- (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
- ASSERT(stackBase);
- pthread_attr_destroy(&sattr);
- stackThread = thread;
- }
- return static_cast<char*>(stackBase) + stackSize;
-#else
-#error Need a way to get the stack base on this platform
-#endif
-}
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-static inline PlatformThread getCurrentPlatformThread()
-{
-#if PLATFORM(DARWIN)
- return pthread_mach_thread_np(pthread_self());
-#elif PLATFORM(WIN_OS)
- HANDLE threadHandle = pthread_getw32threadhandle_np(pthread_self());
- return PlatformThread(GetCurrentThreadId(), threadHandle);
-#endif
-}
-
-void Heap::registerThread()
-{
- if (pthread_getspecific(m_currentThreadRegistrar))
- return;
-
- pthread_setspecific(m_currentThreadRegistrar, this);
- Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), currentThreadStackBase());
-
- MutexLocker lock(m_registeredThreadsMutex);
-
- thread->next = m_registeredThreads;
- m_registeredThreads = thread;
-}
-
-void Heap::unregisterThread(void* p)
-{
- if (p)
- static_cast<Heap*>(p)->unregisterThread();
-}
-
-void Heap::unregisterThread()
-{
- pthread_t currentPosixThread = pthread_self();
-
- MutexLocker lock(m_registeredThreadsMutex);
-
- if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {
- Thread* t = m_registeredThreads;
- m_registeredThreads = m_registeredThreads->next;
- delete t;
- } else {
- Heap::Thread* last = m_registeredThreads;
- Heap::Thread* t;
- for (t = m_registeredThreads->next; t; t = t->next) {
- if (pthread_equal(t->posixThread, currentPosixThread)) {
- last->next = t->next;
- break;
- }
- last = t;
- }
- ASSERT(t); // If t is NULL, we never found ourselves in the list.
- delete t;
- }
-}
-
-#else // ENABLE(JSC_MULTIPLE_THREADS)
-
-void Heap::registerThread()
-{
-}
-
-#endif
-
-#define IS_POINTER_ALIGNED(p) (((intptr_t)(p) & (sizeof(char*) - 1)) == 0)
-
-// cell size needs to be a power of two for this to be valid
-#define IS_HALF_CELL_ALIGNED(p) (((intptr_t)(p) & (CELL_MASK >> 1)) == 0)
-
-void Heap::markConservatively(void* start, void* end)
-{
- if (start > end) {
- void* tmp = start;
- start = end;
- end = tmp;
- }
-
- ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000);
- ASSERT(IS_POINTER_ALIGNED(start));
- ASSERT(IS_POINTER_ALIGNED(end));
-
- char** p = static_cast<char**>(start);
- char** e = static_cast<char**>(end);
-
- size_t usedPrimaryBlocks = primaryHeap.usedBlocks;
- size_t usedNumberBlocks = numberHeap.usedBlocks;
- CollectorBlock** primaryBlocks = primaryHeap.blocks;
- CollectorBlock** numberBlocks = numberHeap.blocks;
-
- const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
-
- while (p != e) {
- char* x = *p++;
- if (IS_HALF_CELL_ALIGNED(x) && x) {
- uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
- xAsBits &= CELL_ALIGN_MASK;
- uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK;
- CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);
- // Mark the the number heap, we can mark these Cells directly to avoid the virtual call cost
- for (size_t block = 0; block < usedNumberBlocks; block++) {
- if ((numberBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
- Heap::markCell(reinterpret_cast<JSCell*>(xAsBits));
- goto endMarkLoop;
- }
- }
-
- // Mark the primary heap
- for (size_t block = 0; block < usedPrimaryBlocks; block++) {
- if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
- if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree != 0) {
- JSCell* imp = reinterpret_cast<JSCell*>(xAsBits);
- if (!imp->marked())
- imp->mark();
- }
- break;
- }
- }
- endMarkLoop:
- ;
- }
- }
-}
-
-void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal()
-{
- void* dummy;
- void* stackPointer = &dummy;
- void* stackBase = currentThreadStackBase();
- markConservatively(stackPointer, stackBase);
-}
-
-void Heap::markCurrentThreadConservatively()
-{
- // setjmp forces volatile registers onto the stack
- jmp_buf registers;
-#if COMPILER(MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4611)
-#endif
- setjmp(registers);
-#if COMPILER(MSVC)
-#pragma warning(pop)
-#endif
-
- markCurrentThreadConservativelyInternal();
-}
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-static inline void suspendThread(const PlatformThread& platformThread)
-{
-#if PLATFORM(DARWIN)
- thread_suspend(platformThread);
-#elif PLATFORM(WIN_OS)
- SuspendThread(platformThread.handle);
-#else
-#error Need a way to suspend threads on this platform
-#endif
-}
-
-static inline void resumeThread(const PlatformThread& platformThread)
-{
-#if PLATFORM(DARWIN)
- thread_resume(platformThread);
-#elif PLATFORM(WIN_OS)
- ResumeThread(platformThread.handle);
-#else
-#error Need a way to resume threads on this platform
-#endif
-}
-
-typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
-
-#if PLATFORM(DARWIN)
-
-#if PLATFORM(X86)
-typedef i386_thread_state_t PlatformThreadRegisters;
-#elif PLATFORM(X86_64)
-typedef x86_thread_state64_t PlatformThreadRegisters;
-#elif PLATFORM(PPC)
-typedef ppc_thread_state_t PlatformThreadRegisters;
-#elif PLATFORM(PPC64)
-typedef ppc_thread_state64_t PlatformThreadRegisters;
-#elif PLATFORM(ARM)
-typedef arm_thread_state_t PlatformThreadRegisters;
-#else
-#error Unknown Architecture
-#endif
-
-#elif PLATFORM(WIN_OS)&& PLATFORM(X86)
-typedef CONTEXT PlatformThreadRegisters;
-#else
-#error Need a thread register struct for this platform
-#endif
-
-size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
-{
-#if PLATFORM(DARWIN)
-
-#if PLATFORM(X86)
- unsigned user_count = sizeof(regs)/sizeof(int);
- thread_state_flavor_t flavor = i386_THREAD_STATE;
-#elif PLATFORM(X86_64)
- unsigned user_count = x86_THREAD_STATE64_COUNT;
- thread_state_flavor_t flavor = x86_THREAD_STATE64;
-#elif PLATFORM(PPC)
- unsigned user_count = PPC_THREAD_STATE_COUNT;
- thread_state_flavor_t flavor = PPC_THREAD_STATE;
-#elif PLATFORM(PPC64)
- unsigned user_count = PPC_THREAD_STATE64_COUNT;
- thread_state_flavor_t flavor = PPC_THREAD_STATE64;
-#elif PLATFORM(ARM)
- unsigned user_count = ARM_THREAD_STATE_COUNT;
- thread_state_flavor_t flavor = ARM_THREAD_STATE;
-#else
-#error Unknown Architecture
-#endif
-
- kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
- if (result != KERN_SUCCESS) {
- WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION,
- "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
- CRASH();
- }
- return user_count * sizeof(usword_t);
-// end PLATFORM(DARWIN)
-
-#elif PLATFORM(WIN_OS) && PLATFORM(X86)
- regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
- GetThreadContext(platformThread.handle, &regs);
- return sizeof(CONTEXT);
-#else
-#error Need a way to get thread registers on this platform
-#endif
-}
-
-static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
-{
-#if PLATFORM(DARWIN)
-
-#if __DARWIN_UNIX03
-
-#if PLATFORM(X86)
- return reinterpret_cast<void*>(regs.__esp);
-#elif PLATFORM(X86_64)
- return reinterpret_cast<void*>(regs.__rsp);
-#elif PLATFORM(PPC) || PLATFORM(PPC64)
- return reinterpret_cast<void*>(regs.__r1);
-#elif PLATFORM(ARM)
- return reinterpret_cast<void*>(regs.__sp);
-#else
-#error Unknown Architecture
-#endif
-
-#else // !__DARWIN_UNIX03
-
-#if PLATFORM(X86)
- return reinterpret_cast<void*>(regs.esp);
-#elif PLATFORM(X86_64)
- return reinterpret_cast<void*>(regs.rsp);
-#elif (PLATFORM(PPC) || PLATFORM(PPC64))
- return reinterpret_cast<void*>(regs.r1);
-#else
-#error Unknown Architecture
-#endif
-
-#endif // __DARWIN_UNIX03
-
-// end PLATFORM(DARWIN)
-#elif PLATFORM(X86) && PLATFORM(WIN_OS)
- return reinterpret_cast<void*>((uintptr_t) regs.Esp);
-#else
-#error Need a way to get the stack pointer for another thread on this platform
-#endif
-}
-
-void Heap::markOtherThreadConservatively(Thread* thread)
-{
- suspendThread(thread->platformThread);
-
- PlatformThreadRegisters regs;
- size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
-
- // mark the thread's registers
- markConservatively(static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
-
- void* stackPointer = otherThreadStackPointer(regs);
- markConservatively(stackPointer, thread->stackBase);
-
- resumeThread(thread->platformThread);
-}
-
-#endif
-
-void Heap::markStackObjectsConservatively()
-{
- markCurrentThreadConservatively();
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
- if (m_currentThreadRegistrar) {
-
- MutexLocker lock(m_registeredThreadsMutex);
-
-#ifndef NDEBUG
- // Forbid malloc during the mark phase. Marking a thread suspends it, so
- // a malloc inside mark() would risk a deadlock with a thread that had been
- // suspended while holding the malloc lock.
- fastMallocForbid();
-#endif
- // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
- // and since this is a shared heap, they are real locks.
- for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
- if (!pthread_equal(thread->posixThread, pthread_self()))
- markOtherThreadConservatively(thread);
- }
-#ifndef NDEBUG
- fastMallocAllow();
-#endif
- }
-#endif
-}
-
-void Heap::setGCProtectNeedsLocking()
-{
- // Most clients do not need to call this, with the notable exception of WebCore.
- // Clients that use shared heap have JSLock protection, while others are supposed
- // to do explicit locking. WebCore violates this contract in Database code,
- // which calls gcUnprotect from a secondary thread.
- if (!m_protectedValuesMutex)
- m_protectedValuesMutex.set(new Mutex);
-}
-
-void Heap::protect(JSValue* k)
-{
- ASSERT(k);
- ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance);
-
- if (JSImmediate::isImmediate(k))
- return;
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
- m_protectedValues.add(k->asCell());
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-}
-
-void Heap::unprotect(JSValue* k)
-{
- ASSERT(k);
- ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance);
-
- if (JSImmediate::isImmediate(k))
- return;
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
- m_protectedValues.remove(k->asCell());
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-}
-
-Heap* Heap::heap(JSValue* v)
-{
- if (JSImmediate::isImmediate(v))
- return 0;
- return Heap::cellBlock(v->asCell())->heap;
-}
-
-void Heap::markProtectedObjects()
-{
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
- ProtectCountSet::iterator end = m_protectedValues.end();
- for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
- JSCell* val = it->first;
- if (!val->marked())
- val->mark();
- }
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-}
-
-template <HeapType heapType> size_t Heap::sweep()
-{
- typedef typename HeapConstants<heapType>::Block Block;
- typedef typename HeapConstants<heapType>::Cell Cell;
-
- // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else
- CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
-
- size_t emptyBlocks = 0;
- size_t numLiveObjects = heap.numLiveObjects;
-
- for (size_t block = 0; block < heap.usedBlocks; block++) {
- Block* curBlock = reinterpret_cast<Block*>(heap.blocks[block]);
-
- size_t usedCells = curBlock->usedCells;
- Cell* freeList = curBlock->freeList;
-
- if (usedCells == HeapConstants<heapType>::cellsPerBlock) {
- // special case with a block where all cells are used -- testing indicates this happens often
- for (size_t i = 0; i < HeapConstants<heapType>::cellsPerBlock; i++) {
- if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
- Cell* cell = curBlock->cells + i;
-
- if (heapType != NumberHeap) {
- JSCell* imp = reinterpret_cast<JSCell*>(cell);
- // special case for allocated but uninitialized object
- // (We don't need this check earlier because nothing prior this point
- // assumes the object has a valid vptr.)
- if (cell->u.freeCell.zeroIfFree == 0)
- continue;
-
- imp->~JSCell();
- }
-
- --usedCells;
- --numLiveObjects;
-
- // put cell on the free list
- cell->u.freeCell.zeroIfFree = 0;
- cell->u.freeCell.next = freeList - (cell + 1);
- freeList = cell;
- }
- }
- } else {
- size_t minimumCellsToProcess = usedCells;
- for (size_t i = 0; (i < minimumCellsToProcess) & (i < HeapConstants<heapType>::cellsPerBlock); i++) {
- Cell* cell = curBlock->cells + i;
- if (cell->u.freeCell.zeroIfFree == 0) {
- ++minimumCellsToProcess;
- } else {
- if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
- if (heapType != NumberHeap) {
- JSCell* imp = reinterpret_cast<JSCell*>(cell);
- imp->~JSCell();
- }
- --usedCells;
- --numLiveObjects;
-
- // put cell on the free list
- cell->u.freeCell.zeroIfFree = 0;
- cell->u.freeCell.next = freeList - (cell + 1);
- freeList = cell;
- }
- }
- }
- }
-
- curBlock->usedCells = static_cast<uint32_t>(usedCells);
- curBlock->freeList = freeList;
- curBlock->marked.clearAll();
-
- if (usedCells == 0) {
- emptyBlocks++;
- if (emptyBlocks > SPARE_EMPTY_BLOCKS) {
-#if !DEBUG_COLLECTOR
- freeBlock(reinterpret_cast<CollectorBlock*>(curBlock));
-#endif
- // swap with the last block so we compact as we go
- heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
- heap.usedBlocks--;
- block--; // Don't move forward a step in this case
-
- if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
- heap.numBlocks = heap.numBlocks / GROWTH_FACTOR;
- heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*)));
- }
- }
- }
- }
-
- if (heap.numLiveObjects != numLiveObjects)
- heap.firstBlockWithPossibleSpace = 0;
-
- heap.numLiveObjects = numLiveObjects;
- heap.numLiveObjectsAtLastCollect = numLiveObjects;
- heap.extraCost = 0;
- return numLiveObjects;
-}
-
-bool Heap::collect()
-{
-#ifndef NDEBUG
- if (m_globalData->isSharedInstance) {
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
- }
-#endif
-
- ASSERT((primaryHeap.operationInProgress == NoOperation) | (numberHeap.operationInProgress == NoOperation));
- if ((primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation))
- abort();
-
- JAVASCRIPTCORE_GC_BEGIN();
- primaryHeap.operationInProgress = Collection;
- numberHeap.operationInProgress = Collection;
-
- // MARK: first mark all referenced objects recursively starting out from the set of root objects
-
- markStackObjectsConservatively();
- markProtectedObjects();
- if (m_markListSet && m_markListSet->size())
- ArgList::markLists(*m_markListSet);
- if (m_globalData->exception && !m_globalData->exception->marked())
- m_globalData->exception->mark();
- m_globalData->machine->registerFile().markCallFrames(this);
- m_globalData->smallStrings.mark();
-
- JSGlobalObject* globalObject = m_globalData->head;
- if (globalObject) {
- do {
- globalObject->markCrossHeapDependentObjects();
- globalObject = globalObject->next();
- } while (globalObject != m_globalData->head);
- }
-
- JAVASCRIPTCORE_GC_MARKED();
-
- size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
- size_t numLiveObjects = sweep<PrimaryHeap>();
- numLiveObjects += sweep<NumberHeap>();
-
- primaryHeap.operationInProgress = NoOperation;
- numberHeap.operationInProgress = NoOperation;
- JAVASCRIPTCORE_GC_END(originalLiveObjects, numLiveObjects);
-
- return numLiveObjects < originalLiveObjects;
-}
-
-size_t Heap::size()
-{
- return primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
-}
-
-size_t Heap::globalObjectCount()
-{
- size_t count = 0;
- if (JSGlobalObject* head = m_globalData->head) {
- JSGlobalObject* o = head;
- do {
- ++count;
- o = o->next();
- } while (o != head);
- }
- return count;
-}
-
-size_t Heap::protectedGlobalObjectCount()
-{
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
- size_t count = 0;
- if (JSGlobalObject* head = m_globalData->head) {
- JSGlobalObject* o = head;
- do {
- if (m_protectedValues.contains(o))
- ++count;
- o = o->next();
- } while (o != head);
- }
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-
- return count;
-}
-
-size_t Heap::protectedObjectCount()
-{
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
- size_t result = m_protectedValues.size();
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-
- return result;
-}
-
-static const char* typeName(JSCell* val)
-{
- if (val->isString())
- return "string";
- if (val->isNumber())
- return "number";
- if (val->isGetterSetter())
- return "gettersetter";
- ASSERT(val->isObject());
- const ClassInfo* info = static_cast<JSObject*>(val)->classInfo();
- return info ? info->className : "Object";
-}
-
-HashCountedSet<const char*>* Heap::protectedObjectTypeCounts()
-{
- HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
- ProtectCountSet::iterator end = m_protectedValues.end();
- for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
- counts->add(typeName(it->first));
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-
- return counts;
-}
-
-bool Heap::isBusy()
-{
- return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation);
-}
-
-Heap::iterator Heap::primaryHeapBegin()
-{
- return iterator(primaryHeap.blocks, primaryHeap.blocks + primaryHeap.usedBlocks);
-}
-
-Heap::iterator Heap::primaryHeapEnd()
-{
- return iterator(primaryHeap.blocks + primaryHeap.usedBlocks, primaryHeap.blocks + primaryHeap.usedBlocks);
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/collector.h b/JavaScriptCore/kjs/collector.h
deleted file mode 100644
index 4233b06..0000000
--- a/JavaScriptCore/kjs/collector.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef KJSCOLLECTOR_H_
-#define KJSCOLLECTOR_H_
-
-#include "JSImmediate.h"
-#include <string.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/Threading.h>
-
-// This is supremely lame that we require pthreads to build on windows.
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#include <pthread.h>
-#endif
-
-#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell)
-
-namespace JSC {
-
- class ArgList;
- class CollectorBlock;
- class JSCell;
- class JSGlobalData;
-
- enum OperationInProgress { NoOperation, Allocation, Collection };
- enum HeapType { PrimaryHeap, NumberHeap };
-
- template <HeapType> class CollectorHeapIterator;
-
- struct CollectorHeap {
- CollectorBlock** blocks;
- size_t numBlocks;
- size_t usedBlocks;
- size_t firstBlockWithPossibleSpace;
-
- size_t numLiveObjects;
- size_t numLiveObjectsAtLastCollect;
- size_t extraCost;
-
- OperationInProgress operationInProgress;
- };
-
- class Heap : Noncopyable {
- public:
- class Thread;
- typedef CollectorHeapIterator<PrimaryHeap> iterator;
-
- void destroy();
-
-#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
- // We can inline these functions because everything is compiled as
- // one file, so the heapAllocate template definitions are available.
- // However, allocateNumber is used via jsNumberCell outside JavaScriptCore.
- // Thus allocateNumber needs to provide a non-inline version too.
- void* inlineAllocateNumber(size_t s) { return heapAllocate<NumberHeap>(s); }
- void* inlineAllocate(size_t s) { return heapAllocate<PrimaryHeap>(s); }
-#endif
- void* allocateNumber(size_t);
- void* allocate(size_t);
-
- bool collect();
- bool isBusy(); // true if an allocation or collection is in progress
-
- static const size_t minExtraCostSize = 256;
-
- void reportExtraMemoryCost(size_t cost);
-
- size_t size();
-
- void setGCProtectNeedsLocking();
- void protect(JSValue*);
- void unprotect(JSValue*);
-
- static Heap* heap(JSValue*); // 0 for immediate values
-
- size_t globalObjectCount();
- size_t protectedObjectCount();
- size_t protectedGlobalObjectCount();
- HashCountedSet<const char*>* protectedObjectTypeCounts();
-
- void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
-
- static bool isCellMarked(const JSCell*);
- static void markCell(JSCell*);
-
- void markConservatively(void* start, void* end);
-
- HashSet<ArgList*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<ArgList*>; return *m_markListSet; }
-
- JSGlobalData* globalData() const { return m_globalData; }
- static bool isNumber(JSCell*);
-
- // Iterators for the object heap.
- iterator primaryHeapBegin();
- iterator primaryHeapEnd();
-
- private:
- template <HeapType heapType> void* heapAllocate(size_t);
- template <HeapType heapType> size_t sweep();
- static CollectorBlock* cellBlock(const JSCell*);
- static size_t cellOffset(const JSCell*);
-
- friend class JSGlobalData;
- Heap(JSGlobalData*);
- ~Heap();
-
- void recordExtraCost(size_t);
- void markProtectedObjects();
- void markCurrentThreadConservatively();
- void markCurrentThreadConservativelyInternal();
- void markOtherThreadConservatively(Thread*);
- void markStackObjectsConservatively();
-
- typedef HashCountedSet<JSCell*> ProtectCountSet;
-
- CollectorHeap primaryHeap;
- CollectorHeap numberHeap;
-
- OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking().
- ProtectCountSet m_protectedValues;
-
- HashSet<ArgList*>* m_markListSet;
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
- static void unregisterThread(void*);
- void unregisterThread();
-
- Mutex m_registeredThreadsMutex;
- Thread* m_registeredThreads;
- pthread_key_t m_currentThreadRegistrar;
-#endif
-
- JSGlobalData* m_globalData;
- };
-
- // tunable parameters
- template<size_t bytesPerWord> struct CellSize;
-
- // cell size needs to be a power of two for certain optimizations in collector.cpp
- template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; }; // 32-bit
- template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; // 64-bit
- const size_t BLOCK_SIZE = 16 * 4096; // 64k
-
- // derived constants
- const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
- const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
- const size_t MINIMUM_CELL_SIZE = CellSize<sizeof(void*)>::m_value;
- const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
- const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
- const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
- const size_t CELL_MASK = CELL_SIZE - 1;
- const size_t CELL_ALIGN_MASK = ~CELL_MASK;
- const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2);
- const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK;
- const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
- const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
-
- struct CollectorBitmap {
- uint32_t bits[BITMAP_WORDS];
- bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); }
- void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); }
- void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); }
- void clearAll() { memset(bits, 0, sizeof(bits)); }
- };
-
- struct CollectorCell {
- union {
- double memory[CELL_ARRAY_LENGTH];
- struct {
- void* zeroIfFree;
- ptrdiff_t next;
- } freeCell;
- } u;
- };
-
- struct SmallCollectorCell {
- union {
- double memory[CELL_ARRAY_LENGTH / 2];
- struct {
- void* zeroIfFree;
- ptrdiff_t next;
- } freeCell;
- } u;
- };
-
- class CollectorBlock {
- public:
- CollectorCell cells[CELLS_PER_BLOCK];
- uint32_t usedCells;
- CollectorCell* freeList;
- CollectorBitmap marked;
- Heap* heap;
- HeapType type;
- };
-
- class SmallCellCollectorBlock {
- public:
- SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK];
- uint32_t usedCells;
- SmallCollectorCell* freeList;
- CollectorBitmap marked;
- Heap* heap;
- HeapType type;
- };
-
- template <HeapType heapType> struct HeapConstants;
-
- template <> struct HeapConstants<PrimaryHeap> {
- static const size_t cellSize = CELL_SIZE;
- static const size_t cellsPerBlock = CELLS_PER_BLOCK;
- static const size_t bitmapShift = 0;
- typedef CollectorCell Cell;
- typedef CollectorBlock Block;
- };
-
- template <> struct HeapConstants<NumberHeap> {
- static const size_t cellSize = SMALL_CELL_SIZE;
- static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK;
- static const size_t bitmapShift = 1;
- typedef SmallCollectorCell Cell;
- typedef SmallCellCollectorBlock Block;
- };
-
- inline CollectorBlock* Heap::cellBlock(const JSCell* cell)
- {
- return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK);
- }
-
- inline bool Heap::isNumber(JSCell* cell)
- {
- return Heap::cellBlock(cell)->type == NumberHeap;
- }
-
- inline size_t Heap::cellOffset(const JSCell* cell)
- {
- return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
- }
-
- inline bool Heap::isCellMarked(const JSCell* cell)
- {
- return cellBlock(cell)->marked.get(cellOffset(cell));
- }
-
- inline void Heap::markCell(JSCell* cell)
- {
- cellBlock(cell)->marked.set(cellOffset(cell));
- }
-
- inline void Heap::reportExtraMemoryCost(size_t cost)
- {
- if (cost > minExtraCostSize)
- recordExtraCost(cost / (CELL_SIZE * 2));
- }
-
-} // namespace JSC
-
-#endif /* KJSCOLLECTOR_H_ */
diff --git a/JavaScriptCore/kjs/completion.h b/JavaScriptCore/kjs/completion.h
deleted file mode 100644
index 56d13ed..0000000
--- a/JavaScriptCore/kjs/completion.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_COMPLETION_H
-#define KJS_COMPLETION_H
-
-#include "JSValue.h"
-
-namespace JSC {
-
- enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted };
-
- /*
- * Completion objects are used to convey the return status and value
- * from functions.
- */
- class Completion {
- public:
- Completion(ComplType type = Normal, JSValue* value = noValue())
- : m_type(type)
- , m_value(value)
- {
- }
-
- ComplType complType() const { return m_type; }
- JSValue* value() const { return m_value; }
- void setValue(JSValue* v) { m_value = v; }
- bool isValueCompletion() const { return !!m_value; }
-
- private:
- ComplType m_type;
- JSValue* m_value;
- };
-
-} // namespace JSC
-
-#endif // KJS_COMPLETION_H
diff --git a/JavaScriptCore/kjs/config.h b/JavaScriptCore/kjs/config.h
deleted file mode 100644
index 80a3798..0000000
--- a/JavaScriptCore/kjs/config.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
-#include "autotoolsconfig.h"
-#endif
-
-#include <wtf/Platform.h>
-
-#if PLATFORM(ANDROID)
-
-#define ANDROID_MOBILE // change can be merged back to WebKit.org for MOBILE
-//#define ANDROID_INSTRUMENT
-#endif
-
-#if PLATFORM(WIN_OS)
-
-// If we don't define these, they get defined in windef.h.
-// We want to use std::min and std::max
-#define max max
-#define min min
-
-#if !COMPILER(MSVC7)
-// We need to define this before the first #include of stdlib.h or it won't contain rand_s.
-#ifndef _CRT_RAND_S
-#define _CRT_RAND_S
-#endif
-#endif
-
-#endif
-
-#if PLATFORM(FREEBSD) || PLATFORM(OPENBSD)
-#define HAVE_PTHREAD_NP_H 1
-#endif
-
-/* FIXME: if all platforms have these, do they really need #defines? */
-#define HAVE_STDINT_H 1
-#define HAVE_STRING_H 1
-
-#define WTF_CHANGES 1
-
-#ifdef __cplusplus
-#undef new
-#undef delete
-#include <wtf/FastMalloc.h>
-#endif
-
-// this breaks compilation of <QFontDatabase>, at least, so turn it off for now
-// Also generates errors on wx on Windows, because these functions
-// are used from wx headers.
-#if !PLATFORM(QT) && !PLATFORM(WX)
-#include <wtf/DisallowCType.h>
-#endif
diff --git a/JavaScriptCore/kjs/create_hash_table b/JavaScriptCore/kjs/create_hash_table
deleted file mode 100755
index 829a024..0000000
--- a/JavaScriptCore/kjs/create_hash_table
+++ /dev/null
@@ -1,242 +0,0 @@
-#! /usr/bin/perl -w
-#
-# Static Hashtable Generator
-#
-# (c) 2000-2002 by Harri Porten <porten@kde.org> and
-# David Faure <faure@kde.org>
-# Modified (c) 2004 by Nikolas Zimmermann <wildfox@kde.org>
-# Copyright (C) 2007 Apple Inc. All rights reserved.
-#
-# Part of the KJS library.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-use strict;
-
-my $file = $ARGV[0];
-shift;
-my $includelookup = 0;
-
-# Use -i as second argument to make it include "lookup.h"
-$includelookup = 1 if (defined($ARGV[0]) && $ARGV[0] eq "-i");
-
-# Use -n as second argument to make it use the third argument as namespace parameter ie. -n KDOM
-my $useNameSpace = $ARGV[1] if (defined($ARGV[0]) && $ARGV[0] eq "-n");
-
-print STDERR "Creating hashtable for $file\n";
-open(IN, $file) or die "No such file $file";
-
-my @keys = ();
-my @attrs = ();
-my @values = ();
-my @hashes = ();
-
-my $inside = 0;
-my $name;
-my $size;
-my $banner = 0;
-sub calcSize();
-sub output();
-sub jsc_ucfirst($);
-sub hashValue($);
-
-while (<IN>) {
- chomp;
- s/^\s+//;
- next if /^\#|^$/; # Comment or blank line. Do nothing.
- if (/^\@begin/ && !$inside) {
- if (/^\@begin\s*([:_\w]+)\s*\d*\s*$/) {
- $inside = 1;
- $name = $1;
- } else {
- print STDERR "WARNING: \@begin without table name, skipping $_\n";
- }
- } elsif (/^\@end\s*$/ && $inside) {
- calcSize();
- output();
-
- @keys = ();
- @attrs = ();
- @values = ();
- @hashes = ();
-
- $inside = 0;
- } elsif (/^(\S+)\s*(\S+)\s*([\w\|]*)\s*(\w*)\s*$/ && $inside) {
- my $key = $1;
- my $val = $2;
- my $att = $3;
- my $param = $4;
-
- push(@keys, $key);
- push(@attrs, length($att) > 0 ? $att : "0");
-
- if ($att =~ m/Function/) {
- push(@values, { "type" => "Function", "function" => $val, "params" => (length($param) ? $param : "") });
- #printf STDERR "WARNING: Number of arguments missing for $key/$val\n" if (length($param) == 0);
- } elsif (length($att)) {
- my $get = $val;
- my $put = !($att =~ m/ReadOnly/) ? "set" . jsc_ucfirst($val) : "0";
- push(@values, { "type" => "Property", "get" => $get, "put" => $put });
- } else {
- push(@values, { "type" => "Lexer", "value" => $val });
- }
- push(@hashes, hashValue($key));
- } elsif ($inside) {
- die "invalid data {" . $_ . "}";
- }
-}
-
-die "missing closing \@end" if ($inside);
-
-sub jsc_ucfirst($)
-{
- my ($value) = @_;
-
- if ($value =~ /js/) {
- $value =~ s/js/JS/;
- return $value;
- }
-
- return ucfirst($value);
-}
-
-
-sub ceilingToPowerOf2
-{
- my ($size) = @_;
-
- my $powerOf2 = 1;
- while ($size > $powerOf2) {
- $powerOf2 <<= 1;
- }
-
- return $powerOf2;
-}
-
-sub calcSize()
-{
-tableSizeLoop:
- for ($size = ceilingToPowerOf2(scalar @keys); ; $size += $size) {
- my @table = ();
- foreach my $key (@keys) {
- my $h = hashValue($key) % $size;
- next tableSizeLoop if $table[$h];
- $table[$h] = 1;
- }
- last;
- }
-}
-
-sub leftShift($$) {
- my ($value, $distance) = @_;
- return (($value << $distance) & 0xFFFFFFFF);
-}
-
-# Paul Hsieh's SuperFastHash
-# http://www.azillionmonkeys.com/qed/hash.html
-# Ported from UString..
-sub hashValue($) {
- my @chars = split(/ */, $_[0]);
-
- # This hash is designed to work on 16-bit chunks at a time. But since the normal case
- # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
- # were 16-bit chunks, which should give matching results
-
- my $EXP2_32 = 4294967296;
-
- my $hash = 0x9e3779b9;
- my $l = scalar @chars; #I wish this was in Ruby --- Maks
- my $rem = $l & 1;
- $l = $l >> 1;
-
- my $s = 0;
-
- # Main loop
- for (; $l > 0; $l--) {
- $hash += ord($chars[$s]);
- my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
- $hash = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
- $s += 2;
- $hash += $hash >> 11;
- $hash %= $EXP2_32;
- }
-
- # Handle end case
- if ($rem !=0) {
- $hash += ord($chars[$s]);
- $hash ^= (leftShift($hash, 11)% $EXP2_32);
- $hash += $hash >> 17;
- }
-
- # Force "avalanching" of final 127 bits
- $hash ^= leftShift($hash, 3);
- $hash += ($hash >> 5);
- $hash = ($hash% $EXP2_32);
- $hash ^= (leftShift($hash, 2)% $EXP2_32);
- $hash += ($hash >> 15);
- $hash = $hash% $EXP2_32;
- $hash ^= (leftShift($hash, 10)% $EXP2_32);
-
- # this avoids ever returning a hash code of 0, since that is used to
- # signal "hash not computed yet", using a value that is likely to be
- # effectively the same as 0 when the low bits are masked
- $hash = 0x80000000 if ($hash == 0);
-
- return $hash;
-}
-
-sub output() {
- if (!$banner) {
- $banner = 1;
- print "// Automatically generated from $file using $0. DO NOT EDIT!\n";
- }
-
- my $nameEntries = "${name}Values";
- $nameEntries =~ s/:/_/g;
-
- print "\n#include \"lookup.h\"\n" if ($includelookup);
- if ($useNameSpace) {
- print "\nnamespace ${useNameSpace} {\n";
- print "\nusing namespace JSC;\n";
- } else {
- print "\nnamespace JSC {\n";
- }
- my $count = scalar @keys + 1;
- print "\nstatic const struct HashTableValue ${nameEntries}\[$count\] = {\n";
- my $i = 0;
- foreach my $key (@keys) {
- my $firstValue = "";
- my $secondValue = "";
-
- if ($values[$i]{"type"} eq "Function") {
- $firstValue = $values[$i]{"function"};
- $secondValue = $values[$i]{"params"};
- } elsif ($values[$i]{"type"} eq "Property") {
- $firstValue = $values[$i]{"get"};
- $secondValue = $values[$i]{"put"};
- } elsif ($values[$i]{"type"} eq "Lexer") {
- $firstValue = $values[$i]{"value"};
- $secondValue = "0";
- }
- print " { \"$key\", $attrs[$i], (intptr_t)$firstValue, (intptr_t)$secondValue },\n";
- $i++;
- }
- print " { 0, 0, 0, 0 }\n";
- print "};\n\n";
- print "extern const struct HashTable $name = ";
- print "\{ ", $size - 1, ", $nameEntries, 0 \};\n\n";
- print "} // namespace\n";
-}
diff --git a/JavaScriptCore/kjs/dtoa.cpp b/JavaScriptCore/kjs/dtoa.cpp
deleted file mode 100644
index 2dc2cff..0000000
--- a/JavaScriptCore/kjs/dtoa.cpp
+++ /dev/null
@@ -1,2438 +0,0 @@
-/****************************************************************
- *
- * The author of this software is David M. Gay.
- *
- * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
- * Copyright (C) 2002, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- ***************************************************************/
-
-/* Please send bug reports to
- David M. Gay
- Bell Laboratories, Room 2C-463
- 600 Mountain Avenue
- Murray Hill, NJ 07974-0636
- U.S.A.
- dmg@bell-labs.com
- */
-
-/* On a machine with IEEE extended-precision registers, it is
- * necessary to specify double-precision (53-bit) rounding precision
- * before invoking strtod or dtoa. If the machine uses (the equivalent
- * of) Intel 80x87 arithmetic, the call
- * _control87(PC_53, MCW_PC);
- * does this with many compilers. Whether this or another call is
- * appropriate depends on the compiler; for this to work, it may be
- * necessary to #include "float.h" or another system-dependent header
- * file.
- */
-
-/* strtod for IEEE-arithmetic machines.
- *
- * This strtod returns a nearest machine number to the input decimal
- * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
- * broken by the IEEE round-even rule. Otherwise ties are broken by
- * biased rounding (add half and chop).
- *
- * Inspired loosely by William D. Clinger's paper "How to Read Floating
- * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- *
- * 1. We only require IEEE.
- * 2. We get by with floating-point arithmetic in a case that
- * Clinger missed -- when we're computing d * 10^n
- * for a small integer d and the integer n is not too
- * much larger than 22 (the maximum integer k for which
- * we can represent 10^k exactly), we may be able to
- * compute (d*10^k) * 10^(e-k) with just one roundoff.
- * 3. Rather than a bit-at-a-time adjustment of the binary
- * result in the hard case, we use floating-point
- * arithmetic to determine the adjustment to within
- * one bit; only in really hard cases do we need to
- * compute a second residual.
- * 4. Because of 3., we don't need a large table of powers of 10
- * for ten-to-e (just some small tables, e.g. of 10^k
- * for 0 <= k <= 22).
- */
-
-/*
- * #define IEEE_8087 for IEEE-arithmetic machines where the least
- * significant byte has the lowest address.
- * #define IEEE_MC68k for IEEE-arithmetic machines where the most
- * significant byte has the lowest address.
- * #define No_leftright to omit left-right logic in fast floating-point
- * computation of dtoa.
- * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- * and Honor_FLT_ROUNDS is not #defined.
- * #define Inaccurate_Divide for IEEE-format with correctly rounded
- * products but inaccurate quotients, e.g., for Intel i860.
- * #define USE_LONG_LONG on machines that have a "long long"
- * integer type (of >= 64 bits), and performance testing shows that
- * it is faster than 32-bit fallback (which is often not the case
- * on 32-bit machines). On such machines, you can #define Just_16
- * to store 16 bits per 32-bit int32_t when doing high-precision integer
- * arithmetic. Whether this speeds things up or slows things down
- * depends on the machine and the number being converted.
- * #define Bad_float_h if your system lacks a float.h or if it does not
- * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
- * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
- * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
- * Infinity and NaN (case insensitively). On some systems (e.g.,
- * some HP systems), it may be necessary to #define NAN_WORD0
- * appropriately -- to the most significant word of a quiet NaN.
- * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
- * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
- * strtod also accepts (case insensitively) strings of the form
- * NaN(x), where x is a string of hexadecimal digits and spaces;
- * if there is only one string of hexadecimal digits, it is taken
- * for the 52 fraction bits of the resulting NaN; if there are two
- * or more strings of hex digits, the first is for the high 20 bits,
- * the second and subsequent for the low 32 bits, with intervening
- * white space ignored; but if this results in none of the 52
- * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
- * and NAN_WORD1 are used instead.
- * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
- * avoids underflows on inputs whose result does not underflow.
- * If you #define NO_IEEE_Scale on a machine that uses IEEE-format
- * floating-point numbers and flushes underflows to zero rather
- * than implementing gradual underflow, then you must also #define
- * Sudden_Underflow.
- * #define YES_ALIAS to permit aliasing certain double values with
- * arrays of ULongs. This leads to slightly better code with
- * some compilers and was always used prior to 19990916, but it
- * is not strictly legal and can cause trouble with aggressively
- * optimizing compilers (e.g., gcc 2.95.1 under -O2).
- * #define SET_INEXACT if IEEE arithmetic is being used and extra
- * computation should be done to set the inexact flag when the
- * result is inexact and avoid setting inexact when the result
- * is exact. In this case, dtoa.c must be compiled in
- * an environment, perhaps provided by #include "dtoa.c" in a
- * suitable wrapper, that defines two functions,
- * int get_inexact(void);
- * void clear_inexact(void);
- * such that get_inexact() returns a nonzero value if the
- * inexact bit is already set, and clear_inexact() sets the
- * inexact bit to 0. When SET_INEXACT is #defined, strtod
- * also does extra computations to set the underflow and overflow
- * flags when appropriate (i.e., when the result is tiny and
- * inexact or when it is a numeric value rounded to +-infinity).
- * #define NO_ERRNO if strtod should not assign errno = ERANGE when
- * the result overflows to +-Infinity or underflows to 0.
- */
-
-#include "config.h"
-#include "dtoa.h"
-
-#include <errno.h>
-#include <float.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wtf/AlwaysInline.h>
-#include <wtf/Assertions.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/Threading.h>
-
-#if COMPILER(MSVC)
-#pragma warning(disable: 4244)
-#pragma warning(disable: 4245)
-#pragma warning(disable: 4554)
-#endif
-
-// ANDROID : || PLATFORM(MIDDLE_ENDIAN) added in #if statement below
-// for dtoa, MIDDLE_ENDIAN needs to be same as BIG_ENDIAN according to the following site
-// http://lists.debian.org/debian-arm/2003/11/msg00008.html
-#if PLATFORM(BIG_ENDIAN) || PLATFORM(MIDDLE_ENDIAN)
-#define IEEE_MC68k
-#elif PLATFORM(MIDDLE_ENDIAN)
-#define IEEE_ARM
-#else
-#define IEEE_8087
-#endif
-
-#define INFNAN_CHECK
-
-#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) != 1
-Exactly one of IEEE_8087, IEEE_ARM or IEEE_MC68k should be defined.
-#endif
-
-namespace JSC {
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-Mutex* s_dtoaP5Mutex;
-#endif
-
-typedef union { double d; uint32_t L[2]; } U;
-
-#ifdef YES_ALIAS
-#define dval(x) x
-#ifdef IEEE_8087
-#define word0(x) ((uint32_t*)&x)[1]
-#define word1(x) ((uint32_t*)&x)[0]
-#else
-#define word0(x) ((uint32_t*)&x)[0]
-#define word1(x) ((uint32_t*)&x)[1]
-#endif
-#else
-#ifdef IEEE_8087
-#define word0(x) ((U*)&x)->L[1]
-#define word1(x) ((U*)&x)->L[0]
-#else
-#define word0(x) ((U*)&x)->L[0]
-#define word1(x) ((U*)&x)->L[1]
-#endif
-#define dval(x) ((U*)&x)->d
-#endif
-
-/* The following definition of Storeinc is appropriate for MIPS processors.
- * An alternative that might be better on some machines is
- * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
- */
-#if defined(IEEE_8087) || defined(IEEE_ARM)
-#define Storeinc(a,b,c) (((unsigned short*)a)[1] = (unsigned short)b, ((unsigned short*)a)[0] = (unsigned short)c, a++)
-#else
-#define Storeinc(a,b,c) (((unsigned short*)a)[0] = (unsigned short)b, ((unsigned short*)a)[1] = (unsigned short)c, a++)
-#endif
-
-#define Exp_shift 20
-#define Exp_shift1 20
-#define Exp_msk1 0x100000
-#define Exp_msk11 0x100000
-#define Exp_mask 0x7ff00000
-#define P 53
-#define Bias 1023
-#define Emin (-1022)
-#define Exp_1 0x3ff00000
-#define Exp_11 0x3ff00000
-#define Ebits 11
-#define Frac_mask 0xfffff
-#define Frac_mask1 0xfffff
-#define Ten_pmax 22
-#define Bletch 0x10
-#define Bndry_mask 0xfffff
-#define Bndry_mask1 0xfffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 1
-#define Tiny0 0
-#define Tiny1 1
-#define Quick_max 14
-#define Int_max 14
-
-#if !defined(NO_IEEE_Scale)
-#undef Avoid_Underflow
-#define Avoid_Underflow
-#endif
-
-#if !defined(Flt_Rounds)
-#if defined(FLT_ROUNDS)
-#define Flt_Rounds FLT_ROUNDS
-#else
-#define Flt_Rounds 1
-#endif
-#endif /*Flt_Rounds*/
-
-
-#define rounded_product(a,b) a *= b
-#define rounded_quotient(a,b) a /= b
-
-#define Big0 (Frac_mask1 | Exp_msk1 * (DBL_MAX_EXP + Bias - 1))
-#define Big1 0xffffffff
-
-#ifndef Pack_32
-#define Pack_32
-#endif
-
-#if PLATFORM(PPC64) || PLATFORM(X86_64)
-// 64-bit emulation provided by the compiler is likely to be slower than dtoa own code on 32-bit hardware.
-#define USE_LONG_LONG
-#endif
-
-#ifndef USE_LONG_LONG
-#ifdef Just_16
-#undef Pack_32
-/* When Pack_32 is not defined, we store 16 bits per 32-bit int32_t.
- * This makes some inner loops simpler and sometimes saves work
- * during multiplications, but it often seems to make things slightly
- * slower. Hence the default is now to store 32 bits per int32_t.
- */
-#endif
-#endif
-
-#define Kmax 15
-
-struct Bigint {
- struct Bigint* next;
- int k, maxwds, sign, wds;
- uint32_t x[1];
-};
-
-static Bigint* Balloc(int k)
-{
- int x = 1 << k;
- Bigint* rv = (Bigint*)fastMalloc(sizeof(Bigint) + (x - 1)*sizeof(uint32_t));
- rv->k = k;
- rv->maxwds = x;
- rv->next = 0;
- rv->sign = rv->wds = 0;
-
- return rv;
-}
-
-static void Bfree(Bigint* v)
-{
- fastFree(v);
-}
-
-#define Bcopy(x, y) memcpy((char*)&x->sign, (char*)&y->sign, y->wds * sizeof(int32_t) + 2 * sizeof(int))
-
-static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */
-{
-#ifdef USE_LONG_LONG
- unsigned long long carry;
-#else
- uint32_t carry;
-#endif
-
- int wds = b->wds;
- uint32_t* x = b->x;
- int i = 0;
- carry = a;
- do {
-#ifdef USE_LONG_LONG
- unsigned long long y = *x * (unsigned long long)m + carry;
- carry = y >> 32;
- *x++ = (uint32_t)y & 0xffffffffUL;
-#else
-#ifdef Pack_32
- uint32_t xi = *x;
- uint32_t y = (xi & 0xffff) * m + carry;
- uint32_t z = (xi >> 16) * m + (y >> 16);
- carry = z >> 16;
- *x++ = (z << 16) + (y & 0xffff);
-#else
- uint32_t y = *x * m + carry;
- carry = y >> 16;
- *x++ = y & 0xffff;
-#endif
-#endif
- } while (++i < wds);
-
- if (carry) {
- if (wds >= b->maxwds) {
- Bigint* b1 = Balloc(b->k + 1);
- Bcopy(b1, b);
- Bfree(b);
- b = b1;
- }
- b->x[wds++] = (uint32_t)carry;
- b->wds = wds;
- }
- return b;
-}
-
-static Bigint* s2b(const char* s, int nd0, int nd, uint32_t y9)
-{
- int k;
- int32_t y;
- int32_t x = (nd + 8) / 9;
-
- for (k = 0, y = 1; x > y; y <<= 1, k++) { }
-#ifdef Pack_32
- Bigint* b = Balloc(k);
- b->x[0] = y9;
- b->wds = 1;
-#else
- Bigint* b = Balloc(k + 1);
- b->x[0] = y9 & 0xffff;
- b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
-#endif
-
- int i = 9;
- if (9 < nd0) {
- s += 9;
- do {
- b = multadd(b, 10, *s++ - '0');
- } while (++i < nd0);
- s++;
- } else
- s += 10;
- for (; i < nd; i++)
- b = multadd(b, 10, *s++ - '0');
- return b;
-}
-
-static int hi0bits(uint32_t x)
-{
- int k = 0;
-
- if (!(x & 0xffff0000)) {
- k = 16;
- x <<= 16;
- }
- if (!(x & 0xff000000)) {
- k += 8;
- x <<= 8;
- }
- if (!(x & 0xf0000000)) {
- k += 4;
- x <<= 4;
- }
- if (!(x & 0xc0000000)) {
- k += 2;
- x <<= 2;
- }
- if (!(x & 0x80000000)) {
- k++;
- if (!(x & 0x40000000))
- return 32;
- }
- return k;
-}
-
-static int lo0bits (uint32_t* y)
-{
- int k;
- uint32_t x = *y;
-
- if (x & 7) {
- if (x & 1)
- return 0;
- if (x & 2) {
- *y = x >> 1;
- return 1;
- }
- *y = x >> 2;
- return 2;
- }
- k = 0;
- if (!(x & 0xffff)) {
- k = 16;
- x >>= 16;
- }
- if (!(x & 0xff)) {
- k += 8;
- x >>= 8;
- }
- if (!(x & 0xf)) {
- k += 4;
- x >>= 4;
- }
- if (!(x & 0x3)) {
- k += 2;
- x >>= 2;
- }
- if (!(x & 1)) {
- k++;
- x >>= 1;
- if (!x & 1)
- return 32;
- }
- *y = x;
- return k;
-}
-
-static Bigint* i2b(int i)
-{
- Bigint* b;
-
- b = Balloc(1);
- b->x[0] = i;
- b->wds = 1;
- return b;
-}
-
-static Bigint* mult(Bigint* a, Bigint* b)
-{
- Bigint* c;
- int k, wa, wb, wc;
- uint32_t *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
- uint32_t y;
-#ifdef USE_LONG_LONG
- unsigned long long carry, z;
-#else
- uint32_t carry, z;
-#endif
-
- if (a->wds < b->wds) {
- c = a;
- a = b;
- b = c;
- }
- k = a->k;
- wa = a->wds;
- wb = b->wds;
- wc = wa + wb;
- if (wc > a->maxwds)
- k++;
- c = Balloc(k);
- for (x = c->x, xa = x + wc; x < xa; x++)
- *x = 0;
- xa = a->x;
- xae = xa + wa;
- xb = b->x;
- xbe = xb + wb;
- xc0 = c->x;
-#ifdef USE_LONG_LONG
- for (; xb < xbe; xc0++) {
- if ((y = *xb++)) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = *x++ * (unsigned long long)y + *xc + carry;
- carry = z >> 32;
- *xc++ = (uint32_t)z & 0xffffffffUL;
- } while (x < xae);
- *xc = (uint32_t)carry;
- }
- }
-#else
-#ifdef Pack_32
- for (; xb < xbe; xb++, xc0++) {
- if ((y = *xb & 0xffff)) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
- carry = z >> 16;
- uint32_t z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
- carry = z2 >> 16;
- Storeinc(xc, z2, z);
- } while (x < xae);
- *xc = carry;
- }
- if ((y = *xb >> 16)) {
- x = xa;
- xc = xc0;
- carry = 0;
- uint32_t z2 = *xc;
- do {
- z = (*x & 0xffff) * y + (*xc >> 16) + carry;
- carry = z >> 16;
- Storeinc(xc, z, z2);
- z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
- carry = z2 >> 16;
- } while (x < xae);
- *xc = z2;
- }
- }
-#else
- for(; xb < xbe; xc0++) {
- if ((y = *xb++)) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = *x++ * y + *xc + carry;
- carry = z >> 16;
- *xc++ = z & 0xffff;
- } while (x < xae);
- *xc = carry;
- }
- }
-#endif
-#endif
- for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) { }
- c->wds = wc;
- return c;
-}
-
-static Bigint* p5s;
-static int p5s_count;
-
-static Bigint* pow5mult(Bigint* b, int k)
-{
- static int p05[3] = { 5, 25, 125 };
-
- if (int i = k & 3)
- b = multadd(b, p05[i - 1], 0);
-
- if (!(k >>= 2))
- return b;
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
- s_dtoaP5Mutex->lock();
-#endif
- Bigint* p5 = p5s;
- if (!p5) {
- /* first time */
- p5 = p5s = i2b(625);
- p5s_count = 1;
- }
- int p5s_count_local = p5s_count;
-#if ENABLE(JSC_MULTIPLE_THREADS)
- s_dtoaP5Mutex->unlock();
-#endif
- int p5s_used = 0;
-
- for (;;) {
- if (k & 1) {
- Bigint* b1 = mult(b, p5);
- Bfree(b);
- b = b1;
- }
- if (!(k >>= 1))
- break;
-
- if (++p5s_used == p5s_count_local) {
-#if ENABLE(JSC_MULTIPLE_THREADS)
- s_dtoaP5Mutex->lock();
-#endif
- if (p5s_used == p5s_count) {
- ASSERT(!p5->next);
- p5->next = mult(p5, p5);
- ++p5s_count;
- }
-
- p5s_count_local = p5s_count;
-#if ENABLE(JSC_MULTIPLE_THREADS)
- s_dtoaP5Mutex->unlock();
-#endif
- }
- p5 = p5->next;
- }
-
- return b;
-}
-
-static Bigint* lshift(Bigint* b, int k)
-{
- Bigint* result = b;
-
-#ifdef Pack_32
- int n = k >> 5;
-#else
- int n = k >> 4;
-#endif
-
- int k1 = b->k;
- int n1 = n + b->wds + 1;
- for (int i = b->maxwds; n1 > i; i <<= 1)
- k1++;
- if (b->k < k1)
- result = Balloc(k1);
-
- const uint32_t* srcStart = b->x;
- uint32_t* dstStart = result->x;
- const uint32_t* src = srcStart + b->wds - 1;
- uint32_t* dst = dstStart + n1 - 1;
-#ifdef Pack_32
- if (k &= 0x1f) {
- uint32_t hiSubword = 0;
- int s = 32 - k;
- for (; src >= srcStart; --src) {
- *dst-- = hiSubword | *src >> s;
- hiSubword = *src << k;
- }
- *dst = hiSubword;
- ASSERT(dst == dstStart + n);
- result->wds = b->wds + n + (result->x[n1 - 1] != 0);
- }
-#else
- if (k &= 0xf) {
- uint32_t hiSubword = 0;
- int s = 16 - k;
- for (; src >= srcStart; --src) {
- *dst-- = hiSubword | *src >> s;
- hiSubword = (*src << k) & 0xffff;
- }
- *dst = hiSubword;
- ASSERT(dst == dstStart + n);
- result->wds = b->wds + n + (result->x[n1 - 1] != 0);
- }
- #endif
- else {
- do {
- *--dst = *src--;
- } while (src >= srcStart);
- result->wds = b->wds + n;
- }
- for (dst = dstStart + n; dst != dstStart; )
- *--dst = 0;
-
- if (result != b)
- Bfree(b);
- return result;
-}
-
-static int cmp(Bigint* a, Bigint* b)
-{
- uint32_t *xa, *xa0, *xb, *xb0;
- int i, j;
-
- i = a->wds;
- j = b->wds;
- ASSERT(i <= 1 || a->x[i - 1]);
- ASSERT(j <= 1 || b->x[j - 1]);
- if (i -= j)
- return i;
- xa0 = a->x;
- xa = xa0 + j;
- xb0 = b->x;
- xb = xb0 + j;
- for (;;) {
- if (*--xa != *--xb)
- return *xa < *xb ? -1 : 1;
- if (xa <= xa0)
- break;
- }
- return 0;
-}
-
-static Bigint* diff(Bigint* a, Bigint* b)
-{
- Bigint* c;
- int i, wa, wb;
- uint32_t *xa, *xae, *xb, *xbe, *xc;
-
- i = cmp(a,b);
- if (!i) {
- c = Balloc(0);
- c->wds = 1;
- c->x[0] = 0;
- return c;
- }
- if (i < 0) {
- c = a;
- a = b;
- b = c;
- i = 1;
- } else
- i = 0;
- c = Balloc(a->k);
- c->sign = i;
- wa = a->wds;
- xa = a->x;
- xae = xa + wa;
- wb = b->wds;
- xb = b->x;
- xbe = xb + wb;
- xc = c->x;
-#ifdef USE_LONG_LONG
- unsigned long long borrow = 0;
- do {
- unsigned long long y = (unsigned long long)*xa++ - *xb++ - borrow;
- borrow = y >> 32 & (uint32_t)1;
- *xc++ = (uint32_t)y & 0xffffffffUL;
- } while (xb < xbe);
- while (xa < xae) {
- unsigned long long y = *xa++ - borrow;
- borrow = y >> 32 & (uint32_t)1;
- *xc++ = (uint32_t)y & 0xffffffffUL;
- }
-#else
- uint32_t borrow = 0;
-#ifdef Pack_32
- do {
- uint32_t y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- uint32_t z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(xc, z, y);
- } while (xb < xbe);
- while (xa < xae) {
- uint32_t y = (*xa & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- uint32_t z = (*xa++ >> 16) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(xc, z, y);
- }
-#else
- do {
- uint32_t y = *xa++ - *xb++ - borrow;
- borrow = (y & 0x10000) >> 16;
- *xc++ = y & 0xffff;
- } while (xb < xbe);
- while (xa < xae) {
- uint32_t y = *xa++ - borrow;
- borrow = (y & 0x10000) >> 16;
- *xc++ = y & 0xffff;
- }
-#endif
-#endif
- while (!*--xc)
- wa--;
- c->wds = wa;
- return c;
-}
-
-static double ulp(double x)
-{
- register int32_t L;
- double a;
-
- L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
- if (L > 0) {
-#endif
-#endif
- word0(a) = L;
- word1(a) = 0;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
- } else {
- L = -L >> Exp_shift;
- if (L < Exp_shift) {
- word0(a) = 0x80000 >> L;
- word1(a) = 0;
- } else {
- word0(a) = 0;
- L -= Exp_shift;
- word1(a) = L >= 31 ? 1 : 1 << 31 - L;
- }
- }
-#endif
-#endif
- return dval(a);
-}
-
-static double b2d(Bigint* a, int* e)
-{
- uint32_t* xa;
- uint32_t* xa0;
- uint32_t w;
- uint32_t y;
- uint32_t z;
- int k;
- double d;
-
-#define d0 word0(d)
-#define d1 word1(d)
-
- xa0 = a->x;
- xa = xa0 + a->wds;
- y = *--xa;
- ASSERT(y);
- k = hi0bits(y);
- *e = 32 - k;
-#ifdef Pack_32
- if (k < Ebits) {
- d0 = Exp_1 | y >> Ebits - k;
- w = xa > xa0 ? *--xa : 0;
- d1 = y << (32 - Ebits) + k | w >> Ebits - k;
- goto ret_d;
- }
- z = xa > xa0 ? *--xa : 0;
- if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> 32 - k;
- y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> 32 - k;
- } else {
- d0 = Exp_1 | y;
- d1 = z;
- }
-#else
- if (k < Ebits + 16) {
- z = xa > xa0 ? *--xa : 0;
- d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
- w = xa > xa0 ? *--xa : 0;
- y = xa > xa0 ? *--xa : 0;
- d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
- goto ret_d;
- }
- z = xa > xa0 ? *--xa : 0;
- w = xa > xa0 ? *--xa : 0;
- k -= Ebits + 16;
- d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
- y = xa > xa0 ? *--xa : 0;
- d1 = w << k + 16 | y << k;
-#endif
-ret_d:
-#undef d0
-#undef d1
- return dval(d);
-}
-
-static Bigint* d2b(double d, int* e, int* bits)
-{
- Bigint* b;
- int de, k;
- uint32_t *x, y, z;
-#ifndef Sudden_Underflow
- int i;
-#endif
-#define d0 word0(d)
-#define d1 word1(d)
-
-#ifdef Pack_32
- b = Balloc(1);
-#else
- b = Balloc(2);
-#endif
- x = b->x;
-
- z = d0 & Frac_mask;
- d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
-#ifdef Sudden_Underflow
- de = (int)(d0 >> Exp_shift);
-#else
- if ((de = (int)(d0 >> Exp_shift)))
- z |= Exp_msk1;
-#endif
-#ifdef Pack_32
- if ((y = d1)) {
- if ((k = lo0bits(&y))) {
- x[0] = y | z << 32 - k;
- z >>= k;
- } else
- x[0] = y;
-#ifndef Sudden_Underflow
- i =
-#endif
- b->wds = (x[1] = z) ? 2 : 1;
- } else {
- k = lo0bits(&z);
- x[0] = z;
-#ifndef Sudden_Underflow
- i =
-#endif
- b->wds = 1;
- k += 32;
- }
-#else
- if ((y = d1)) {
- if ((k = lo0bits(&y))) {
- if (k >= 16) {
- x[0] = y | z << 32 - k & 0xffff;
- x[1] = z >> k - 16 & 0xffff;
- x[2] = z >> k;
- i = 2;
- } else {
- x[0] = y & 0xffff;
- x[1] = y >> 16 | z << 16 - k & 0xffff;
- x[2] = z >> k & 0xffff;
- x[3] = z >> k + 16;
- i = 3;
- }
- } else {
- x[0] = y & 0xffff;
- x[1] = y >> 16;
- x[2] = z & 0xffff;
- x[3] = z >> 16;
- i = 3;
- }
- } else {
- k = lo0bits(&z);
- if (k >= 16) {
- x[0] = z;
- i = 0;
- } else {
- x[0] = z & 0xffff;
- x[1] = z >> 16;
- i = 1;
- }
- k += 32;
- } while (!x[i])
- --i;
- b->wds = i + 1;
-#endif
-#ifndef Sudden_Underflow
- if (de) {
-#endif
- *e = de - Bias - (P - 1) + k;
- *bits = P - k;
-#ifndef Sudden_Underflow
- } else {
- *e = de - Bias - (P - 1) + 1 + k;
-#ifdef Pack_32
- *bits = (32 * i) - hi0bits(x[i - 1]);
-#else
- *bits = (i + 2) * 16 - hi0bits(x[i]);
-#endif
- }
-#endif
- return b;
-}
-#undef d0
-#undef d1
-
-static double ratio(Bigint* a, Bigint* b)
-{
- double da, db;
- int k, ka, kb;
-
- dval(da) = b2d(a, &ka);
- dval(db) = b2d(b, &kb);
-#ifdef Pack_32
- k = ka - kb + 32 * (a->wds - b->wds);
-#else
- k = ka - kb + 16 * (a->wds - b->wds);
-#endif
- if (k > 0)
- word0(da) += k * Exp_msk1;
- else {
- k = -k;
- word0(db) += k * Exp_msk1;
- }
- return dval(da) / dval(db);
-}
-
-static const double tens[] = {
- 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
- 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
- 1e20, 1e21, 1e22
-};
-
-static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
-static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
-#ifdef Avoid_Underflow
- 9007199254740992. * 9007199254740992.e-256
- /* = 2^106 * 1e-53 */
-#else
- 1e-256
-#endif
-};
-
-/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
-/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
-#define Scale_Bit 0x10
-#define n_bigtens 5
-
-#if defined(INFNAN_CHECK)
-
-#ifndef NAN_WORD0
-#define NAN_WORD0 0x7ff80000
-#endif
-
-#ifndef NAN_WORD1
-#define NAN_WORD1 0
-#endif
-
-static int match(const char** sp, const char* t)
-{
- int c, d;
- const char* s = *sp;
-
- while ((d = *t++)) {
- if ((c = *++s) >= 'A' && c <= 'Z')
- c += 'a' - 'A';
- if (c != d)
- return 0;
- }
- *sp = s + 1;
- return 1;
-}
-
-#ifndef No_Hex_NaN
-static void hexnan(double* rvp, const char** sp)
-{
- uint32_t c, x[2];
- const char* s;
- int havedig, udx0, xshift;
-
- x[0] = x[1] = 0;
- havedig = xshift = 0;
- udx0 = 1;
- s = *sp;
- while ((c = *(const unsigned char*)++s)) {
- if (c >= '0' && c <= '9')
- c -= '0';
- else if (c >= 'a' && c <= 'f')
- c += 10 - 'a';
- else if (c >= 'A' && c <= 'F')
- c += 10 - 'A';
- else if (c <= ' ') {
- if (udx0 && havedig) {
- udx0 = 0;
- xshift = 1;
- }
- continue;
- } else if (/*(*/ c == ')' && havedig) {
- *sp = s + 1;
- break;
- } else
- return; /* invalid form: don't change *sp */
- havedig = 1;
- if (xshift) {
- xshift = 0;
- x[0] = x[1];
- x[1] = 0;
- }
- if (udx0)
- x[0] = (x[0] << 4) | (x[1] >> 28);
- x[1] = (x[1] << 4) | c;
- }
- if ((x[0] &= 0xfffff) || x[1]) {
- word0(*rvp) = Exp_mask | x[0];
- word1(*rvp) = x[1];
- }
-}
-#endif /*No_Hex_NaN*/
-#endif /* INFNAN_CHECK */
-
-double strtod(const char* s00, char** se)
-{
-#ifdef Avoid_Underflow
- int scale;
-#endif
- int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
- e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
- const char *s, *s0, *s1;
- double aadj, aadj1, adj, rv, rv0;
- int32_t L;
- uint32_t y, z;
- Bigint *bb = NULL, *bb1 = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL;
-#ifdef SET_INEXACT
- int inexact, oldinexact;
-#endif
-
- sign = nz0 = nz = 0;
- dval(rv) = 0.;
- for (s = s00; ; s++)
- switch (*s) {
- case '-':
- sign = 1;
- /* no break */
- case '+':
- if (*++s)
- goto break2;
- /* no break */
- case 0:
- goto ret0;
- case '\t':
- case '\n':
- case '\v':
- case '\f':
- case '\r':
- case ' ':
- continue;
- default:
- goto break2;
- }
-break2:
- if (*s == '0') {
- nz0 = 1;
- while (*++s == '0') { }
- if (!*s)
- goto ret;
- }
- s0 = s;
- y = z = 0;
- for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
- if (nd < 9)
- y = (10 * y) + c - '0';
- else if (nd < 16)
- z = (10 * z) + c - '0';
- nd0 = nd;
- if (c == '.') {
- c = *++s;
- if (!nd) {
- for (; c == '0'; c = *++s)
- nz++;
- if (c > '0' && c <= '9') {
- s0 = s;
- nf += nz;
- nz = 0;
- goto have_dig;
- }
- goto dig_done;
- }
- for (; c >= '0' && c <= '9'; c = *++s) {
-have_dig:
- nz++;
- if (c -= '0') {
- nf += nz;
- for (i = 1; i < nz; i++)
- if (nd++ < 9)
- y *= 10;
- else if (nd <= DBL_DIG + 1)
- z *= 10;
- if (nd++ < 9)
- y = (10 * y) + c;
- else if (nd <= DBL_DIG + 1)
- z = (10 * z) + c;
- nz = 0;
- }
- }
- }
-dig_done:
- e = 0;
- if (c == 'e' || c == 'E') {
- if (!nd && !nz && !nz0) {
- goto ret0;
- }
- s00 = s;
- esign = 0;
- switch (c = *++s) {
- case '-':
- esign = 1;
- case '+':
- c = *++s;
- }
- if (c >= '0' && c <= '9') {
- while (c == '0')
- c = *++s;
- if (c > '0' && c <= '9') {
- L = c - '0';
- s1 = s;
- while ((c = *++s) >= '0' && c <= '9')
- L = (10 * L) + c - '0';
- if (s - s1 > 8 || L > 19999)
- /* Avoid confusion from exponents
- * so large that e might overflow.
- */
- e = 19999; /* safe for 16 bit ints */
- else
- e = (int)L;
- if (esign)
- e = -e;
- } else
- e = 0;
- } else
- s = s00;
- }
- if (!nd) {
- if (!nz && !nz0) {
-#ifdef INFNAN_CHECK
- /* Check for Nan and Infinity */
- switch(c) {
- case 'i':
- case 'I':
- if (match(&s,"nf")) {
- --s;
- if (!match(&s,"inity"))
- ++s;
- word0(rv) = 0x7ff00000;
- word1(rv) = 0;
- goto ret;
- }
- break;
- case 'n':
- case 'N':
- if (match(&s, "an")) {
- word0(rv) = NAN_WORD0;
- word1(rv) = NAN_WORD1;
-#ifndef No_Hex_NaN
- if (*s == '(') /*)*/
- hexnan(&rv, &s);
-#endif
- goto ret;
- }
- }
-#endif /* INFNAN_CHECK */
-ret0:
- s = s00;
- sign = 0;
- }
- goto ret;
- }
- e1 = e -= nf;
-
- /* Now we have nd0 digits, starting at s0, followed by a
- * decimal point, followed by nd-nd0 digits. The number we're
- * after is the integer represented by those digits times
- * 10**e */
-
- if (!nd0)
- nd0 = nd;
- k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
- if (k > 9) {
-#ifdef SET_INEXACT
- if (k > DBL_DIG)
- oldinexact = get_inexact();
-#endif
- dval(rv) = tens[k - 9] * dval(rv) + z;
- }
- bd0 = 0;
- if (nd <= DBL_DIG && Flt_Rounds == 1) {
- if (!e)
- goto ret;
- if (e > 0) {
- if (e <= Ten_pmax) {
- /* rv = */ rounded_product(dval(rv), tens[e]);
- goto ret;
- }
- i = DBL_DIG - nd;
- if (e <= Ten_pmax + i) {
- /* A fancier test would sometimes let us do
- * this for larger i values.
- */
- e -= i;
- dval(rv) *= tens[i];
- /* rv = */ rounded_product(dval(rv), tens[e]);
- goto ret;
- }
- }
-#ifndef Inaccurate_Divide
- else if (e >= -Ten_pmax) {
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
- goto ret;
- }
-#endif
- }
- e1 += nd - k;
-
-#ifdef SET_INEXACT
- inexact = 1;
- if (k <= DBL_DIG)
- oldinexact = get_inexact();
-#endif
-#ifdef Avoid_Underflow
- scale = 0;
-#endif
-
- /* Get starting approximation = rv * 10**e1 */
-
- if (e1 > 0) {
- if ((i = e1 & 15))
- dval(rv) *= tens[i];
- if (e1 &= ~15) {
- if (e1 > DBL_MAX_10_EXP) {
-ovfl:
-#ifndef NO_ERRNO
- errno = ERANGE;
-#endif
- /* Can't trust HUGE_VAL */
- word0(rv) = Exp_mask;
- word1(rv) = 0;
-#ifdef SET_INEXACT
- /* set overflow bit */
- dval(rv0) = 1e300;
- dval(rv0) *= dval(rv0);
-#endif
- if (bd0)
- goto retfree;
- goto ret;
- }
- e1 >>= 4;
- for (j = 0; e1 > 1; j++, e1 >>= 1)
- if (e1 & 1)
- dval(rv) *= bigtens[j];
- /* The last multiplication could overflow. */
- word0(rv) -= P * Exp_msk1;
- dval(rv) *= bigtens[j];
- if ((z = word0(rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P))
- goto ovfl;
- if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) {
- /* set to largest number */
- /* (Can't trust DBL_MAX) */
- word0(rv) = Big0;
- word1(rv) = Big1;
- } else
- word0(rv) += P * Exp_msk1;
- }
- } else if (e1 < 0) {
- e1 = -e1;
- if ((i = e1 & 15))
- dval(rv) /= tens[i];
- if (e1 >>= 4) {
- if (e1 >= 1 << n_bigtens)
- goto undfl;
-#ifdef Avoid_Underflow
- if (e1 & Scale_Bit)
- scale = 2 * P;
- for (j = 0; e1 > 0; j++, e1 >>= 1)
- if (e1 & 1)
- dval(rv) *= tinytens[j];
- if (scale && (j = (2 * P) + 1 - ((word0(rv) & Exp_mask) >> Exp_shift)) > 0) {
- /* scaled rv is denormal; zap j low bits */
- if (j >= 32) {
- word1(rv) = 0;
- if (j >= 53)
- word0(rv) = (P + 2) * Exp_msk1;
- else
- word0(rv) &= 0xffffffff << j - 32;
- } else
- word1(rv) &= 0xffffffff << j;
- }
-#else
- for (j = 0; e1 > 1; j++, e1 >>= 1)
- if (e1 & 1)
- dval(rv) *= tinytens[j];
- /* The last multiplication could underflow. */
- dval(rv0) = dval(rv);
- dval(rv) *= tinytens[j];
- if (!dval(rv)) {
- dval(rv) = 2. * dval(rv0);
- dval(rv) *= tinytens[j];
-#endif
- if (!dval(rv)) {
-undfl:
- dval(rv) = 0.;
-#ifndef NO_ERRNO
- errno = ERANGE;
-#endif
- if (bd0)
- goto retfree;
- goto ret;
- }
-#ifndef Avoid_Underflow
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
- /* The refinement below will clean
- * this approximation up.
- */
- }
-#endif
- }
- }
-
- /* Now the hard part -- adjusting rv to the correct value.*/
-
- /* Put digits into bd: true value = bd * 10^e */
-
- bd0 = s2b(s0, nd0, nd, y);
-
- for (;;) {
- bd = Balloc(bd0->k);
- Bcopy(bd, bd0);
- bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
- bs = i2b(1);
-
- if (e >= 0) {
- bb2 = bb5 = 0;
- bd2 = bd5 = e;
- } else {
- bb2 = bb5 = -e;
- bd2 = bd5 = 0;
- }
- if (bbe >= 0)
- bb2 += bbe;
- else
- bd2 -= bbe;
- bs2 = bb2;
-#ifdef Avoid_Underflow
- j = bbe - scale;
- i = j + bbbits - 1; /* logb(rv) */
- if (i < Emin) /* denormal */
- j += P - Emin;
- else
- j = P + 1 - bbbits;
-#else /*Avoid_Underflow*/
-#ifdef Sudden_Underflow
- j = P + 1 - bbbits;
-#else /*Sudden_Underflow*/
- j = bbe;
- i = j + bbbits - 1; /* logb(rv) */
- if (i < Emin) /* denormal */
- j += P - Emin;
- else
- j = P + 1 - bbbits;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- bb2 += j;
- bd2 += j;
-#ifdef Avoid_Underflow
- bd2 += scale;
-#endif
- i = bb2 < bd2 ? bb2 : bd2;
- if (i > bs2)
- i = bs2;
- if (i > 0) {
- bb2 -= i;
- bd2 -= i;
- bs2 -= i;
- }
- if (bb5 > 0) {
- bs = pow5mult(bs, bb5);
- bb1 = mult(bs, bb);
- Bfree(bb);
- bb = bb1;
- }
- if (bb2 > 0)
- bb = lshift(bb, bb2);
- if (bd5 > 0)
- bd = pow5mult(bd, bd5);
- if (bd2 > 0)
- bd = lshift(bd, bd2);
- if (bs2 > 0)
- bs = lshift(bs, bs2);
- delta = diff(bb, bd);
- dsign = delta->sign;
- delta->sign = 0;
- i = cmp(delta, bs);
-
- if (i < 0) {
- /* Error is less than half an ulp -- check for
- * special case of mantissa a power of two.
- */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask
-#ifdef Avoid_Underflow
- || (word0(rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1
-#else
- || (word0(rv) & Exp_mask) <= Exp_msk1
-#endif
- ) {
-#ifdef SET_INEXACT
- if (!delta->x[0] && delta->wds <= 1)
- inexact = 0;
-#endif
- break;
- }
- if (!delta->x[0] && delta->wds <= 1) {
- /* exact result */
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- break;
- }
- delta = lshift(delta,Log2P);
- if (cmp(delta, bs) > 0)
- goto drop_down;
- break;
- }
- if (i == 0) {
- /* exactly half-way between */
- if (dsign) {
- if ((word0(rv) & Bndry_mask1) == Bndry_mask1
- && word1(rv) == (
-#ifdef Avoid_Underflow
- (scale && (y = word0(rv) & Exp_mask) <= 2 * P * Exp_msk1)
- ? (0xffffffff & (0xffffffff << (2 * P + 1 - (y >> Exp_shift)))) :
-#endif
- 0xffffffff)) {
- /*boundary case -- increment exponent*/
- word0(rv) = (word0(rv) & Exp_mask) + Exp_msk1;
- word1(rv) = 0;
-#ifdef Avoid_Underflow
- dsign = 0;
-#endif
- break;
- }
- } else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
-drop_down:
- /* boundary case -- decrement exponent */
-#ifdef Sudden_Underflow /*{{*/
- L = word0(rv) & Exp_mask;
-#ifdef Avoid_Underflow
- if (L <= (scale ? (2 * P + 1) * Exp_msk1 : Exp_msk1))
-#else
- if (L <= Exp_msk1)
-#endif /*Avoid_Underflow*/
- goto undfl;
- L -= Exp_msk1;
-#else /*Sudden_Underflow}{*/
-#ifdef Avoid_Underflow
- if (scale) {
- L = word0(rv) & Exp_mask;
- if (L <= (2 * P + 1) * Exp_msk1) {
- if (L > (P + 2) * Exp_msk1)
- /* round even ==> */
- /* accept rv */
- break;
- /* rv = smallest denormal */
- goto undfl;
- }
- }
-#endif /*Avoid_Underflow*/
- L = (word0(rv) & Exp_mask) - Exp_msk1;
-#endif /*Sudden_Underflow}}*/
- word0(rv) = L | Bndry_mask1;
- word1(rv) = 0xffffffff;
- break;
- }
- if (!(word1(rv) & LSB))
- break;
- if (dsign)
- dval(rv) += ulp(dval(rv));
- else {
- dval(rv) -= ulp(dval(rv));
-#ifndef Sudden_Underflow
- if (!dval(rv))
- goto undfl;
-#endif
- }
-#ifdef Avoid_Underflow
- dsign = 1 - dsign;
-#endif
- break;
- }
- if ((aadj = ratio(delta, bs)) <= 2.) {
- if (dsign)
- aadj = aadj1 = 1.;
- else if (word1(rv) || word0(rv) & Bndry_mask) {
-#ifndef Sudden_Underflow
- if (word1(rv) == Tiny1 && !word0(rv))
- goto undfl;
-#endif
- aadj = 1.;
- aadj1 = -1.;
- } else {
- /* special case -- power of FLT_RADIX to be */
- /* rounded down... */
-
- if (aadj < 2. / FLT_RADIX)
- aadj = 1. / FLT_RADIX;
- else
- aadj *= 0.5;
- aadj1 = -aadj;
- }
- } else {
- aadj *= 0.5;
- aadj1 = dsign ? aadj : -aadj;
-#ifdef Check_FLT_ROUNDS
- switch (Rounding) {
- case 2: /* towards +infinity */
- aadj1 -= 0.5;
- break;
- case 0: /* towards 0 */
- case 3: /* towards -infinity */
- aadj1 += 0.5;
- }
-#else
- if (Flt_Rounds == 0)
- aadj1 += 0.5;
-#endif /*Check_FLT_ROUNDS*/
- }
- y = word0(rv) & Exp_mask;
-
- /* Check for overflow */
-
- if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) {
- dval(rv0) = dval(rv);
- word0(rv) -= P * Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
- if ((word0(rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) {
- if (word0(rv0) == Big0 && word1(rv0) == Big1)
- goto ovfl;
- word0(rv) = Big0;
- word1(rv) = Big1;
- goto cont;
- } else
- word0(rv) += P * Exp_msk1;
- } else {
-#ifdef Avoid_Underflow
- if (scale && y <= 2 * P * Exp_msk1) {
- if (aadj <= 0x7fffffff) {
- if ((z = (uint32_t)aadj) <= 0)
- z = 1;
- aadj = z;
- aadj1 = dsign ? aadj : -aadj;
- }
- word0(aadj1) += (2 * P + 1) * Exp_msk1 - y;
- }
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
-#else
-#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P * Exp_msk1) {
- dval(rv0) = dval(rv);
- word0(rv) += P * Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
- if ((word0(rv) & Exp_mask) <= P * Exp_msk1)
- {
- if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1)
- goto undfl;
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
- goto cont;
- }
- else
- word0(rv) -= P * Exp_msk1;
- } else {
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
- }
-#else /*Sudden_Underflow*/
- /* Compute adj so that the IEEE rounding rules will
- * correctly round rv + adj in some half-way cases.
- * If rv * ulp(rv) is denormalized (i.e.,
- * y <= (P - 1) * Exp_msk1), we must adjust aadj to avoid
- * trouble from bits lost to denormalization;
- * example: 1.2e-307 .
- */
- if (y <= (P - 1) * Exp_msk1 && aadj > 1.) {
- aadj1 = (double)(int)(aadj + 0.5);
- if (!dsign)
- aadj1 = -aadj1;
- }
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- }
- z = word0(rv) & Exp_mask;
-#ifndef SET_INEXACT
-#ifdef Avoid_Underflow
- if (!scale)
-#endif
- if (y == z) {
- /* Can we stop now? */
- L = (int32_t)aadj;
- aadj -= L;
- /* The tolerances below are conservative. */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
- if (aadj < .4999999 || aadj > .5000001)
- break;
- } else if (aadj < .4999999 / FLT_RADIX)
- break;
- }
-#endif
-cont:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(delta);
- }
-#ifdef SET_INEXACT
- if (inexact) {
- if (!oldinexact) {
- word0(rv0) = Exp_1 + (70 << Exp_shift);
- word1(rv0) = 0;
- dval(rv0) += 1.;
- }
- } else if (!oldinexact)
- clear_inexact();
-#endif
-#ifdef Avoid_Underflow
- if (scale) {
- word0(rv0) = Exp_1 - 2 * P * Exp_msk1;
- word1(rv0) = 0;
- dval(rv) *= dval(rv0);
-#ifndef NO_ERRNO
- /* try to avoid the bug of testing an 8087 register value */
- if (word0(rv) == 0 && word1(rv) == 0)
- errno = ERANGE;
-#endif
- }
-#endif /* Avoid_Underflow */
-#ifdef SET_INEXACT
- if (inexact && !(word0(rv) & Exp_mask)) {
- /* set underflow bit */
- dval(rv0) = 1e-300;
- dval(rv0) *= dval(rv0);
- }
-#endif
-retfree:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(bd0);
- Bfree(delta);
-ret:
- if (se)
- *se = (char*)s;
- return sign ? -dval(rv) : dval(rv);
-}
-
-static int quorem(Bigint* b, Bigint* S)
-{
- int n;
- uint32_t *bx, *bxe, q, *sx, *sxe;
-#ifdef USE_LONG_LONG
- unsigned long long borrow, carry, y, ys;
-#else
- uint32_t borrow, carry, y, ys;
-#ifdef Pack_32
- uint32_t si, z, zs;
-#endif
-#endif
-
- n = S->wds;
- ASSERT_WITH_MESSAGE(b->wds <= n, "oversize b in quorem");
- if (b->wds < n)
- return 0;
- sx = S->x;
- sxe = sx + --n;
- bx = b->x;
- bxe = bx + n;
- q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
- ASSERT_WITH_MESSAGE(q <= 9, "oversized quotient in quorem");
- if (q) {
- borrow = 0;
- carry = 0;
- do {
-#ifdef USE_LONG_LONG
- ys = *sx++ * (unsigned long long)q + carry;
- carry = ys >> 32;
- y = *bx - (ys & 0xffffffffUL) - borrow;
- borrow = y >> 32 & (uint32_t)1;
- *bx++ = (uint32_t)y & 0xffffffffUL;
-#else
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) * q + carry;
- zs = (si >> 16) * q + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*bx >> 16) - (zs & 0xffff) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(bx, z, y);
-#else
- ys = *sx++ * q + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- *bx++ = y & 0xffff;
-#endif
-#endif
- } while (sx <= sxe);
- if (!*bxe) {
- bx = b->x;
- while (--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- if (cmp(b, S) >= 0) {
- q++;
- borrow = 0;
- carry = 0;
- bx = b->x;
- sx = S->x;
- do {
-#ifdef USE_LONG_LONG
- ys = *sx++ + carry;
- carry = ys >> 32;
- y = *bx - (ys & 0xffffffffUL) - borrow;
- borrow = y >> 32 & (uint32_t)1;
- *bx++ = (uint32_t)y & 0xffffffffUL;
-#else
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) + carry;
- zs = (si >> 16) + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*bx >> 16) - (zs & 0xffff) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(bx, z, y);
-#else
- ys = *sx++ + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- *bx++ = y & 0xffff;
-#endif
-#endif
- } while (sx <= sxe);
- bx = b->x;
- bxe = bx + n;
- if (!*bxe) {
- while (--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- return q;
-}
-
-#if !ENABLE(JSC_MULTIPLE_THREADS)
-static char* dtoa_result;
-#endif
-
-static char* rv_alloc(int i)
-{
- int k;
-
- int j = sizeof(uint32_t);
- for (k = 0;
- sizeof(Bigint) - sizeof(uint32_t) - sizeof(int) + j <= (unsigned)i;
- j <<= 1)
- k++;
- int* r = (int*)Balloc(k);
- *r = k;
- return
-#if !ENABLE(JSC_MULTIPLE_THREADS)
- dtoa_result =
-#endif
- (char*)(r + 1);
-}
-
-static char* nrv_alloc(const char* s, char** rve, int n)
-{
- char* rv = rv_alloc(n);
- char* t = rv;
-
- while ((*t = *s++))
- t++;
- if (rve)
- *rve = t;
- return rv;
-}
-
-/* freedtoa(s) must be used to free values s returned by dtoa
- * when MULTIPLE_THREADS is #defined. It should be used in all cases,
- * but for consistency with earlier versions of dtoa, it is optional
- * when MULTIPLE_THREADS is not defined.
- */
-
-void freedtoa(char* s)
-{
- Bigint* b = (Bigint*)((int*)s - 1);
- b->maxwds = 1 << (b->k = *(int*)b);
- Bfree(b);
-#if !ENABLE(JSC_MULTIPLE_THREADS)
- if (s == dtoa_result)
- dtoa_result = 0;
-#endif
-}
-
-/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
- *
- * Inspired by "How to Print Floating-Point Numbers Accurately" by
- * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- * 1. Rather than iterating, we use a simple numeric overestimate
- * to determine k = floor(log10(d)). We scale relevant
- * quantities using O(log2(k)) rather than O(k) multiplications.
- * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
- * try to generate digits strictly left to right. Instead, we
- * compute with fewer bits and propagate the carry if necessary
- * when rounding the final digit up. This is often faster.
- * 3. Under the assumption that input will be rounded nearest,
- * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
- * That is, we allow equality in stopping tests when the
- * round-nearest rule will give the same floating-point value
- * as would satisfaction of the stopping test with strict
- * inequality.
- * 4. We remove common factors of powers of 2 from relevant
- * quantities.
- * 5. When converting floating-point integers less than 1e16,
- * we use floating-point arithmetic rather than resorting
- * to multiple-precision integers.
- * 6. When asked to produce fewer than 15 digits, we first try
- * to get by with floating-point arithmetic; we resort to
- * multiple-precision integer arithmetic only if we cannot
- * guarantee that the floating-point calculation has given
- * the correctly rounded result. For k requested digits and
- * "uniformly" distributed input, the probability is
- * something like 10^(k-15) that we must resort to the int32_t
- * calculation.
- */
-
-char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve)
-{
- /*
- Arguments ndigits, decpt, sign are similar to those
- of ecvt and fcvt; trailing zeros are suppressed from
- the returned string. If not null, *rve is set to point
- to the end of the return value. If d is +-Infinity or NaN,
- then *decpt is set to 9999.
-
- */
-
- int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0,
- j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
- spec_case, try_quick;
- int32_t L;
-#ifndef Sudden_Underflow
- int denorm;
- uint32_t x;
-#endif
- Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S;
- double d2, ds, eps;
- char *s, *s0;
-#ifdef SET_INEXACT
- int inexact, oldinexact;
-#endif
-
-#if !ENABLE(JSC_MULTIPLE_THREADS)
- if (dtoa_result) {
- freedtoa(dtoa_result);
- dtoa_result = 0;
- }
-#endif
-
- if (word0(d) & Sign_bit) {
- /* set sign for everything, including 0's and NaNs */
- *sign = 1;
- word0(d) &= ~Sign_bit; /* clear sign bit */
- } else
- *sign = 0;
-
- if ((word0(d) & Exp_mask) == Exp_mask)
- {
- /* Infinity or NaN */
- *decpt = 9999;
- if (!word1(d) && !(word0(d) & 0xfffff))
- return nrv_alloc("Infinity", rve, 8);
- return nrv_alloc("NaN", rve, 3);
- }
- if (!dval(d)) {
- *decpt = 1;
- return nrv_alloc("0", rve, 1);
- }
-
-#ifdef SET_INEXACT
- try_quick = oldinexact = get_inexact();
- inexact = 1;
-#endif
-
- b = d2b(dval(d), &be, &bbits);
-#ifdef Sudden_Underflow
- i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1));
-#else
- if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) {
-#endif
- dval(d2) = dval(d);
- word0(d2) &= Frac_mask1;
- word0(d2) |= Exp_11;
-
- /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
- * log10(x) = log(x) / log(10)
- * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
- * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
- *
- * This suggests computing an approximation k to log10(d) by
- *
- * k = (i - Bias)*0.301029995663981
- * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
- *
- * We want k to be too large rather than too small.
- * The error in the first-order Taylor series approximation
- * is in our favor, so we just round up the constant enough
- * to compensate for any error in the multiplication of
- * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
- * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
- * adding 1e-13 to the constant term more than suffices.
- * Hence we adjust the constant term to 0.1760912590558.
- * (We could get a more accurate k by invoking log10,
- * but this is probably not worthwhile.)
- */
-
- i -= Bias;
-#ifndef Sudden_Underflow
- denorm = 0;
- } else {
- /* d is denormalized */
-
- i = bbits + be + (Bias + (P - 1) - 1);
- x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
- : word1(d) << 32 - i;
- dval(d2) = x;
- word0(d2) -= 31 * Exp_msk1; /* adjust exponent */
- i -= (Bias + (P - 1) - 1) + 1;
- denorm = 1;
- }
-#endif
- ds = (dval(d2) - 1.5) * 0.289529654602168 + 0.1760912590558 + (i * 0.301029995663981);
- k = (int)ds;
- if (ds < 0. && ds != k)
- k--; /* want k = floor(ds) */
- k_check = 1;
- if (k >= 0 && k <= Ten_pmax) {
- if (dval(d) < tens[k])
- k--;
- k_check = 0;
- }
- j = bbits - i - 1;
- if (j >= 0) {
- b2 = 0;
- s2 = j;
- } else {
- b2 = -j;
- s2 = 0;
- }
- if (k >= 0) {
- b5 = 0;
- s5 = k;
- s2 += k;
- } else {
- b2 -= k;
- b5 = -k;
- s5 = 0;
- }
-
-#ifndef SET_INEXACT
-#ifdef Check_FLT_ROUNDS
- try_quick = Rounding == 1;
-#else
- try_quick = 1;
-#endif
-#endif /*SET_INEXACT*/
-
- leftright = 1;
- ilim = ilim1 = -1;
- i = 18;
- ndigits = 0;
- s = s0 = rv_alloc(i);
-
- if (ilim >= 0 && ilim <= Quick_max && try_quick) {
-
- /* Try to get by with floating-point arithmetic. */
-
- i = 0;
- dval(d2) = dval(d);
- k0 = k;
- ilim0 = ilim;
- ieps = 2; /* conservative */
- if (k > 0) {
- ds = tens[k & 0xf];
- j = k >> 4;
- if (j & Bletch) {
- /* prevent overflows */
- j &= Bletch - 1;
- dval(d) /= bigtens[n_bigtens - 1];
- ieps++;
- }
- for (; j; j >>= 1, i++) {
- if (j & 1) {
- ieps++;
- ds *= bigtens[i];
- }
- }
- dval(d) /= ds;
- } else if ((j1 = -k)) {
- dval(d) *= tens[j1 & 0xf];
- for (j = j1 >> 4; j; j >>= 1, i++) {
- if (j & 1) {
- ieps++;
- dval(d) *= bigtens[i];
- }
- }
- }
- if (k_check && dval(d) < 1. && ilim > 0) {
- if (ilim1 <= 0)
- goto fast_failed;
- ilim = ilim1;
- k--;
- dval(d) *= 10.;
- ieps++;
- }
- dval(eps) = (ieps * dval(d)) + 7.;
- word0(eps) -= (P - 1) * Exp_msk1;
- if (ilim == 0) {
- S = mhi = 0;
- dval(d) -= 5.;
- if (dval(d) > dval(eps))
- goto one_digit;
- if (dval(d) < -dval(eps))
- goto no_digits;
- goto fast_failed;
- }
-#ifndef No_leftright
- if (leftright) {
- /* Use Steele & White method of only
- * generating digits needed.
- */
- dval(eps) = (0.5 / tens[ilim - 1]) - dval(eps);
- for (i = 0;;) {
- L = (long int)dval(d);
- dval(d) -= L;
- *s++ = '0' + (int)L;
- if (dval(d) < dval(eps))
- goto ret1;
- if (1. - dval(d) < dval(eps))
- goto bump_up;
- if (++i >= ilim)
- break;
- dval(eps) *= 10.;
- dval(d) *= 10.;
- }
- } else {
-#endif
- /* Generate ilim digits, then fix them up. */
- dval(eps) *= tens[ilim - 1];
- for (i = 1;; i++, dval(d) *= 10.) {
- L = (int32_t)(dval(d));
- if (!(dval(d) -= L))
- ilim = i;
- *s++ = '0' + (int)L;
- if (i == ilim) {
- if (dval(d) > 0.5 + dval(eps))
- goto bump_up;
- else if (dval(d) < 0.5 - dval(eps)) {
- while (*--s == '0') { }
- s++;
- goto ret1;
- }
- break;
- }
- }
-#ifndef No_leftright
- }
-#endif
-fast_failed:
- s = s0;
- dval(d) = dval(d2);
- k = k0;
- ilim = ilim0;
- }
-
- /* Do we have a "small" integer? */
-
- if (be >= 0 && k <= Int_max) {
- /* Yes. */
- ds = tens[k];
- if (ndigits < 0 && ilim <= 0) {
- S = mhi = 0;
- if (ilim < 0 || dval(d) <= 5 * ds)
- goto no_digits;
- goto one_digit;
- }
- for (i = 1;; i++, dval(d) *= 10.) {
- L = (int32_t)(dval(d) / ds);
- dval(d) -= L * ds;
-#ifdef Check_FLT_ROUNDS
- /* If FLT_ROUNDS == 2, L will usually be high by 1 */
- if (dval(d) < 0) {
- L--;
- dval(d) += ds;
- }
-#endif
- *s++ = '0' + (int)L;
- if (!dval(d)) {
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- break;
- }
- if (i == ilim) {
- dval(d) += dval(d);
- if (dval(d) > ds || dval(d) == ds && L & 1) {
-bump_up:
- while (*--s == '9')
- if (s == s0) {
- k++;
- *s = '0';
- break;
- }
- ++*s++;
- }
- break;
- }
- }
- goto ret1;
- }
-
- m2 = b2;
- m5 = b5;
- mhi = mlo = 0;
- if (leftright) {
- i =
-#ifndef Sudden_Underflow
- denorm ? be + (Bias + (P - 1) - 1 + 1) :
-#endif
- 1 + P - bbits;
- b2 += i;
- s2 += i;
- mhi = i2b(1);
- }
- if (m2 > 0 && s2 > 0) {
- i = m2 < s2 ? m2 : s2;
- b2 -= i;
- m2 -= i;
- s2 -= i;
- }
- if (b5 > 0) {
- if (leftright) {
- if (m5 > 0) {
- mhi = pow5mult(mhi, m5);
- b1 = mult(mhi, b);
- Bfree(b);
- b = b1;
- }
- if ((j = b5 - m5))
- b = pow5mult(b, j);
- } else
- b = pow5mult(b, b5);
- }
- S = i2b(1);
- if (s5 > 0)
- S = pow5mult(S, s5);
-
- /* Check for special case that d is a normalized power of 2. */
-
- spec_case = 0;
- if (!word1(d) && !(word0(d) & Bndry_mask)
-#ifndef Sudden_Underflow
- && word0(d) & (Exp_mask & ~Exp_msk1)
-#endif
- ) {
- /* The special case */
- b2 += Log2P;
- s2 += Log2P;
- spec_case = 1;
- }
-
- /* Arrange for convenient computation of quotients:
- * shift left if necessary so divisor has 4 leading 0 bits.
- *
- * Perhaps we should just compute leading 28 bits of S once
- * and for all and pass them and a shift to quorem, so it
- * can do shifts and ors to compute the numerator for q.
- */
-#ifdef Pack_32
- if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0x1f))
- i = 32 - i;
-#else
- if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0xf))
- i = 16 - i;
-#endif
- if (i > 4) {
- i -= 4;
- b2 += i;
- m2 += i;
- s2 += i;
- } else if (i < 4) {
- i += 28;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- if (b2 > 0)
- b = lshift(b, b2);
- if (s2 > 0)
- S = lshift(S, s2);
- if (k_check) {
- if (cmp(b,S) < 0) {
- k--;
- b = multadd(b, 10, 0); /* we botched the k estimate */
- if (leftright)
- mhi = multadd(mhi, 10, 0);
- ilim = ilim1;
- }
- }
-
- if (leftright) {
- if (m2 > 0)
- mhi = lshift(mhi, m2);
-
- /* Compute mlo -- check for special case
- * that d is a normalized power of 2.
- */
-
- mlo = mhi;
- if (spec_case) {
- mhi = Balloc(mhi->k);
- Bcopy(mhi, mlo);
- mhi = lshift(mhi, Log2P);
- }
-
- for (i = 1;;i++) {
- dig = quorem(b,S) + '0';
- /* Do we yet have the shortest decimal string
- * that will round to d?
- */
- j = cmp(b, mlo);
- delta = diff(S, mhi);
- j1 = delta->sign ? 1 : cmp(b, delta);
- Bfree(delta);
- if (j1 == 0 && !(word1(d) & 1)) {
- if (dig == '9')
- goto round_9_up;
- if (j > 0)
- dig++;
-#ifdef SET_INEXACT
- else if (!b->x[0] && b->wds <= 1)
- inexact = 0;
-#endif
- *s++ = dig;
- goto ret;
- }
- if (j < 0 || j == 0 && !(word1(d) & 1)) {
- if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- goto accept_dig;
- }
- if (j1 > 0) {
- b = lshift(b, 1);
- j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1) && dig++ == '9')
- goto round_9_up;
- }
-accept_dig:
- *s++ = dig;
- goto ret;
- }
- if (j1 > 0) {
- if (dig == '9') { /* possible if i == 1 */
-round_9_up:
- *s++ = '9';
- goto roundoff;
- }
- *s++ = dig + 1;
- goto ret;
- }
- *s++ = dig;
- if (i == ilim)
- break;
- b = multadd(b, 10, 0);
- if (mlo == mhi)
- mlo = mhi = multadd(mhi, 10, 0);
- else {
- mlo = multadd(mlo, 10, 0);
- mhi = multadd(mhi, 10, 0);
- }
- }
- } else
- for (i = 1;; i++) {
- *s++ = dig = quorem(b,S) + '0';
- if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- goto ret;
- }
- if (i >= ilim)
- break;
- b = multadd(b, 10, 0);
- }
-
- /* Round off last digit */
-
- b = lshift(b, 1);
- j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
-roundoff:
- while (*--s == '9')
- if (s == s0) {
- k++;
- *s++ = '1';
- goto ret;
- }
- ++*s++;
- } else {
- while (*--s == '0') { }
- s++;
- }
- goto ret;
-no_digits:
- k = -1 - ndigits;
- goto ret;
-one_digit:
- *s++ = '1';
- k++;
- goto ret;
-ret:
- Bfree(S);
- if (mhi) {
- if (mlo && mlo != mhi)
- Bfree(mlo);
- Bfree(mhi);
- }
-ret1:
-#ifdef SET_INEXACT
- if (inexact) {
- if (!oldinexact) {
- word0(d) = Exp_1 + (70 << Exp_shift);
- word1(d) = 0;
- dval(d) += 1.;
- }
- } else if (!oldinexact)
- clear_inexact();
-#endif
- Bfree(b);
- *s = 0;
- *decpt = k + 1;
- if (rve)
- *rve = s;
- return s0;
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/dtoa.h b/JavaScriptCore/kjs/dtoa.h
deleted file mode 100644
index 690ebc8..0000000
--- a/JavaScriptCore/kjs/dtoa.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_dtoa_h
-#define KJS_dtoa_h
-
-namespace WTF {
- class Mutex;
-}
-
-namespace JSC {
-
- extern WTF::Mutex* s_dtoaP5Mutex;
-
- double strtod(const char* s00, char** se);
- char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve);
- void freedtoa(char* s);
-
-} // namespace JSC
-
-#endif /* KJS_dtoa_h */
diff --git a/JavaScriptCore/kjs/grammar.y b/JavaScriptCore/kjs/grammar.y
deleted file mode 100644
index 370798d..0000000
--- a/JavaScriptCore/kjs/grammar.y
+++ /dev/null
@@ -1,1511 +0,0 @@
-%pure_parser
-
-%{
-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include "JSValue.h"
-#include "JSObject.h"
-#include "nodes.h"
-#include "lexer.h"
-#include "JSString.h"
-#include "JSGlobalData.h"
-#include "CommonIdentifiers.h"
-#include "NodeInfo.h"
-#include "Parser.h"
-#include <wtf/MathExtras.h>
-
-#define YYMAXDEPTH 10000
-#define YYENABLE_NLS 0
-
-/* default values for bison */
-#define YYDEBUG 0 // Set to 1 to debug a parse error.
-#define kjsyydebug 0 // Set to 1 to debug a parse error.
-#if !PLATFORM(DARWIN)
- // avoid triggering warnings in older bison
-#define YYERROR_VERBOSE
-#endif
-
-int kjsyylex(void* lvalp, void* llocp, void* globalPtr);
-int kjsyyerror(const char*);
-static inline bool allowAutomaticSemicolon(JSC::Lexer&, int);
-
-#define GLOBAL_DATA static_cast<JSGlobalData*>(globalPtr)
-#define LEXER (GLOBAL_DATA->lexer)
-
-#define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*LEXER, yychar)) YYABORT; } while (0)
-#define SET_EXCEPTION_LOCATION(node, start, divot, end) node->setExceptionSourceCode((divot), (divot) - (start), (end) - (divot))
-#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line)
-
-using namespace JSC;
-using namespace std;
-
-static ExpressionNode* makeAssignNode(void*, ExpressionNode* loc, Operator, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end);
-static ExpressionNode* makePrefixNode(void*, ExpressionNode* expr, Operator, int start, int divot, int end);
-static ExpressionNode* makePostfixNode(void*, ExpressionNode* expr, Operator, int start, int divot, int end);
-static PropertyNode* makeGetterOrSetterPropertyNode(void*, const Identifier &getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*, const SourceCode&);
-static ExpressionNodeInfo makeFunctionCallNode(void*, ExpressionNodeInfo func, ArgumentsNodeInfo, int start, int divot, int end);
-static ExpressionNode* makeTypeOfNode(void*, ExpressionNode*);
-static ExpressionNode* makeDeleteNode(void*, ExpressionNode*, int start, int divot, int end);
-static ExpressionNode* makeNegateNode(void*, ExpressionNode*);
-static NumberNode* makeNumberNode(void*, double);
-static ExpressionNode* makeBitwiseNotNode(void*, ExpressionNode*);
-static ExpressionNode* makeMultNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeDivNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeAddNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeSubNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeLeftShiftNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeRightShiftNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static StatementNode* makeVarStatementNode(void*, ExpressionNode*);
-static ExpressionNode* combineVarInitializers(void*, ExpressionNode* list, AssignResolveNode* init);
-
-#if COMPILER(MSVC)
-
-#pragma warning(disable: 4065)
-#pragma warning(disable: 4244)
-#pragma warning(disable: 4702)
-
-// At least some of the time, the declarations of malloc and free that bison
-// generates are causing warnings. A way to avoid this is to explicitly define
-// the macros so that bison doesn't try to declare malloc and free.
-#define YYMALLOC malloc
-#define YYFREE free
-
-#endif
-
-#define YYPARSE_PARAM globalPtr
-#define YYLEX_PARAM globalPtr
-
-template <typename T> NodeDeclarationInfo<T> createNodeDeclarationInfo(T node, ParserRefCountedData<DeclarationStacks::VarStack>* varDecls,
- ParserRefCountedData<DeclarationStacks::FunctionStack>* funcDecls,
- CodeFeatures info,
- int numConstants)
-{
- ASSERT((info & ~AllFeatures) == 0);
- NodeDeclarationInfo<T> result = {node, varDecls, funcDecls, info, numConstants};
- return result;
-}
-
-template <typename T> NodeInfo<T> createNodeInfo(T node, CodeFeatures info, int numConstants)
-{
- ASSERT((info & ~AllFeatures) == 0);
- NodeInfo<T> result = {node, info, numConstants};
- return result;
-}
-
-template <typename T> T mergeDeclarationLists(T decls1, T decls2)
-{
- // decls1 or both are null
- if (!decls1)
- return decls2;
- // only decls1 is non-null
- if (!decls2)
- return decls1;
-
- // Both are non-null
- decls1->data.append(decls2->data);
-
- // We manually release the declaration lists to avoid accumulating many many
- // unused heap allocated vectors
- decls2->ref();
- decls2->deref();
- return decls1;
-}
-
-static void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
-{
- if (!varDecls)
- varDecls = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
-
- varDecls->data.append(make_pair(ident, attrs));
-
-}
-
-static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl)
-{
- unsigned attrs = DeclarationStacks::IsConstant;
- if (decl->m_init)
- attrs |= DeclarationStacks::HasInitializer;
- appendToVarDeclarationList(globalPtr, varDecls, decl->m_ident, attrs);
-}
-
-%}
-
-%union {
- int intValue;
- double doubleValue;
- Identifier* ident;
-
- // expression subtrees
- ExpressionNodeInfo expressionNode;
- FuncDeclNodeInfo funcDeclNode;
- PropertyNodeInfo propertyNode;
- ArgumentsNodeInfo argumentsNode;
- ConstDeclNodeInfo constDeclNode;
- CaseBlockNodeInfo caseBlockNode;
- CaseClauseNodeInfo caseClauseNode;
- FuncExprNodeInfo funcExprNode;
-
- // statement nodes
- StatementNodeInfo statementNode;
- FunctionBodyNode* functionBodyNode;
- ProgramNode* programNode;
-
- SourceElementsInfo sourceElements;
- PropertyListInfo propertyList;
- ArgumentListInfo argumentList;
- VarDeclListInfo varDeclList;
- ConstDeclListInfo constDeclList;
- ClauseListInfo clauseList;
- ElementListInfo elementList;
- ParameterListInfo parameterList;
-
- Operator op;
-}
-
-%start Program
-
-/* literals */
-%token NULLTOKEN TRUETOKEN FALSETOKEN
-
-/* keywords */
-%token BREAK CASE DEFAULT FOR NEW VAR CONSTTOKEN CONTINUE
-%token FUNCTION RETURN VOIDTOKEN DELETETOKEN
-%token IF THISTOKEN DO WHILE INTOKEN INSTANCEOF TYPEOF
-%token SWITCH WITH RESERVED
-%token THROW TRY CATCH FINALLY
-%token DEBUGGER
-
-/* give an if without an else higher precedence than an else to resolve the ambiguity */
-%nonassoc IF_WITHOUT_ELSE
-%nonassoc ELSE
-
-/* punctuators */
-%token EQEQ NE /* == and != */
-%token STREQ STRNEQ /* === and !== */
-%token LE GE /* < and > */
-%token OR AND /* || and && */
-%token PLUSPLUS MINUSMINUS /* ++ and -- */
-%token LSHIFT /* << */
-%token RSHIFT URSHIFT /* >> and >>> */
-%token PLUSEQUAL MINUSEQUAL /* += and -= */
-%token MULTEQUAL DIVEQUAL /* *= and /= */
-%token LSHIFTEQUAL /* <<= */
-%token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
-%token ANDEQUAL MODEQUAL /* &= and %= */
-%token XOREQUAL OREQUAL /* ^= and |= */
-%token <intValue> OPENBRACE /* { (with char offset) */
-%token <intValue> CLOSEBRACE /* { (with char offset) */
-
-/* terminal types */
-%token <doubleValue> NUMBER
-%token <ident> IDENT STRING
-
-/* automatically inserted semicolon */
-%token AUTOPLUSPLUS AUTOMINUSMINUS
-
-/* non-terminal types */
-%type <expressionNode> Literal ArrayLiteral
-
-%type <expressionNode> PrimaryExpr PrimaryExprNoBrace
-%type <expressionNode> MemberExpr MemberExprNoBF /* BF => brace or function */
-%type <expressionNode> NewExpr NewExprNoBF
-%type <expressionNode> CallExpr CallExprNoBF
-%type <expressionNode> LeftHandSideExpr LeftHandSideExprNoBF
-%type <expressionNode> PostfixExpr PostfixExprNoBF
-%type <expressionNode> UnaryExpr UnaryExprNoBF UnaryExprCommon
-%type <expressionNode> MultiplicativeExpr MultiplicativeExprNoBF
-%type <expressionNode> AdditiveExpr AdditiveExprNoBF
-%type <expressionNode> ShiftExpr ShiftExprNoBF
-%type <expressionNode> RelationalExpr RelationalExprNoIn RelationalExprNoBF
-%type <expressionNode> EqualityExpr EqualityExprNoIn EqualityExprNoBF
-%type <expressionNode> BitwiseANDExpr BitwiseANDExprNoIn BitwiseANDExprNoBF
-%type <expressionNode> BitwiseXORExpr BitwiseXORExprNoIn BitwiseXORExprNoBF
-%type <expressionNode> BitwiseORExpr BitwiseORExprNoIn BitwiseORExprNoBF
-%type <expressionNode> LogicalANDExpr LogicalANDExprNoIn LogicalANDExprNoBF
-%type <expressionNode> LogicalORExpr LogicalORExprNoIn LogicalORExprNoBF
-%type <expressionNode> ConditionalExpr ConditionalExprNoIn ConditionalExprNoBF
-%type <expressionNode> AssignmentExpr AssignmentExprNoIn AssignmentExprNoBF
-%type <expressionNode> Expr ExprNoIn ExprNoBF
-
-%type <expressionNode> ExprOpt ExprNoInOpt
-
-%type <statementNode> Statement Block
-%type <statementNode> VariableStatement ConstStatement EmptyStatement ExprStatement
-%type <statementNode> IfStatement IterationStatement ContinueStatement
-%type <statementNode> BreakStatement ReturnStatement WithStatement
-%type <statementNode> SwitchStatement LabelledStatement
-%type <statementNode> ThrowStatement TryStatement
-%type <statementNode> DebuggerStatement
-%type <statementNode> SourceElement
-
-%type <expressionNode> Initializer InitializerNoIn
-%type <funcDeclNode> FunctionDeclaration
-%type <funcExprNode> FunctionExpr
-%type <functionBodyNode> FunctionBody
-%type <sourceElements> SourceElements
-%type <parameterList> FormalParameterList
-%type <op> AssignmentOperator
-%type <argumentsNode> Arguments
-%type <argumentList> ArgumentList
-%type <varDeclList> VariableDeclarationList VariableDeclarationListNoIn
-%type <constDeclList> ConstDeclarationList
-%type <constDeclNode> ConstDeclaration
-%type <caseBlockNode> CaseBlock
-%type <caseClauseNode> CaseClause DefaultClause
-%type <clauseList> CaseClauses CaseClausesOpt
-%type <intValue> Elision ElisionOpt
-%type <elementList> ElementList
-%type <propertyNode> Property
-%type <propertyList> PropertyList
-%%
-
-Literal:
- NULLTOKEN { $$ = createNodeInfo<ExpressionNode*>(new NullNode(GLOBAL_DATA), 0, 1); }
- | TRUETOKEN { $$ = createNodeInfo<ExpressionNode*>(new BooleanNode(GLOBAL_DATA, true), 0, 1); }
- | FALSETOKEN { $$ = createNodeInfo<ExpressionNode*>(new BooleanNode(GLOBAL_DATA, false), 0, 1); }
- | NUMBER { $$ = createNodeInfo<ExpressionNode*>(makeNumberNode(GLOBAL_DATA, $1), 0, 1); }
- | STRING { $$ = createNodeInfo<ExpressionNode*>(new StringNode(GLOBAL_DATA, *$1), 0, 1); }
- | '/' /* regexp */ {
- Lexer& l = *LEXER;
- if (!l.scanRegExp())
- YYABORT;
- RegExpNode* node = new RegExpNode(GLOBAL_DATA, l.pattern(), l.flags());
- int size = l.pattern().size() + 2; // + 2 for the two /'s
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size);
- $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
- }
- | DIVEQUAL /* regexp with /= */ {
- Lexer& l = *LEXER;
- if (!l.scanRegExp())
- YYABORT;
- RegExpNode* node = new RegExpNode(GLOBAL_DATA, "=" + l.pattern(), l.flags());
- int size = l.pattern().size() + 2; // + 2 for the two /'s
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size);
- $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
- }
-;
-
-Property:
- IDENT ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
- | STRING ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
- | NUMBER ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, Identifier(GLOBAL_DATA, UString::from($1)), $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
- | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(globalPtr, *$1, *$2, 0, $6, LEXER->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); DBG($6, @5, @7); if (!$$.m_node) YYABORT; }
- | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
- {
- $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(globalPtr, *$1, *$2, $4.m_node.head, $7, LEXER->sourceCode($6, $8, @6.first_line)), $4.m_features | ClosureFeature, 0);
- if ($4.m_features & ArgumentsFeature)
- $7->setUsesArguments();
- DBG($7, @6, @8);
- if (!$$.m_node)
- YYABORT;
- }
-;
-
-PropertyList:
- Property { $$.m_node.head = new PropertyListNode(GLOBAL_DATA, $1.m_node);
- $$.m_node.tail = $$.m_node.head;
- $$.m_features = $1.m_features;
- $$.m_numConstants = $1.m_numConstants; }
- | PropertyList ',' Property { $$.m_node.head = $1.m_node.head;
- $$.m_node.tail = new PropertyListNode(GLOBAL_DATA, $3.m_node, $1.m_node.tail);
- $$.m_features = $1.m_features | $3.m_features;
- $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
-;
-
-PrimaryExpr:
- PrimaryExprNoBrace
- | OPENBRACE CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA), 0, 0); }
- | OPENBRACE PropertyList CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
- /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
- | OPENBRACE PropertyList ',' CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
-;
-
-PrimaryExprNoBrace:
- THISTOKEN { $$ = createNodeInfo<ExpressionNode*>(new ThisNode(GLOBAL_DATA), ThisFeature, 0); }
- | Literal
- | ArrayLiteral
- | IDENT { $$ = createNodeInfo<ExpressionNode*>(new ResolveNode(GLOBAL_DATA, *$1, @1.first_column), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); }
- | '(' Expr ')' { $$ = $2; }
-;
-
-ArrayLiteral:
- '[' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $2), 0, $2 ? 1 : 0); }
- | '[' ElementList ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
- | '[' ElementList ',' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $4, $2.m_node.head), $2.m_features, $4 ? $2.m_numConstants + 1 : $2.m_numConstants); }
-;
-
-ElementList:
- ElisionOpt AssignmentExpr { $$.m_node.head = new ElementNode(GLOBAL_DATA, $1, $2.m_node);
- $$.m_node.tail = $$.m_node.head;
- $$.m_features = $2.m_features;
- $$.m_numConstants = $2.m_numConstants; }
- | ElementList ',' ElisionOpt AssignmentExpr
- { $$.m_node.head = $1.m_node.head;
- $$.m_node.tail = new ElementNode(GLOBAL_DATA, $1.m_node.tail, $3, $4.m_node);
- $$.m_features = $1.m_features | $4.m_features;
- $$.m_numConstants = $1.m_numConstants + $4.m_numConstants; }
-;
-
-ElisionOpt:
- /* nothing */ { $$ = 0; }
- | Elision
-;
-
-Elision:
- ',' { $$ = 1; }
- | Elision ',' { $$ = $1 + 1; }
-;
-
-MemberExpr:
- PrimaryExpr
- | FunctionExpr { $$ = createNodeInfo<ExpressionNode*>($1.m_node, $1.m_features, $1.m_numConstants); }
- | MemberExpr '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
- }
- | MemberExpr '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
- }
- | NEW MemberExpr Arguments { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
- }
-;
-
-MemberExprNoBF:
- PrimaryExprNoBrace
- | MemberExprNoBF '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
- }
- | MemberExprNoBF '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
- }
- | NEW MemberExpr Arguments { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
- }
-;
-
-NewExpr:
- MemberExpr
- | NEW NewExpr { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants);
- }
-;
-
-NewExprNoBF:
- MemberExprNoBF
- | NEW NewExpr { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants);
- }
-;
-
-CallExpr:
- MemberExpr Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
- | CallExpr Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
- | CallExpr '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
- }
- | CallExpr '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); }
-;
-
-CallExprNoBF:
- MemberExprNoBF Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
- | CallExprNoBF Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
- | CallExprNoBF '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
- }
- | CallExprNoBF '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
- }
-;
-
-Arguments:
- '(' ')' { $$ = createNodeInfo<ArgumentsNode*>(new ArgumentsNode(GLOBAL_DATA), 0, 0); }
- | '(' ArgumentList ')' { $$ = createNodeInfo<ArgumentsNode*>(new ArgumentsNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
-;
-
-ArgumentList:
- AssignmentExpr { $$.m_node.head = new ArgumentListNode(GLOBAL_DATA, $1.m_node);
- $$.m_node.tail = $$.m_node.head;
- $$.m_features = $1.m_features;
- $$.m_numConstants = $1.m_numConstants; }
- | ArgumentList ',' AssignmentExpr { $$.m_node.head = $1.m_node.head;
- $$.m_node.tail = new ArgumentListNode(GLOBAL_DATA, $1.m_node.tail, $3.m_node);
- $$.m_features = $1.m_features | $3.m_features;
- $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
-;
-
-LeftHandSideExpr:
- NewExpr
- | CallExpr
-;
-
-LeftHandSideExprNoBF:
- NewExprNoBF
- | CallExprNoBF
-;
-
-PostfixExpr:
- LeftHandSideExpr
- | LeftHandSideExpr PLUSPLUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpPlusPlus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
- | LeftHandSideExpr MINUSMINUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpMinusMinus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
-;
-
-PostfixExprNoBF:
- LeftHandSideExprNoBF
- | LeftHandSideExprNoBF PLUSPLUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpPlusPlus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
- | LeftHandSideExprNoBF MINUSMINUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpMinusMinus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
-;
-
-UnaryExprCommon:
- DELETETOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeDeleteNode(GLOBAL_DATA, $2.m_node, @1.first_column, @2.last_column, @2.last_column), $2.m_features, $2.m_numConstants); }
- | VOIDTOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new VoidNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants + 1); }
- | TYPEOF UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeTypeOfNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
- | PLUSPLUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
- | AUTOPLUSPLUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
- | MINUSMINUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
- | AUTOMINUSMINUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
- | '+' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new UnaryPlusNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
- | '-' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeNegateNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
- | '~' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeBitwiseNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
- | '!' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
-
-UnaryExpr:
- PostfixExpr
- | UnaryExprCommon
-;
-
-UnaryExprNoBF:
- PostfixExprNoBF
- | UnaryExprCommon
-;
-
-MultiplicativeExpr:
- UnaryExpr
- | MultiplicativeExpr '*' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | MultiplicativeExpr '/' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | MultiplicativeExpr '%' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-MultiplicativeExprNoBF:
- UnaryExprNoBF
- | MultiplicativeExprNoBF '*' UnaryExpr
- { $$ = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | MultiplicativeExprNoBF '/' UnaryExpr
- { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | MultiplicativeExprNoBF '%' UnaryExpr
- { $$ = createNodeInfo<ExpressionNode*>(new ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-AdditiveExpr:
- MultiplicativeExpr
- | AdditiveExpr '+' MultiplicativeExpr { $$ = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | AdditiveExpr '-' MultiplicativeExpr { $$ = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-AdditiveExprNoBF:
- MultiplicativeExprNoBF
- | AdditiveExprNoBF '+' MultiplicativeExpr
- { $$ = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | AdditiveExprNoBF '-' MultiplicativeExpr
- { $$ = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ShiftExpr:
- AdditiveExpr
- | ShiftExpr LSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | ShiftExpr RSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | ShiftExpr URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ShiftExprNoBF:
- AdditiveExprNoBF
- | ShiftExprNoBF LSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | ShiftExprNoBF RSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | ShiftExprNoBF URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-RelationalExpr:
- ShiftExpr
- | RelationalExpr '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExpr '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExpr LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExpr GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExpr INSTANCEOF ShiftExpr { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExpr INTOKEN ShiftExpr { InNode* node = new InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-RelationalExprNoIn:
- ShiftExpr
- | RelationalExprNoIn '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExprNoIn '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExprNoIn LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExprNoIn GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExprNoIn INSTANCEOF ShiftExpr
- { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-RelationalExprNoBF:
- ShiftExprNoBF
- | RelationalExprNoBF '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExprNoBF '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExprNoBF LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExprNoBF GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExprNoBF INSTANCEOF ShiftExpr
- { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | RelationalExprNoBF INTOKEN ShiftExpr
- { InNode* node = new InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
- $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-EqualityExpr:
- RelationalExpr
- | EqualityExpr EQEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | EqualityExpr NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | EqualityExpr STREQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | EqualityExpr STRNEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-EqualityExprNoIn:
- RelationalExprNoIn
- | EqualityExprNoIn EQEQ RelationalExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | EqualityExprNoIn NE RelationalExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | EqualityExprNoIn STREQ RelationalExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | EqualityExprNoIn STRNEQ RelationalExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-EqualityExprNoBF:
- RelationalExprNoBF
- | EqualityExprNoBF EQEQ RelationalExpr
- { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | EqualityExprNoBF NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | EqualityExprNoBF STREQ RelationalExpr
- { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
- | EqualityExprNoBF STRNEQ RelationalExpr
- { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseANDExpr:
- EqualityExpr
- | BitwiseANDExpr '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseANDExprNoIn:
- EqualityExprNoIn
- | BitwiseANDExprNoIn '&' EqualityExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseANDExprNoBF:
- EqualityExprNoBF
- | BitwiseANDExprNoBF '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseXORExpr:
- BitwiseANDExpr
- | BitwiseXORExpr '^' BitwiseANDExpr { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseXORExprNoIn:
- BitwiseANDExprNoIn
- | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseXORExprNoBF:
- BitwiseANDExprNoBF
- | BitwiseXORExprNoBF '^' BitwiseANDExpr
- { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseORExpr:
- BitwiseXORExpr
- | BitwiseORExpr '|' BitwiseXORExpr { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseORExprNoIn:
- BitwiseXORExprNoIn
- | BitwiseORExprNoIn '|' BitwiseXORExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseORExprNoBF:
- BitwiseXORExprNoBF
- | BitwiseORExprNoBF '|' BitwiseXORExpr
- { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalANDExpr:
- BitwiseORExpr
- | LogicalANDExpr AND BitwiseORExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalANDExprNoIn:
- BitwiseORExprNoIn
- | LogicalANDExprNoIn AND BitwiseORExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalANDExprNoBF:
- BitwiseORExprNoBF
- | LogicalANDExprNoBF AND BitwiseORExpr
- { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalORExpr:
- LogicalANDExpr
- | LogicalORExpr OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalORExprNoIn:
- LogicalANDExprNoIn
- | LogicalORExprNoIn OR LogicalANDExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalORExprNoBF:
- LogicalANDExprNoBF
- | LogicalORExprNoBF OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ConditionalExpr:
- LogicalORExpr
- | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
- { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
-;
-
-ConditionalExprNoIn:
- LogicalORExprNoIn
- | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
-;
-
-ConditionalExprNoBF:
- LogicalORExprNoBF
- | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr
- { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
-;
-
-AssignmentExpr:
- ConditionalExpr
- | LeftHandSideExpr AssignmentOperator AssignmentExpr
- { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
- @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
- }
-;
-
-AssignmentExprNoIn:
- ConditionalExprNoIn
- | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn
- { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
- @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
- }
-;
-
-AssignmentExprNoBF:
- ConditionalExprNoBF
- | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr
- { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
- @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
- }
-;
-
-AssignmentOperator:
- '=' { $$ = OpEqual; }
- | PLUSEQUAL { $$ = OpPlusEq; }
- | MINUSEQUAL { $$ = OpMinusEq; }
- | MULTEQUAL { $$ = OpMultEq; }
- | DIVEQUAL { $$ = OpDivEq; }
- | LSHIFTEQUAL { $$ = OpLShift; }
- | RSHIFTEQUAL { $$ = OpRShift; }
- | URSHIFTEQUAL { $$ = OpURShift; }
- | ANDEQUAL { $$ = OpAndEq; }
- | XOREQUAL { $$ = OpXOrEq; }
- | OREQUAL { $$ = OpOrEq; }
- | MODEQUAL { $$ = OpModEq; }
-;
-
-Expr:
- AssignmentExpr
- | Expr ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ExprNoIn:
- AssignmentExprNoIn
- | ExprNoIn ',' AssignmentExprNoIn { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ExprNoBF:
- AssignmentExprNoBF
- | ExprNoBF ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-Statement:
- Block
- | VariableStatement
- | ConstStatement
- | EmptyStatement
- | ExprStatement
- | IfStatement
- | IterationStatement
- | ContinueStatement
- | BreakStatement
- | ReturnStatement
- | WithStatement
- | SwitchStatement
- | LabelledStatement
- | ThrowStatement
- | TryStatement
- | DebuggerStatement
-;
-
-Block:
- OPENBRACE CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0);
- DBG($$.m_node, @1, @2); }
- | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
- DBG($$.m_node, @1, @3); }
-;
-
-VariableStatement:
- VAR VariableDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
- DBG($$.m_node, @1, @3); }
- | VAR VariableDeclarationList error { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
- DBG($$.m_node, @1, @2);
- AUTO_SEMICOLON; }
-;
-
-VariableDeclarationList:
- IDENT { $$.m_node = 0;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0);
- $$.m_funcDeclarations = 0;
- $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
- $$.m_numConstants = 0;
- }
- | IDENT Initializer { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column);
- $$.m_node = node;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
- $$.m_funcDeclarations = 0;
- $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features;
- $$.m_numConstants = $2.m_numConstants;
- }
- | VariableDeclarationList ',' IDENT
- { $$.m_node = $1.m_node;
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, 0);
- $$.m_funcDeclarations = 0;
- $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
- $$.m_numConstants = $1.m_numConstants;
- }
- | VariableDeclarationList ',' IDENT Initializer
- { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column);
- $$.m_node = combineVarInitializers(GLOBAL_DATA, $1.m_node, node);
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
- $$.m_funcDeclarations = 0;
- $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features;
- $$.m_numConstants = $1.m_numConstants + $4.m_numConstants;
- }
-;
-
-VariableDeclarationListNoIn:
- IDENT { $$.m_node = 0;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0);
- $$.m_funcDeclarations = 0;
- $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
- $$.m_numConstants = 0;
- }
- | IDENT InitializerNoIn { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column);
- $$.m_node = node;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
- $$.m_funcDeclarations = 0;
- $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features;
- $$.m_numConstants = $2.m_numConstants;
- }
- | VariableDeclarationListNoIn ',' IDENT
- { $$.m_node = $1.m_node;
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, 0);
- $$.m_funcDeclarations = 0;
- $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
- $$.m_numConstants = $1.m_numConstants;
- }
- | VariableDeclarationListNoIn ',' IDENT InitializerNoIn
- { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
- SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column);
- $$.m_node = combineVarInitializers(GLOBAL_DATA, $1.m_node, node);
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
- $$.m_funcDeclarations = 0;
- $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features;
- $$.m_numConstants = $1.m_numConstants + $4.m_numConstants;
- }
-;
-
-ConstStatement:
- CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
- DBG($$.m_node, @1, @3); }
- | CONSTTOKEN ConstDeclarationList error
- { $$ = createNodeDeclarationInfo<StatementNode*>(new ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
- DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-ConstDeclarationList:
- ConstDeclaration { $$.m_node.head = $1.m_node;
- $$.m_node.tail = $$.m_node.head;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, $1.m_node);
- $$.m_funcDeclarations = 0;
- $$.m_features = $1.m_features;
- $$.m_numConstants = $1.m_numConstants;
- }
- | ConstDeclarationList ',' ConstDeclaration
- { $$.m_node.head = $1.m_node.head;
- $1.m_node.tail->m_next = $3.m_node;
- $$.m_node.tail = $3.m_node;
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, $3.m_node);
- $$.m_funcDeclarations = 0;
- $$.m_features = $1.m_features | $3.m_features;
- $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
-;
-
-ConstDeclaration:
- IDENT { $$ = createNodeInfo<ConstDeclNode*>(new ConstDeclNode(GLOBAL_DATA, *$1, 0), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); }
- | IDENT Initializer { $$ = createNodeInfo<ConstDeclNode*>(new ConstDeclNode(GLOBAL_DATA, *$1, $2.m_node), ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features, $2.m_numConstants); }
-;
-
-Initializer:
- '=' AssignmentExpr { $$ = $2; }
-;
-
-InitializerNoIn:
- '=' AssignmentExprNoIn { $$ = $2; }
-;
-
-EmptyStatement:
- ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new EmptyStatementNode(GLOBAL_DATA), 0, 0, 0, 0); }
-;
-
-ExprStatement:
- ExprNoBF ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
- DBG($$.m_node, @1, @2); }
- | ExprNoBF error { $$ = createNodeDeclarationInfo<StatementNode*>(new ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
- DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
-;
-
-IfStatement:
- IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE
- { $$ = createNodeDeclarationInfo<StatementNode*>(new IfNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
- DBG($$.m_node, @1, @4); }
- | IF '(' Expr ')' Statement ELSE Statement
- { $$ = createNodeDeclarationInfo<StatementNode*>(new IfElseNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node),
- mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations),
- $3.m_features | $5.m_features | $7.m_features,
- $3.m_numConstants + $5.m_numConstants + $7.m_numConstants);
- DBG($$.m_node, @1, @4); }
-;
-
-IterationStatement:
- DO Statement WHILE '(' Expr ')' ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
- DBG($$.m_node, @1, @3); }
- | DO Statement WHILE '(' Expr ')' error { $$ = createNodeDeclarationInfo<StatementNode*>(new DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
- DBG($$.m_node, @1, @3); } // Always performs automatic semicolon insertion.
- | WHILE '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new WhileNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
- DBG($$.m_node, @1, @4); }
- | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement
- { $$ = createNodeDeclarationInfo<StatementNode*>(new ForNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations,
- $3.m_features | $5.m_features | $7.m_features | $9.m_features,
- $3.m_numConstants + $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
- DBG($$.m_node, @1, @8);
- }
- | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement
- { $$ = createNodeDeclarationInfo<StatementNode*>(new ForNode(GLOBAL_DATA, $4.m_node, $6.m_node, $8.m_node, $10.m_node, true),
- mergeDeclarationLists($4.m_varDeclarations, $10.m_varDeclarations),
- mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations),
- $4.m_features | $6.m_features | $8.m_features | $10.m_features,
- $4.m_numConstants + $6.m_numConstants + $8.m_numConstants + $10.m_numConstants);
- DBG($$.m_node, @1, @9); }
- | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement
- {
- ForInNode* node = new ForInNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node);
- SET_EXCEPTION_LOCATION(node, @3.first_column, @3.last_column, @5.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, $7.m_varDeclarations, $7.m_funcDeclarations,
- $3.m_features | $5.m_features | $7.m_features,
- $3.m_numConstants + $5.m_numConstants + $7.m_numConstants);
- DBG($$.m_node, @1, @6);
- }
- | FOR '(' VAR IDENT INTOKEN Expr ')' Statement
- { ForInNode *forIn = new ForInNode(GLOBAL_DATA, *$4, 0, $6.m_node, $8.m_node, @5.first_column, @5.first_column - @4.first_column, @6.last_column - @5.first_column);
- SET_EXCEPTION_LOCATION(forIn, @4.first_column, @5.first_column + 1, @6.last_column);
- appendToVarDeclarationList(GLOBAL_DATA, $8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
- $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations, ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $6.m_features | $8.m_features, $6.m_numConstants + $8.m_numConstants);
- DBG($$.m_node, @1, @7); }
- | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement
- { ForInNode *forIn = new ForInNode(GLOBAL_DATA, *$4, $5.m_node, $7.m_node, $9.m_node, @5.first_column, @5.first_column - @4.first_column, @5.last_column - @5.first_column);
- SET_EXCEPTION_LOCATION(forIn, @4.first_column, @6.first_column + 1, @7.last_column);
- appendToVarDeclarationList(GLOBAL_DATA, $9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
- $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations,
- ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $5.m_features | $7.m_features | $9.m_features,
- $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
- DBG($$.m_node, @1, @8); }
-;
-
-ExprOpt:
- /* nothing */ { $$ = createNodeInfo<ExpressionNode*>(0, 0, 0); }
- | Expr
-;
-
-ExprNoInOpt:
- /* nothing */ { $$ = createNodeInfo<ExpressionNode*>(0, 0, 0); }
- | ExprNoIn
-;
-
-ContinueStatement:
- CONTINUE ';' { ContinueNode* node = new ContinueNode(GLOBAL_DATA);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
- DBG($$.m_node, @1, @2); }
- | CONTINUE error { ContinueNode* node = new ContinueNode(GLOBAL_DATA);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
- DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
- | CONTINUE IDENT ';' { ContinueNode* node = new ContinueNode(GLOBAL_DATA, *$2);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
- DBG($$.m_node, @1, @3); }
- | CONTINUE IDENT error { ContinueNode* node = new ContinueNode(GLOBAL_DATA, *$2);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
- DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-BreakStatement:
- BREAK ';' { BreakNode* node = new BreakNode(GLOBAL_DATA);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); }
- | BREAK error { BreakNode* node = new BreakNode(GLOBAL_DATA);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(new BreakNode(GLOBAL_DATA), 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
- | BREAK IDENT ';' { BreakNode* node = new BreakNode(GLOBAL_DATA, *$2);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @3); }
- | BREAK IDENT error { BreakNode* node = new BreakNode(GLOBAL_DATA, *$2);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(new BreakNode(GLOBAL_DATA, *$2), 0, 0, 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-ReturnStatement:
- RETURN ';' { ReturnNode* node = new ReturnNode(GLOBAL_DATA, 0);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); }
- | RETURN error { ReturnNode* node = new ReturnNode(GLOBAL_DATA, 0);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
- | RETURN Expr ';' { ReturnNode* node = new ReturnNode(GLOBAL_DATA, $2.m_node);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @3); }
- | RETURN Expr error { ReturnNode* node = new ReturnNode(GLOBAL_DATA, $2.m_node);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-WithStatement:
- WITH '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new WithNode(GLOBAL_DATA, $3.m_node, $5.m_node, @3.last_column, @3.last_column - @3.first_column),
- $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features | WithFeature, $3.m_numConstants + $5.m_numConstants);
- DBG($$.m_node, @1, @4); }
-;
-
-SwitchStatement:
- SWITCH '(' Expr ')' CaseBlock { $$ = createNodeDeclarationInfo<StatementNode*>(new SwitchNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations,
- $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
- DBG($$.m_node, @1, @4); }
-;
-
-CaseBlock:
- OPENBRACE CaseClausesOpt CLOSEBRACE { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode(GLOBAL_DATA, $2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); }
- | OPENBRACE CaseClausesOpt DefaultClause CaseClausesOpt CLOSEBRACE
- { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode(GLOBAL_DATA, $2.m_node.head, $3.m_node, $4.m_node.head),
- mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $3.m_varDeclarations), $4.m_varDeclarations),
- mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $3.m_funcDeclarations), $4.m_funcDeclarations),
- $2.m_features | $3.m_features | $4.m_features,
- $2.m_numConstants + $3.m_numConstants + $4.m_numConstants); }
-;
-
-CaseClausesOpt:
-/* nothing */ { $$.m_node.head = 0; $$.m_node.tail = 0; $$.m_varDeclarations = 0; $$.m_funcDeclarations = 0; $$.m_features = 0; $$.m_numConstants = 0; }
- | CaseClauses
-;
-
-CaseClauses:
- CaseClause { $$.m_node.head = new ClauseListNode(GLOBAL_DATA, $1.m_node);
- $$.m_node.tail = $$.m_node.head;
- $$.m_varDeclarations = $1.m_varDeclarations;
- $$.m_funcDeclarations = $1.m_funcDeclarations;
- $$.m_features = $1.m_features;
- $$.m_numConstants = $1.m_numConstants; }
- | CaseClauses CaseClause { $$.m_node.head = $1.m_node.head;
- $$.m_node.tail = new ClauseListNode(GLOBAL_DATA, $1.m_node.tail, $2.m_node);
- $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
- $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
- $$.m_features = $1.m_features | $2.m_features;
- $$.m_numConstants = $1.m_numConstants + $2.m_numConstants;
- }
-;
-
-CaseClause:
- CASE Expr ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, $2.m_node), 0, 0, $2.m_features, $2.m_numConstants); }
- | CASE Expr ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, $2.m_node, $4.m_node), $4.m_varDeclarations, $4.m_funcDeclarations, $2.m_features | $4.m_features, $2.m_numConstants + $4.m_numConstants); }
-;
-
-DefaultClause:
- DEFAULT ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, 0), 0, 0, 0, 0); }
- | DEFAULT ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, 0, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
-;
-
-LabelledStatement:
- IDENT ':' Statement { LabelNode* node = new LabelNode(GLOBAL_DATA, *$1, $3.m_node);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
-;
-
-ThrowStatement:
- THROW Expr ';' { ThrowNode* node = new ThrowNode(GLOBAL_DATA, $2.m_node);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2);
- }
- | THROW Expr error { ThrowNode* node = new ThrowNode(GLOBAL_DATA, $2.m_node);
- SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
- $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON;
- }
-;
-
-TryStatement:
- TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, 0, $4.m_node),
- mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations),
- mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations),
- $2.m_features | $4.m_features,
- $2.m_numConstants + $4.m_numConstants);
- DBG($$.m_node, @1, @2); }
- | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, $7.m_node, 0),
- mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations),
- mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations),
- $2.m_features | $7.m_features | CatchFeature,
- $2.m_numConstants + $7.m_numConstants);
- DBG($$.m_node, @1, @2); }
- | TRY Block CATCH '(' IDENT ')' Block FINALLY Block
- { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, $7.m_node, $9.m_node),
- mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations),
- mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations),
- $2.m_features | $7.m_features | $9.m_features | CatchFeature,
- $2.m_numConstants + $7.m_numConstants + $9.m_numConstants);
- DBG($$.m_node, @1, @2); }
-;
-
-DebuggerStatement:
- DEBUGGER ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
- DBG($$.m_node, @1, @2); }
- | DEBUGGER error { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
- DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
-;
-
-FunctionDeclaration:
- FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncDeclNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); DBG($6, @5, @7); }
- | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
- {
- $$ = createNodeInfo(new FuncDeclNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0);
- if ($4.m_features & ArgumentsFeature)
- $7->setUsesArguments();
- DBG($7, @6, @8);
- }
-;
-
-FunctionExpr:
- FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $5, LEXER->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); DBG($5, @4, @6); }
- | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
- {
- $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $6, LEXER->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0);
- if ($3.m_features & ArgumentsFeature)
- $6->setUsesArguments();
- DBG($6, @5, @7);
- }
- | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); DBG($6, @5, @7); }
- | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
- {
- $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), $4.m_features | ClosureFeature, 0);
- if ($4.m_features & ArgumentsFeature)
- $7->setUsesArguments();
- DBG($7, @6, @8);
- }
-;
-
-FormalParameterList:
- IDENT { $$.m_node.head = new ParameterNode(GLOBAL_DATA, *$1);
- $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
- $$.m_node.tail = $$.m_node.head; }
- | FormalParameterList ',' IDENT { $$.m_node.head = $1.m_node.head;
- $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
- $$.m_node.tail = new ParameterNode(GLOBAL_DATA, $1.m_node.tail, *$3); }
-;
-
-FunctionBody:
- /* not in spec */ { $$ = FunctionBodyNode::create(GLOBAL_DATA, 0, 0, 0, NoFeatures, 0); }
- | SourceElements { $$ = FunctionBodyNode::create(GLOBAL_DATA, $1.m_node, $1.m_varDeclarations ? &$1.m_varDeclarations->data : 0,
- $1.m_funcDeclarations ? &$1.m_funcDeclarations->data : 0,
- $1.m_features, $1.m_numConstants);
- // As in mergeDeclarationLists() we have to ref/deref to safely get rid of
- // the declaration lists.
- if ($1.m_varDeclarations) {
- $1.m_varDeclarations->ref();
- $1.m_varDeclarations->deref();
- }
- if ($1.m_funcDeclarations) {
- $1.m_funcDeclarations->ref();
- $1.m_funcDeclarations->deref();
- }
- }
-;
-
-Program:
- /* not in spec */ { GLOBAL_DATA->parser->didFinishParsing(new SourceElements(GLOBAL_DATA), 0, 0, NoFeatures, @0.last_line, 0); }
- | SourceElements { GLOBAL_DATA->parser->didFinishParsing($1.m_node, $1.m_varDeclarations, $1.m_funcDeclarations, $1.m_features,
- @1.last_line, $1.m_numConstants); }
-;
-
-SourceElements:
- SourceElement { $$.m_node = new SourceElements(GLOBAL_DATA);
- $$.m_node->append($1.m_node);
- $$.m_varDeclarations = $1.m_varDeclarations;
- $$.m_funcDeclarations = $1.m_funcDeclarations;
- $$.m_features = $1.m_features;
- $$.m_numConstants = $1.m_numConstants;
- }
- | SourceElements SourceElement { $$.m_node->append($2.m_node);
- $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
- $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
- $$.m_features = $1.m_features | $2.m_features;
- $$.m_numConstants = $1.m_numConstants + $2.m_numConstants;
- }
-;
-
-SourceElement:
- FunctionDeclaration { $$ = createNodeDeclarationInfo<StatementNode*>($1.m_node, 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), $1.m_features, 0); $$.m_funcDeclarations->data.append($1.m_node); }
- | Statement { $$ = $1; }
-;
-
-%%
-
-static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
-{
- if (!loc->isLocation())
- return new AssignErrorNode(GLOBAL_DATA, loc, op, expr, divot, divot - start, end - divot);
-
- if (loc->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(loc);
- if (op == OpEqual) {
- AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, resolve->identifier(), expr, exprHasAssignments);
- SET_EXCEPTION_LOCATION(node, start, divot, end);
- return node;
- } else
- return new ReadModifyResolveNode(GLOBAL_DATA, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
- }
- if (loc->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
- if (op == OpEqual)
- return new AssignBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot());
- else {
- ReadModifyBracketNode* node = new ReadModifyBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot);
- node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
- return node;
- }
- }
- ASSERT(loc->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
- if (op == OpEqual)
- return new AssignDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
-
- ReadModifyDotNode* node = new ReadModifyDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
- node->setSubexpressionInfo(dot->divot(), dot->endOffset());
- return node;
-}
-
-static ExpressionNode* makePrefixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end)
-{
- if (!expr->isLocation())
- return new PrefixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot);
-
- if (expr->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- return new PrefixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot);
- }
- if (expr->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
- PrefixBracketNode* node = new PrefixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
- node->setSubexpressionInfo(bracket->divot(), bracket->startOffset());
- return node;
- }
- ASSERT(expr->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
- PrefixDotNode* node = new PrefixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
- node->setSubexpressionInfo(dot->divot(), dot->startOffset());
- return node;
-}
-
-static ExpressionNode* makePostfixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end)
-{
- if (!expr->isLocation())
- return new PostfixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot);
-
- if (expr->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- return new PostfixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot);
- }
- if (expr->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
- PostfixBracketNode* node = new PostfixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
- node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
- return node;
-
- }
- ASSERT(expr->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
- PostfixDotNode* node = new PostfixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
- node->setSubexpressionInfo(dot->divot(), dot->endOffset());
- return node;
-}
-
-static ExpressionNodeInfo makeFunctionCallNode(void* globalPtr, ExpressionNodeInfo func, ArgumentsNodeInfo args, int start, int divot, int end)
-{
- CodeFeatures features = func.m_features | args.m_features;
- int numConstants = func.m_numConstants + args.m_numConstants;
- if (!func.m_node->isLocation())
- return createNodeInfo<ExpressionNode*>(new FunctionCallValueNode(GLOBAL_DATA, func.m_node, args.m_node, divot, divot - start, end - divot), features, numConstants);
- if (func.m_node->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(func.m_node);
- const Identifier& identifier = resolve->identifier();
- if (identifier == GLOBAL_DATA->propertyNames->eval)
- return createNodeInfo<ExpressionNode*>(new EvalFunctionCallNode(GLOBAL_DATA, args.m_node, divot, divot - start, end - divot), EvalFeature | features, numConstants);
- return createNodeInfo<ExpressionNode*>(new FunctionCallResolveNode(GLOBAL_DATA, identifier, args.m_node, divot, divot - start, end - divot), features, numConstants);
- }
- if (func.m_node->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func.m_node);
- FunctionCallBracketNode* node = new FunctionCallBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), args.m_node, divot, divot - start, end - divot);
- node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
- return createNodeInfo<ExpressionNode*>(node, features, numConstants);
- }
- ASSERT(func.m_node->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(func.m_node);
- FunctionCallDotNode* node = new FunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
- node->setSubexpressionInfo(dot->divot(), dot->endOffset());
- return createNodeInfo<ExpressionNode*>(node, features, numConstants);
-}
-
-static ExpressionNode* makeTypeOfNode(void* globalPtr, ExpressionNode* expr)
-{
- if (expr->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- return new TypeOfResolveNode(GLOBAL_DATA, resolve->identifier());
- }
- return new TypeOfValueNode(GLOBAL_DATA, expr);
-}
-
-static ExpressionNode* makeDeleteNode(void* globalPtr, ExpressionNode* expr, int start, int divot, int end)
-{
- if (!expr->isLocation())
- return new DeleteValueNode(GLOBAL_DATA, expr);
- if (expr->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- return new DeleteResolveNode(GLOBAL_DATA, resolve->identifier(), divot, divot - start, end - divot);
- }
- if (expr->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
- return new DeleteBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), divot, divot - start, end - divot);
- }
- ASSERT(expr->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
- return new DeleteDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), divot, divot - start, end - divot);
-}
-
-static PropertyNode* makeGetterOrSetterPropertyNode(void* globalPtr, const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body, const SourceCode& source)
-{
- PropertyNode::Type type;
- if (getOrSet == "get")
- type = PropertyNode::Getter;
- else if (getOrSet == "set")
- type = PropertyNode::Setter;
- else
- return 0;
- return new PropertyNode(GLOBAL_DATA, name, new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, body, source, params), type);
-}
-
-static ExpressionNode* makeNegateNode(void* globalPtr, ExpressionNode* n)
-{
- if (n->isNumber()) {
- NumberNode* number = static_cast<NumberNode*>(n);
-
- if (number->value() > 0.0) {
- number->setValue(-number->value());
- return number;
- }
- }
-
- return new NegateNode(GLOBAL_DATA, n);
-}
-
-static NumberNode* makeNumberNode(void* globalPtr, double d)
-{
- JSValue* value = JSImmediate::from(d);
- if (value)
- return new ImmediateNumberNode(GLOBAL_DATA, value, d);
- return new NumberNode(GLOBAL_DATA, d);
-}
-
-static ExpressionNode* makeBitwiseNotNode(void* globalPtr, ExpressionNode* expr)
-{
- if (expr->isNumber())
- return makeNumberNode(globalPtr, ~toInt32(static_cast<NumberNode*>(expr)->value()));
- return new BitwiseNotNode(GLOBAL_DATA, expr);
-}
-
-static ExpressionNode* makeMultNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
- expr1 = expr1->stripUnaryPlus();
- expr2 = expr2->stripUnaryPlus();
-
- if (expr1->isNumber() && expr2->isNumber())
- return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
-
- if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
- return new UnaryPlusNode(GLOBAL_DATA, expr2);
-
- if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
- return new UnaryPlusNode(GLOBAL_DATA, expr1);
-
- return new MultNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeDivNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
- expr1 = expr1->stripUnaryPlus();
- expr2 = expr2->stripUnaryPlus();
-
- if (expr1->isNumber() && expr2->isNumber())
- return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value());
- return new DivNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeAddNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
- if (expr1->isNumber() && expr2->isNumber())
- return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value());
- return new AddNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeSubNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
- expr1 = expr1->stripUnaryPlus();
- expr2 = expr2->stripUnaryPlus();
-
- if (expr1->isNumber() && expr2->isNumber())
- return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value());
- return new SubNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeLeftShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
- if (expr1->isNumber() && expr2->isNumber())
- return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
- return new LeftShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeRightShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
- if (expr1->isNumber() && expr2->isNumber())
- return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
- return new RightShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
-}
-
-/* called by yyparse on error */
-int yyerror(const char *)
-{
- return 1;
-}
-
-/* may we automatically insert a semicolon ? */
-static bool allowAutomaticSemicolon(Lexer& lexer, int yychar)
-{
- return yychar == CLOSEBRACE || yychar == 0 || lexer.prevTerminator();
-}
-
-static ExpressionNode* combineVarInitializers(void* globalPtr, ExpressionNode* list, AssignResolveNode* init)
-{
- if (!list)
- return init;
- return new VarDeclCommaNode(GLOBAL_DATA, list, init);
-}
-
-// We turn variable declarations into either assignments or empty
-// statements (which later get stripped out), because the actual
-// declaration work is hoisted up to the start of the function body
-static StatementNode* makeVarStatementNode(void* globalPtr, ExpressionNode* expr)
-{
- if (!expr)
- return new EmptyStatementNode(GLOBAL_DATA);
- return new VarStatementNode(GLOBAL_DATA, expr);
-}
-
-#undef GLOBAL_DATA
diff --git a/JavaScriptCore/kjs/identifier.cpp b/JavaScriptCore/kjs/identifier.cpp
deleted file mode 100644
index 50a6cc3..0000000
--- a/JavaScriptCore/kjs/identifier.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "identifier.h"
-
-#include "ExecState.h"
-#include <new> // for placement new
-#include <string.h> // for strlen
-#include <wtf/Assertions.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/HashSet.h>
-
-namespace JSC {
-
-typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable;
-
-class IdentifierTable {
-public:
- ~IdentifierTable()
- {
- HashSet<UString::Rep*>::iterator end = m_table.end();
- for (HashSet<UString::Rep*>::iterator iter = m_table.begin(); iter != end; ++iter)
- (*iter)->setIdentifierTable(0);
- }
-
- std::pair<HashSet<UString::Rep*>::iterator, bool> add(UString::Rep* value)
- {
- std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add(value);
- (*result.first)->setIdentifierTable(this);
- return result;
- }
-
- template<typename U, typename V>
- std::pair<HashSet<UString::Rep*>::iterator, bool> add(U value)
- {
- std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add<U, V>(value);
- (*result.first)->setIdentifierTable(this);
- return result;
- }
-
- void remove(UString::Rep* r) { m_table.remove(r); }
-
- LiteralIdentifierTable& literalTable() { return m_literalTable; }
-
-private:
- HashSet<UString::Rep*> m_table;
- LiteralIdentifierTable m_literalTable;
-};
-
-IdentifierTable* createIdentifierTable()
-{
- return new IdentifierTable;
-}
-
-void deleteIdentifierTable(IdentifierTable* table)
-{
- delete table;
-}
-
-bool Identifier::equal(const UString::Rep* r, const char* s)
-{
- int length = r->len;
- const UChar* d = r->data();
- for (int i = 0; i != length; ++i)
- if (d[i] != (unsigned char)s[i])
- return false;
- return s[length] == 0;
-}
-
-bool Identifier::equal(const UString::Rep* r, const UChar* s, int length)
-{
- if (r->len != length)
- return false;
- const UChar* d = r->data();
- for (int i = 0; i != length; ++i)
- if (d[i] != s[i])
- return false;
- return true;
-}
-
-struct CStringTranslator
-{
- static unsigned hash(const char* c)
- {
- return UString::Rep::computeHash(c);
- }
-
- static bool equal(UString::Rep* r, const char* s)
- {
- return Identifier::equal(r, s);
- }
-
- static void translate(UString::Rep*& location, const char* c, unsigned hash)
- {
- size_t length = strlen(c);
- UChar* d = static_cast<UChar*>(fastMalloc(sizeof(UChar) * length));
- for (size_t i = 0; i != length; i++)
- d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
-
- UString::Rep* r = UString::Rep::create(d, static_cast<int>(length)).releaseRef();
- r->rc = 0;
- r->_hash = hash;
-
- location = r;
- }
-};
-
-PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c)
-{
- if (!c) {
- UString::Rep::null.hash();
- return &UString::Rep::null;
- }
- if (!c[0]) {
- UString::Rep::empty.hash();
- return &UString::Rep::empty;
- }
- if (!c[1])
- return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0])));
-
- IdentifierTable& identifierTable = *globalData->identifierTable;
- LiteralIdentifierTable& literalIdentifierTable = identifierTable.literalTable();
-
- const LiteralIdentifierTable::iterator& iter = literalIdentifierTable.find(c);
- if (iter != literalIdentifierTable.end())
- return iter->second;
-
- UString::Rep* addedString = *identifierTable.add<const char*, CStringTranslator>(c).first;
- literalIdentifierTable.add(c, addedString);
-
- return addedString;
-}
-
-PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const char* c)
-{
- return add(&exec->globalData(), c);
-}
-
-struct UCharBuffer {
- const UChar* s;
- unsigned int length;
-};
-
-struct UCharBufferTranslator
-{
- static unsigned hash(const UCharBuffer& buf)
- {
- return UString::Rep::computeHash(buf.s, buf.length);
- }
-
- static bool equal(UString::Rep* str, const UCharBuffer& buf)
- {
- return Identifier::equal(str, buf.s, buf.length);
- }
-
- static void translate(UString::Rep*& location, const UCharBuffer& buf, unsigned hash)
- {
- UChar* d = static_cast<UChar*>(fastMalloc(sizeof(UChar) * buf.length));
- for (unsigned i = 0; i != buf.length; i++)
- d[i] = buf.s[i];
-
- UString::Rep* r = UString::Rep::create(d, buf.length).releaseRef();
- r->rc = 0;
- r->_hash = hash;
-
- location = r;
- }
-};
-
-PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* s, int length)
-{
- if (length == 1) {
- UChar c = s[0];
- if (c <= 0xFF)
- return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
- }
- if (!length) {
- UString::Rep::empty.hash();
- return &UString::Rep::empty;
- }
- UCharBuffer buf = {s, length};
- return *globalData->identifierTable->add<UCharBuffer, UCharBufferTranslator>(buf).first;
-}
-
-PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int length)
-{
- return add(&exec->globalData(), s, length);
-}
-
-PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r)
-{
- ASSERT(!r->identifierTable());
- if (r->len == 1) {
- UChar c = r->data()[0];
- if (c <= 0xFF)
- r = globalData->smallStrings.singleCharacterStringRep(c);
- if (r->identifierTable()) {
-#ifndef NDEBUG
- checkSameIdentifierTable(globalData, r);
-#endif
- return r;
- }
- }
- if (!r->len) {
- UString::Rep::empty.hash();
- return &UString::Rep::empty;
- }
- return *globalData->identifierTable->add(r).first;
-}
-
-PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep* r)
-{
- return addSlowCase(&exec->globalData(), r);
-}
-
-void Identifier::remove(UString::Rep* r)
-{
- r->identifierTable()->remove(r);
-}
-
-#ifndef NDEBUG
-
-void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep* rep)
-{
- ASSERT(rep->identifierTable() == exec->globalData().identifierTable);
-}
-
-void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep* rep)
-{
- ASSERT(rep->identifierTable() == globalData->identifierTable);
-}
-
-#else
-
-void Identifier::checkSameIdentifierTable(ExecState*, UString::Rep*)
-{
-}
-
-void Identifier::checkSameIdentifierTable(JSGlobalData*, UString::Rep*)
-{
-}
-
-#endif
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/identifier.h b/JavaScriptCore/kjs/identifier.h
deleted file mode 100644
index a79dd92..0000000
--- a/JavaScriptCore/kjs/identifier.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_IDENTIFIER_H
-#define KJS_IDENTIFIER_H
-
-#include "JSGlobalData.h"
-#include "ustring.h"
-
-namespace JSC {
-
- class ExecState;
-
- class Identifier {
- friend class StructureID;
- public:
- Identifier() { }
-
- Identifier(ExecState* exec, const char* s) : _ustring(add(exec, s)) { } // Only to be used with string literals.
- Identifier(ExecState* exec, const UChar* s, int length) : _ustring(add(exec, s, length)) { }
- Identifier(ExecState* exec, UString::Rep* rep) : _ustring(add(exec, rep)) { }
- Identifier(ExecState* exec, const UString& s) : _ustring(add(exec, s.rep())) { }
-
- Identifier(JSGlobalData* globalData, const char* s) : _ustring(add(globalData, s)) { } // Only to be used with string literals.
- Identifier(JSGlobalData* globalData, const UChar* s, int length) : _ustring(add(globalData, s, length)) { }
- Identifier(JSGlobalData* globalData, UString::Rep* rep) : _ustring(add(globalData, rep)) { }
- Identifier(JSGlobalData* globalData, const UString& s) : _ustring(add(globalData, s.rep())) { }
-
- // Special constructor for cases where we overwrite an object in place.
- Identifier(PlacementNewAdoptType) : _ustring(PlacementNewAdopt) { }
-
- const UString& ustring() const { return _ustring; }
-
- const UChar* data() const { return _ustring.data(); }
- int size() const { return _ustring.size(); }
-
- const char* ascii() const { return _ustring.ascii(); }
-
- static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); }
-
- bool isNull() const { return _ustring.isNull(); }
- bool isEmpty() const { return _ustring.isEmpty(); }
-
- uint32_t toUInt32(bool* ok) const { return _ustring.toUInt32(ok); }
- uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const { return _ustring.toUInt32(ok, tolerateEmptyString); };
- uint32_t toStrictUInt32(bool* ok) const { return _ustring.toStrictUInt32(ok); }
- unsigned toArrayIndex(bool* ok) const { return _ustring.toArrayIndex(ok); }
- double toDouble() const { return _ustring.toDouble(); }
-
- friend bool operator==(const Identifier&, const Identifier&);
- friend bool operator!=(const Identifier&, const Identifier&);
-
- friend bool operator==(const Identifier&, const char*);
-
- static void remove(UString::Rep*);
-
- static bool equal(const UString::Rep*, const char*);
- static bool equal(const UString::Rep*, const UChar*, int length);
- static bool equal(const UString::Rep* a, const UString::Rep* b) { return JSC::equal(a, b); }
-
- static PassRefPtr<UString::Rep> add(ExecState*, const char*); // Only to be used with string literals.
- static PassRefPtr<UString::Rep> add(JSGlobalData*, const char*); // Only to be used with string literals.
-
- static void initializeIdentifierThreading();
-
- private:
- UString _ustring;
-
- static bool equal(const Identifier& a, const Identifier& b) { return a._ustring.rep() == b._ustring.rep(); }
- static bool equal(const Identifier& a, const char* b) { return equal(a._ustring.rep(), b); }
-
- static PassRefPtr<UString::Rep> add(ExecState*, const UChar*, int length);
- static PassRefPtr<UString::Rep> add(JSGlobalData*, const UChar*, int length);
-
- static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r)
- {
- if (r->identifierTable()) {
-#ifndef NDEBUG
- checkSameIdentifierTable(exec, r);
-#endif
- return r;
- }
- return addSlowCase(exec, r);
- }
- static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r)
- {
- if (r->identifierTable()) {
-#ifndef NDEBUG
- checkSameIdentifierTable(globalData, r);
-#endif
- return r;
- }
- return addSlowCase(globalData, r);
- }
-
- static PassRefPtr<UString::Rep> addSlowCase(ExecState*, UString::Rep* r);
- static PassRefPtr<UString::Rep> addSlowCase(JSGlobalData*, UString::Rep* r);
-
- static void checkSameIdentifierTable(ExecState*, UString::Rep*);
- static void checkSameIdentifierTable(JSGlobalData*, UString::Rep*);
- };
-
- inline bool operator==(const Identifier& a, const Identifier& b)
- {
- return Identifier::equal(a, b);
- }
-
- inline bool operator!=(const Identifier& a, const Identifier& b)
- {
- return !Identifier::equal(a, b);
- }
-
- inline bool operator==(const Identifier& a, const char* b)
- {
- return Identifier::equal(a, b);
- }
-
- IdentifierTable* createIdentifierTable();
- void deleteIdentifierTable(IdentifierTable*);
-
-} // namespace JSC
-
-#endif // KJS_IDENTIFIER_H
diff --git a/JavaScriptCore/kjs/interpreter.cpp b/JavaScriptCore/kjs/interpreter.cpp
deleted file mode 100644
index 1188349..0000000
--- a/JavaScriptCore/kjs/interpreter.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "interpreter.h"
-
-#include "ExecState.h"
-#include "JSGlobalObject.h"
-#include "JSLock.h"
-#include "Machine.h"
-#include "Parser.h"
-#include "completion.h"
-#include "Debugger.h"
-#include <stdio.h>
-
-#if !PLATFORM(WIN_OS)
-#include <unistd.h>
-#endif
-
-namespace JSC {
-
-Completion Interpreter::checkSyntax(ExecState* exec, const SourceCode& source)
-{
- JSLock lock(exec);
-
- int errLine;
- UString errMsg;
-
- RefPtr<ProgramNode> progNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
- if (!progNode)
- return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
- return Completion(Normal);
-}
-
-Completion Interpreter::evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue* thisValue)
-{
- JSLock lock(exec);
-
- int errLine;
- UString errMsg;
- RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-
- if (!programNode)
- return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
-
- JSObject* thisObj = (!thisValue || thisValue->isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue->toObject(exec);
-
- JSValue* exception = noValue();
- JSValue* result = exec->machine()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception);
-
- if (exception) {
- if (exception->isObject() && asObject(exception)->isWatchdogException())
- return Completion(Interrupted, result);
- return Completion(Throw, exception);
- }
- return Completion(Normal, result);
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/interpreter.h b/JavaScriptCore/kjs/interpreter.h
deleted file mode 100644
index 0366063..0000000
--- a/JavaScriptCore/kjs/interpreter.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_Interpreter_h
-#define KJS_Interpreter_h
-
-#include "JSValue.h"
-#include <wtf/PassRefPtr.h>
-#include <wtf/unicode/Unicode.h>
-
-namespace JSC {
-
- class Completion;
- class ExecState;
- class ScopeChain;
- class SourceCode;
-
- class Interpreter {
- public:
- /**
- * Parses the supplied ECMAScript code and checks for syntax errors.
- *
- * @param code The code to check
- * @return A normal completion if there were no syntax errors in the code,
- * otherwise a throw completion with the syntax error as its value.
- */
- static Completion checkSyntax(ExecState*, const SourceCode&);
-
- /**
- * Evaluates the supplied ECMAScript code.
- *
- * Since this method returns a Completion, you should check the type of
- * completion to detect an error or before attempting to access the returned
- * value. For example, if an error occurs during script execution and is not
- * caught by the script, the completion type will be Throw.
- *
- * If the supplied code is invalid, a SyntaxError will be thrown.
- *
- * @param code The code to evaluate
- * @param thisValue The value to pass in as the "this" value for the script
- * execution. This should either be jsNull() or an Object.
- * @return A completion object representing the result of the execution.
- */
- static Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValue* thisValue = noValue());
- };
-
-} // namespace JSC
-
-#endif // KJS_Interpreter_h
diff --git a/JavaScriptCore/kjs/jsc.pro b/JavaScriptCore/kjs/jsc.pro
deleted file mode 100644
index 2a30d65..0000000
--- a/JavaScriptCore/kjs/jsc.pro
+++ /dev/null
@@ -1,35 +0,0 @@
-TEMPLATE = app
-TARGET = jsc
-DESTDIR = ..
-SOURCES = Shell.cpp
-QT -= gui
-INCLUDEPATH += $$PWD/.. \
- $$PWD \
- $$PWD/../bindings \
- $$PWD/../bindings/c \
- $$PWD/../wtf \
- $$PWD/../VM
-CONFIG -= app_bundle
-DEFINES += BUILDING_QT__
-CONFIG += building-libs
-
-CONFIG(release) {
- DEFINES += NDEBUG USE_SYSTEM_MALLOC
-}
-
-include($$PWD/../../WebKit.pri)
-
-CONFIG += link_pkgconfig
-
-QMAKE_RPATHDIR += $$OUTPUT_DIR/lib
-
-isEmpty(OUTPUT_DIR):OUTPUT_DIR=$$PWD/../..
-include($$OUTPUT_DIR/config.pri)
-OBJECTS_DIR = tmp
-OBJECTS_DIR_WTR = $$OBJECTS_DIR/
-win32-*: OBJECTS_DIR_WTR ~= s|/|\|
-include($$PWD/../JavaScriptCore.pri)
-
-lessThan(QT_MINOR_VERSION, 4) {
- DEFINES += QT_BEGIN_NAMESPACE="" QT_END_NAMESPACE=""
-}
diff --git a/JavaScriptCore/kjs/keywords.table b/JavaScriptCore/kjs/keywords.table
deleted file mode 100644
index 490c1cc..0000000
--- a/JavaScriptCore/kjs/keywords.table
+++ /dev/null
@@ -1,72 +0,0 @@
-# main keywords
-@begin mainTable 41
-
-# types
-null NULLTOKEN
-true TRUETOKEN
-false FALSETOKEN
-
-# keywords
-break BREAK
-case CASE
-catch CATCH
-const CONSTTOKEN
-default DEFAULT
-finally FINALLY
-for FOR
-instanceof INSTANCEOF
-new NEW
-var VAR
-continue CONTINUE
-function FUNCTION
-return RETURN
-void VOIDTOKEN
-delete DELETETOKEN
-if IF
-this THISTOKEN
-do DO
-while WHILE
-else ELSE
-in INTOKEN
-switch SWITCH
-throw THROW
-try TRY
-typeof TYPEOF
-with WITH
-debugger DEBUGGER
-
-# reserved for future use
-class RESERVED
-enum RESERVED
-export RESERVED
-extends RESERVED
-import RESERVED
-super RESERVED
-
-# these words are reserved for future use in the ECMA spec, but not in WinIE
-# (see http://bugs.webkit.org/show_bug.cgi?id=6179)
-# abstract RESERVED
-# boolean RESERVED
-# byte RESERVED
-# char RESERVED
-# double RESERVED
-# final RESERVED
-# float RESERVED
-# goto RESERVED
-# implements RESERVED
-# int RESERVED
-# interface RESERVED
-# long RESERVED
-# native RESERVED
-# package RESERVED
-# private RESERVED
-# protected RESERVED
-# public RESERVED
-# short RESERVED
-# static RESERVED
-# synchronized RESERVED
-# throws RESERVED
-# transient RESERVED
-# volatile RESERVED
-@end
-
diff --git a/JavaScriptCore/kjs/lexer.cpp b/JavaScriptCore/kjs/lexer.cpp
deleted file mode 100644
index 7313b12..0000000
--- a/JavaScriptCore/kjs/lexer.cpp
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "lexer.h"
-
-#include "dtoa.h"
-#include "JSFunction.h"
-#include "nodes.h"
-#include "NodeInfo.h"
-#include "JSGlobalObjectFunctions.h"
-#include <ctype.h>
-#include <limits.h>
-#include <string.h>
-#include <wtf/Assertions.h>
-#include <wtf/unicode/Unicode.h>
-
-using namespace WTF;
-using namespace Unicode;
-
-// we can't specify the namespace in yacc's C output, so do it here
-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 C++
-int kjsyylex(void* lvalp, void* llocp, void* globalData)
-{
- return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
-}
-
-namespace JSC {
-
-static bool isDecimalDigit(int);
-
-static const size_t initialReadBufferCapacity = 32;
-static const size_t initialStringTableCapacity = 64;
-
-Lexer::Lexer(JSGlobalData* globalData)
- : yylineno(1)
- , m_restrKeyword(false)
- , m_eatNextIdentifier(false)
- , m_stackToken(-1)
- , m_lastToken(-1)
- , m_position(0)
- , m_code(0)
- , m_length(0)
- , m_atLineStart(true)
- , m_current(0)
- , m_next1(0)
- , m_next2(0)
- , m_next3(0)
- , m_currentOffset(0)
- , m_nextOffset1(0)
- , m_nextOffset2(0)
- , m_nextOffset3(0)
- , m_globalData(globalData)
- , m_mainTable(JSC::mainTable)
-{
- m_buffer8.reserveCapacity(initialReadBufferCapacity);
- m_buffer16.reserveCapacity(initialReadBufferCapacity);
- m_strings.reserveCapacity(initialStringTableCapacity);
- m_identifiers.reserveCapacity(initialStringTableCapacity);
-}
-
-Lexer::~Lexer()
-{
- m_mainTable.deleteTable();
-}
-
-void Lexer::setCode(const SourceCode& source)
-{
- yylineno = source.firstLine();
- m_restrKeyword = false;
- m_delimited = false;
- m_eatNextIdentifier = false;
- m_stackToken = -1;
- m_lastToken = -1;
-
- m_position = 0;
- m_source = &source;
- m_code = source.data();
- m_length = source.length();
- m_skipLF = false;
- m_skipCR = false;
- m_error = false;
- m_atLineStart = true;
-
- // read first characters
- shift(4);
-}
-
-void Lexer::shift(unsigned p)
-{
- // ECMA-262 calls for stripping Cf characters here, but we only do this for BOM,
- // see <https://bugs.webkit.org/show_bug.cgi?id=4931>.
-
- while (p--) {
- m_current = m_next1;
- m_next1 = m_next2;
- m_next2 = m_next3;
- m_currentOffset = m_nextOffset1;
- m_nextOffset1 = m_nextOffset2;
- m_nextOffset2 = m_nextOffset3;
- do {
- if (m_position >= m_length) {
- m_nextOffset3 = m_position;
- m_position++;
- m_next3 = -1;
- break;
- }
- m_nextOffset3 = m_position;
- m_next3 = m_code[m_position++];
- } while (m_next3 == 0xFEFF);
- }
-}
-
-// called on each new line
-void Lexer::nextLine()
-{
- yylineno++;
- m_atLineStart = true;
-}
-
-void Lexer::setDone(State s)
-{
- m_state = s;
- m_done = true;
-}
-
-int Lexer::lex(void* p1, void* p2)
-{
- YYSTYPE* lvalp = static_cast<YYSTYPE*>(p1);
- YYLTYPE* llocp = static_cast<YYLTYPE*>(p2);
- int token = 0;
- m_state = Start;
- unsigned short stringType = 0; // either single or double quotes
- m_buffer8.clear();
- m_buffer16.clear();
- m_done = false;
- m_terminator = false;
- m_skipLF = false;
- m_skipCR = false;
-
- // did we push a token on the stack previously ?
- // (after an automatic semicolon insertion)
- if (m_stackToken >= 0) {
- setDone(Other);
- token = m_stackToken;
- m_stackToken = 0;
- }
- int startOffset = m_currentOffset;
- while (!m_done) {
- if (m_skipLF && m_current != '\n') // found \r but not \n afterwards
- m_skipLF = false;
- if (m_skipCR && m_current != '\r') // found \n but not \r afterwards
- m_skipCR = false;
- if (m_skipLF || m_skipCR) { // found \r\n or \n\r -> eat the second one
- m_skipLF = false;
- m_skipCR = false;
- shift(1);
- }
- switch (m_state) {
- case Start:
- startOffset = m_currentOffset;
- if (isWhiteSpace()) {
- // do nothing
- } else if (m_current == '/' && m_next1 == '/') {
- shift(1);
- m_state = InSingleLineComment;
- } else if (m_current == '/' && m_next1 == '*') {
- shift(1);
- m_state = InMultiLineComment;
- } else if (m_current == -1) {
- if (!m_terminator && !m_delimited) {
- // automatic semicolon insertion if program incomplete
- token = ';';
- m_stackToken = 0;
- setDone(Other);
- } else
- setDone(Eof);
- } else if (isLineTerminator()) {
- nextLine();
- m_terminator = true;
- if (m_restrKeyword) {
- token = ';';
- setDone(Other);
- }
- } else if (m_current == '"' || m_current == '\'') {
- m_state = InString;
- stringType = static_cast<unsigned short>(m_current);
- } else if (isIdentStart(m_current)) {
- record16(m_current);
- m_state = InIdentifierOrKeyword;
- } else if (m_current == '\\')
- m_state = InIdentifierStartUnicodeEscapeStart;
- else if (m_current == '0') {
- record8(m_current);
- m_state = InNum0;
- } else if (isDecimalDigit(m_current)) {
- record8(m_current);
- m_state = InNum;
- } else if (m_current == '.' && isDecimalDigit(m_next1)) {
- record8(m_current);
- m_state = InDecimal;
- // <!-- marks the beginning of a line comment (for www usage)
- } else if (m_current == '<' && m_next1 == '!' && m_next2 == '-' && m_next3 == '-') {
- shift(3);
- m_state = InSingleLineComment;
- // same for -->
- } else if (m_atLineStart && m_current == '-' && m_next1 == '-' && m_next2 == '>') {
- shift(2);
- m_state = InSingleLineComment;
- } else {
- token = matchPunctuator(lvalp->intValue, m_current, m_next1, m_next2, m_next3);
- if (token != -1)
- setDone(Other);
- else
- setDone(Bad);
- }
- break;
- case InString:
- if (m_current == stringType) {
- shift(1);
- setDone(String);
- } else if (isLineTerminator() || m_current == -1)
- setDone(Bad);
- else if (m_current == '\\')
- m_state = InEscapeSequence;
- else
- record16(m_current);
- break;
- // Escape Sequences inside of strings
- case InEscapeSequence:
- if (isOctalDigit(m_current)) {
- if (m_current >= '0' && m_current <= '3' &&
- isOctalDigit(m_next1) && isOctalDigit(m_next2)) {
- record16(convertOctal(m_current, m_next1, m_next2));
- shift(2);
- m_state = InString;
- } else if (isOctalDigit(m_current) && isOctalDigit(m_next1)) {
- record16(convertOctal('0', m_current, m_next1));
- shift(1);
- m_state = InString;
- } else if (isOctalDigit(m_current)) {
- record16(convertOctal('0', '0', m_current));
- m_state = InString;
- } else
- setDone(Bad);
- } else if (m_current == 'x')
- m_state = InHexEscape;
- else if (m_current == 'u')
- m_state = InUnicodeEscape;
- else if (isLineTerminator()) {
- nextLine();
- m_state = InString;
- } else {
- record16(singleEscape(static_cast<unsigned short>(m_current)));
- m_state = InString;
- }
- break;
- case InHexEscape:
- if (isHexDigit(m_current) && isHexDigit(m_next1)) {
- m_state = InString;
- record16(convertHex(m_current, m_next1));
- shift(1);
- } else if (m_current == stringType) {
- record16('x');
- shift(1);
- setDone(String);
- } else {
- record16('x');
- record16(m_current);
- m_state = InString;
- }
- break;
- case InUnicodeEscape:
- if (isHexDigit(m_current) && isHexDigit(m_next1) && isHexDigit(m_next2) && isHexDigit(m_next3)) {
- record16(convertUnicode(m_current, m_next1, m_next2, m_next3));
- shift(3);
- m_state = InString;
- } else if (m_current == stringType) {
- record16('u');
- shift(1);
- setDone(String);
- } else
- setDone(Bad);
- break;
- case InSingleLineComment:
- if (isLineTerminator()) {
- nextLine();
- m_terminator = true;
- if (m_restrKeyword) {
- token = ';';
- setDone(Other);
- } else
- m_state = Start;
- } else if (m_current == -1)
- setDone(Eof);
- break;
- case InMultiLineComment:
- if (m_current == -1)
- setDone(Bad);
- else if (isLineTerminator())
- nextLine();
- else if (m_current == '*' && m_next1 == '/') {
- m_state = Start;
- shift(1);
- }
- break;
- case InIdentifierOrKeyword:
- case InIdentifier:
- if (isIdentPart(m_current))
- record16(m_current);
- else if (m_current == '\\')
- m_state = InIdentifierPartUnicodeEscapeStart;
- else
- setDone(m_state == InIdentifierOrKeyword ? IdentifierOrKeyword : Identifier);
- break;
- case InNum0:
- if (m_current == 'x' || m_current == 'X') {
- record8(m_current);
- m_state = InHex;
- } else if (m_current == '.') {
- record8(m_current);
- m_state = InDecimal;
- } else if (m_current == 'e' || m_current == 'E') {
- record8(m_current);
- m_state = InExponentIndicator;
- } else if (isOctalDigit(m_current)) {
- record8(m_current);
- m_state = InOctal;
- } else if (isDecimalDigit(m_current)) {
- record8(m_current);
- m_state = InDecimal;
- } else
- setDone(Number);
- break;
- case InHex:
- if (isHexDigit(m_current))
- record8(m_current);
- else
- setDone(Hex);
- break;
- case InOctal:
- if (isOctalDigit(m_current))
- record8(m_current);
- else if (isDecimalDigit(m_current)) {
- record8(m_current);
- m_state = InDecimal;
- } else
- setDone(Octal);
- break;
- case InNum:
- if (isDecimalDigit(m_current))
- record8(m_current);
- else if (m_current == '.') {
- record8(m_current);
- m_state = InDecimal;
- } else if (m_current == 'e' || m_current == 'E') {
- record8(m_current);
- m_state = InExponentIndicator;
- } else
- setDone(Number);
- break;
- case InDecimal:
- if (isDecimalDigit(m_current))
- record8(m_current);
- else if (m_current == 'e' || m_current == 'E') {
- record8(m_current);
- m_state = InExponentIndicator;
- } else
- setDone(Number);
- break;
- case InExponentIndicator:
- if (m_current == '+' || m_current == '-')
- record8(m_current);
- else if (isDecimalDigit(m_current)) {
- record8(m_current);
- m_state = InExponent;
- } else
- setDone(Bad);
- break;
- case InExponent:
- if (isDecimalDigit(m_current))
- record8(m_current);
- else
- setDone(Number);
- break;
- case InIdentifierStartUnicodeEscapeStart:
- if (m_current == 'u')
- m_state = InIdentifierStartUnicodeEscape;
- else
- setDone(Bad);
- break;
- case InIdentifierPartUnicodeEscapeStart:
- if (m_current == 'u')
- m_state = InIdentifierPartUnicodeEscape;
- else
- setDone(Bad);
- break;
- case InIdentifierStartUnicodeEscape:
- if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) {
- setDone(Bad);
- break;
- }
- token = convertUnicode(m_current, m_next1, m_next2, m_next3);
- shift(3);
- if (!isIdentStart(token)) {
- setDone(Bad);
- break;
- }
- record16(token);
- m_state = InIdentifier;
- break;
- case InIdentifierPartUnicodeEscape:
- if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) {
- setDone(Bad);
- break;
- }
- token = convertUnicode(m_current, m_next1, m_next2, m_next3);
- shift(3);
- if (!isIdentPart(token)) {
- setDone(Bad);
- break;
- }
- record16(token);
- m_state = InIdentifier;
- break;
- default:
- ASSERT(!"Unhandled state in switch statement");
- }
-
- // move on to the next character
- if (!m_done)
- shift(1);
- if (m_state != Start && m_state != InSingleLineComment)
- m_atLineStart = false;
- }
-
- // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
- if ((m_state == Number || m_state == Octal || m_state == Hex) && isIdentStart(m_current))
- m_state = Bad;
-
- // terminate string
- m_buffer8.append('\0');
-
-#ifdef KJS_DEBUG_LEX
- fprintf(stderr, "line: %d ", lineNo());
- fprintf(stderr, "yytext (%x): ", m_buffer8[0]);
- fprintf(stderr, "%s ", m_buffer8.data());
-#endif
-
- double dval = 0;
- if (m_state == Number)
- dval = strtod(m_buffer8.data(), 0L);
- else if (m_state == Hex) { // scan hex numbers
- const char* p = m_buffer8.data() + 2;
- while (char c = *p++) {
- dval *= 16;
- dval += convertHex(c);
- }
-
- if (dval >= mantissaOverflowLowerBound)
- dval = parseIntOverflow(m_buffer8.data() + 2, p - (m_buffer8.data() + 3), 16);
-
- m_state = Number;
- } else if (m_state == Octal) { // scan octal number
- const char* p = m_buffer8.data() + 1;
- while (char c = *p++) {
- dval *= 8;
- dval += c - '0';
- }
-
- if (dval >= mantissaOverflowLowerBound)
- dval = parseIntOverflow(m_buffer8.data() + 1, p - (m_buffer8.data() + 2), 8);
-
- m_state = Number;
- }
-
-#ifdef KJS_DEBUG_LEX
- switch (m_state) {
- case Eof:
- printf("(EOF)\n");
- break;
- case Other:
- printf("(Other)\n");
- break;
- case Identifier:
- printf("(Identifier)/(Keyword)\n");
- break;
- case String:
- printf("(String)\n");
- break;
- case Number:
- printf("(Number)\n");
- break;
- default:
- printf("(unknown)");
- }
-#endif
-
- if (m_state != Identifier)
- m_eatNextIdentifier = false;
-
- m_restrKeyword = false;
- m_delimited = false;
- llocp->first_line = yylineno;
- llocp->last_line = yylineno;
- llocp->first_column = startOffset;
- llocp->last_column = m_currentOffset;
- switch (m_state) {
- case Eof:
- token = 0;
- break;
- case Other:
- if (token == '}' || token == ';')
- m_delimited = true;
- break;
- case Identifier:
- // Apply anonymous-function hack below (eat the identifier).
- if (m_eatNextIdentifier) {
- m_eatNextIdentifier = false;
- token = lex(lvalp, llocp);
- break;
- }
- lvalp->ident = makeIdentifier(m_buffer16);
- token = IDENT;
- break;
- case IdentifierOrKeyword: {
- lvalp->ident = makeIdentifier(m_buffer16);
- const HashEntry* entry = m_mainTable.entry(m_globalData, *lvalp->ident);
- if (!entry) {
- // Lookup for keyword failed, means this is an identifier.
- token = IDENT;
- break;
- }
- token = entry->lexerValue();
- // Hack for "f = function somename() { ... }"; too hard to get into the grammar.
- m_eatNextIdentifier = token == FUNCTION && m_lastToken == '=';
- if (token == CONTINUE || token == BREAK || token == RETURN || token == THROW)
- m_restrKeyword = true;
- break;
- }
- case String:
- // Atomize constant strings in case they're later used in property lookup.
- lvalp->ident = makeIdentifier(m_buffer16);
- token = STRING;
- break;
- case Number:
- lvalp->doubleValue = dval;
- token = NUMBER;
- break;
- case Bad:
-#ifdef KJS_DEBUG_LEX
- fprintf(stderr, "yylex: ERROR.\n");
-#endif
- m_error = true;
- return -1;
- default:
- ASSERT(!"unhandled numeration value in switch");
- m_error = true;
- return -1;
- }
- m_lastToken = token;
- return token;
-}
-
-bool Lexer::isWhiteSpace() const
-{
- return m_current == '\t' || m_current == 0x0b || m_current == 0x0c || isSeparatorSpace(m_current);
-}
-
-bool Lexer::isLineTerminator()
-{
- bool cr = (m_current == '\r');
- bool lf = (m_current == '\n');
- if (cr)
- m_skipLF = true;
- else if (lf)
- m_skipCR = true;
- return cr || lf || m_current == 0x2028 || m_current == 0x2029;
-}
-
-bool Lexer::isIdentStart(int c)
-{
- return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other))
- || c == '$' || c == '_';
-}
-
-bool Lexer::isIdentPart(int c)
-{
- return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other
- | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector))
- || c == '$' || c == '_';
-}
-
-static bool isDecimalDigit(int c)
-{
- return (c >= '0' && c <= '9');
-}
-
-bool Lexer::isHexDigit(int c)
-{
- return (c >= '0' && c <= '9'
- || c >= 'a' && c <= 'f'
- || c >= 'A' && c <= 'F');
-}
-
-bool Lexer::isOctalDigit(int c)
-{
- return (c >= '0' && c <= '7');
-}
-
-int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4)
-{
- if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
- shift(4);
- return URSHIFTEQUAL;
- }
- if (c1 == '=' && c2 == '=' && c3 == '=') {
- shift(3);
- return STREQ;
- }
- if (c1 == '!' && c2 == '=' && c3 == '=') {
- shift(3);
- return STRNEQ;
- }
- if (c1 == '>' && c2 == '>' && c3 == '>') {
- shift(3);
- return URSHIFT;
- }
- if (c1 == '<' && c2 == '<' && c3 == '=') {
- shift(3);
- return LSHIFTEQUAL;
- }
- if (c1 == '>' && c2 == '>' && c3 == '=') {
- shift(3);
- return RSHIFTEQUAL;
- }
- if (c1 == '<' && c2 == '=') {
- shift(2);
- return LE;
- }
- if (c1 == '>' && c2 == '=') {
- shift(2);
- return GE;
- }
- if (c1 == '!' && c2 == '=') {
- shift(2);
- return NE;
- }
- if (c1 == '+' && c2 == '+') {
- shift(2);
- if (m_terminator)
- return AUTOPLUSPLUS;
- return PLUSPLUS;
- }
- if (c1 == '-' && c2 == '-') {
- shift(2);
- if (m_terminator)
- return AUTOMINUSMINUS;
- return MINUSMINUS;
- }
- if (c1 == '=' && c2 == '=') {
- shift(2);
- return EQEQ;
- }
- if (c1 == '+' && c2 == '=') {
- shift(2);
- return PLUSEQUAL;
- }
- if (c1 == '-' && c2 == '=') {
- shift(2);
- return MINUSEQUAL;
- }
- if (c1 == '*' && c2 == '=') {
- shift(2);
- return MULTEQUAL;
- }
- if (c1 == '/' && c2 == '=') {
- shift(2);
- return DIVEQUAL;
- }
- if (c1 == '&' && c2 == '=') {
- shift(2);
- return ANDEQUAL;
- }
- if (c1 == '^' && c2 == '=') {
- shift(2);
- return XOREQUAL;
- }
- if (c1 == '%' && c2 == '=') {
- shift(2);
- return MODEQUAL;
- }
- if (c1 == '|' && c2 == '=') {
- shift(2);
- return OREQUAL;
- }
- if (c1 == '<' && c2 == '<') {
- shift(2);
- return LSHIFT;
- }
- if (c1 == '>' && c2 == '>') {
- shift(2);
- return RSHIFT;
- }
- if (c1 == '&' && c2 == '&') {
- shift(2);
- return AND;
- }
- if (c1 == '|' && c2 == '|') {
- shift(2);
- return OR;
- }
-
- switch (c1) {
- case '=':
- case '>':
- case '<':
- case ',':
- case '!':
- case '~':
- case '?':
- case ':':
- case '.':
- case '+':
- case '-':
- case '*':
- case '/':
- case '&':
- case '|':
- case '^':
- case '%':
- case '(':
- case ')':
- case '[':
- case ']':
- case ';':
- shift(1);
- return static_cast<int>(c1);
- case '{':
- charPos = m_position - 4;
- shift(1);
- return OPENBRACE;
- case '}':
- charPos = m_position - 4;
- shift(1);
- return CLOSEBRACE;
- default:
- return -1;
- }
-}
-
-unsigned short Lexer::singleEscape(unsigned short c)
-{
- switch (c) {
- case 'b':
- return 0x08;
- case 't':
- return 0x09;
- case 'n':
- return 0x0A;
- case 'v':
- return 0x0B;
- case 'f':
- return 0x0C;
- case 'r':
- return 0x0D;
- case '"':
- return 0x22;
- case '\'':
- return 0x27;
- case '\\':
- return 0x5C;
- default:
- return c;
- }
-}
-
-unsigned short Lexer::convertOctal(int c1, int c2, int c3)
-{
- return static_cast<unsigned short>((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
-}
-
-unsigned char Lexer::convertHex(int c)
-{
- if (c >= '0' && c <= '9')
- return static_cast<unsigned char>(c - '0');
- if (c >= 'a' && c <= 'f')
- return static_cast<unsigned char>(c - 'a' + 10);
- return static_cast<unsigned char>(c - 'A' + 10);
-}
-
-unsigned char Lexer::convertHex(int c1, int c2)
-{
- return ((convertHex(c1) << 4) + convertHex(c2));
-}
-
-UChar Lexer::convertUnicode(int c1, int c2, int c3, int c4)
-{
- unsigned char highByte = (convertHex(c1) << 4) + convertHex(c2);
- unsigned char lowByte = (convertHex(c3) << 4) + convertHex(c4);
- return (highByte << 8 | lowByte);
-}
-
-void Lexer::record8(int c)
-{
- ASSERT(c >= 0);
- ASSERT(c <= 0xff);
- m_buffer8.append(static_cast<char>(c));
-}
-
-void Lexer::record16(int c)
-{
- ASSERT(c >= 0);
- ASSERT(c <= USHRT_MAX);
- record16(UChar(static_cast<unsigned short>(c)));
-}
-
-void Lexer::record16(UChar c)
-{
- m_buffer16.append(c);
-}
-
-bool Lexer::scanRegExp()
-{
- m_buffer16.clear();
- bool lastWasEscape = false;
- bool inBrackets = false;
-
- while (1) {
- if (isLineTerminator() || m_current == -1)
- return false;
- else if (m_current != '/' || lastWasEscape == true || inBrackets == true) {
- // keep track of '[' and ']'
- if (!lastWasEscape) {
- if ( m_current == '[' && !inBrackets )
- inBrackets = true;
- if ( m_current == ']' && inBrackets )
- inBrackets = false;
- }
- record16(m_current);
- lastWasEscape =
- !lastWasEscape && (m_current == '\\');
- } else { // end of regexp
- m_pattern = UString(m_buffer16);
- m_buffer16.clear();
- shift(1);
- break;
- }
- shift(1);
- }
-
- while (isIdentPart(m_current)) {
- record16(m_current);
- shift(1);
- }
- m_flags = UString(m_buffer16);
-
- return true;
-}
-
-void Lexer::clear()
-{
- deleteAllValues(m_strings);
- Vector<UString*> newStrings;
- newStrings.reserveCapacity(initialStringTableCapacity);
- m_strings.swap(newStrings);
-
- deleteAllValues(m_identifiers);
- Vector<JSC::Identifier*> newIdentifiers;
- newIdentifiers.reserveCapacity(initialStringTableCapacity);
- m_identifiers.swap(newIdentifiers);
-
- Vector<char> newBuffer8;
- newBuffer8.reserveCapacity(initialReadBufferCapacity);
- m_buffer8.swap(newBuffer8);
-
- Vector<UChar> newBuffer16;
- newBuffer16.reserveCapacity(initialReadBufferCapacity);
- m_buffer16.swap(newBuffer16);
-
- m_pattern = 0;
- m_flags = 0;
-}
-
-Identifier* Lexer::makeIdentifier(const Vector<UChar>& buffer)
-{
- JSC::Identifier* identifier = new JSC::Identifier(m_globalData, buffer.data(), buffer.size());
- m_identifiers.append(identifier);
- return identifier;
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/lexer.h b/JavaScriptCore/kjs/lexer.h
deleted file mode 100644
index 16bc4b6..0000000
--- a/JavaScriptCore/kjs/lexer.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2007 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef Lexer_h
-#define Lexer_h
-
-#include "lookup.h"
-#include "ustring.h"
-#include <wtf/Vector.h>
-#include "SourceCode.h"
-
-namespace JSC {
-
- class Identifier;
- class RegExp;
-
- class Lexer : Noncopyable {
- public:
- void setCode(const SourceCode&);
- int lex(void* lvalp, void* llocp);
-
- int lineNo() const { return yylineno; }
-
- bool prevTerminator() const { return m_terminator; }
-
- enum State {
- Start,
- IdentifierOrKeyword,
- Identifier,
- InIdentifierOrKeyword,
- InIdentifier,
- InIdentifierStartUnicodeEscapeStart,
- InIdentifierStartUnicodeEscape,
- InIdentifierPartUnicodeEscapeStart,
- InIdentifierPartUnicodeEscape,
- InSingleLineComment,
- InMultiLineComment,
- InNum,
- InNum0,
- InHex,
- InOctal,
- InDecimal,
- InExponentIndicator,
- InExponent,
- Hex,
- Octal,
- Number,
- String,
- Eof,
- InString,
- InEscapeSequence,
- InHexEscape,
- InUnicodeEscape,
- Other,
- Bad
- };
-
- bool scanRegExp();
- const UString& pattern() const { return m_pattern; }
- const UString& flags() const { return m_flags; }
-
- static unsigned char convertHex(int);
- static unsigned char convertHex(int c1, int c2);
- static UChar convertUnicode(int c1, int c2, int c3, int c4);
- static bool isIdentStart(int);
- static bool isIdentPart(int);
- static bool isHexDigit(int);
-
- bool sawError() const { return m_error; }
-
- void clear();
- SourceCode sourceCode(int openBrace, int closeBrace, int firstLine) { return SourceCode(m_source->provider(), m_source->startOffset() + openBrace + 1, m_source->startOffset() + closeBrace, firstLine); }
-
- private:
- friend class JSGlobalData;
- Lexer(JSGlobalData*);
- ~Lexer();
-
- void setDone(State);
- void shift(unsigned int p);
- void nextLine();
- int lookupKeyword(const char *);
-
- bool isWhiteSpace() const;
- bool isLineTerminator();
- static bool isOctalDigit(int);
-
- int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4);
- static unsigned short singleEscape(unsigned short);
- static unsigned short convertOctal(int c1, int c2, int c3);
-
- void record8(int);
- void record16(int);
- void record16(UChar);
-
- JSC::Identifier* makeIdentifier(const Vector<UChar>& buffer);
-
- int yylineno;
- int yycolumn;
-
- bool m_done;
- Vector<char> m_buffer8;
- Vector<UChar> m_buffer16;
- bool m_terminator;
- bool m_restrKeyword;
- bool m_delimited; // encountered delimiter like "'" and "}" on last run
- bool m_skipLF;
- bool m_skipCR;
- bool m_eatNextIdentifier;
- int m_stackToken;
- int m_lastToken;
-
- State m_state;
- unsigned int m_position;
- const SourceCode* m_source;
- const UChar* m_code;
- unsigned int m_length;
- int m_atLineStart;
- bool m_error;
-
- // current and following unicode characters (int to allow for -1 for end-of-file marker)
- int m_current;
- int m_next1;
- int m_next2;
- int m_next3;
-
- int m_currentOffset;
- int m_nextOffset1;
- int m_nextOffset2;
- int m_nextOffset3;
-
- Vector<UString*> m_strings;
- Vector<JSC::Identifier*> m_identifiers;
-
- JSGlobalData* m_globalData;
-
- UString m_pattern;
- UString m_flags;
-
- const HashTable m_mainTable;
- };
-
-} // namespace JSC
-
-#endif // Lexer_h
diff --git a/JavaScriptCore/kjs/lookup.cpp b/JavaScriptCore/kjs/lookup.cpp
deleted file mode 100644
index 41ac725..0000000
--- a/JavaScriptCore/kjs/lookup.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "lookup.h"
-
-#include "PrototypeFunction.h"
-
-namespace JSC {
-
-void HashTable::createTable(JSGlobalData* globalData) const
-{
- ASSERT(!table);
- HashEntry* entries = new HashEntry[hashSizeMask + 1];
- for (int i = 0; i <= hashSizeMask; ++i)
- entries[i].setKey(0);
- for (int i = 0; values[i].key; ++i) {
- UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef();
- int hashIndex = identifier->computedHash() & hashSizeMask;
- ASSERT(!entries[hashIndex].key());
- entries[hashIndex].initialize(identifier, values[i].attributes, values[i].value1, values[i].value2);
- }
- table = entries;
-}
-
-void HashTable::deleteTable() const
-{
- if (table) {
- for (int i = 0; i != hashSizeMask + 1; ++i) {
- if (UString::Rep* key = table[i].key())
- key->deref();
- }
- delete [] table;
- table = 0;
- }
-}
-
-void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
-{
- ASSERT(entry->attributes() & Function);
- JSValue** location = thisObj->getDirectLocation(propertyName);
-
- if (!location) {
- PrototypeFunction* function = new (exec) PrototypeFunction(exec, entry->functionLength(), propertyName, entry->function());
- thisObj->putDirect(propertyName, function, entry->attributes());
- location = thisObj->getDirectLocation(propertyName);
- }
-
- slot.setValueSlot(thisObj, location, thisObj->offsetForLocation(location));
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/lookup.h b/JavaScriptCore/kjs/lookup.h
deleted file mode 100644
index a547613..0000000
--- a/JavaScriptCore/kjs/lookup.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef KJS_lookup_h
-#define KJS_lookup_h
-
-#include "ExecState.h"
-#include "JSFunction.h"
-#include "JSGlobalObject.h"
-#include "JSObject.h"
-#include "PropertySlot.h"
-#include "identifier.h"
-#include <stdio.h>
-#include <wtf/Assertions.h>
-
-namespace JSC {
-
- // Hash table generated by the create_hash_table script.
- struct HashTableValue {
- const char* key; // property name
- unsigned char attributes; // JSObject attributes
- intptr_t value1;
- intptr_t value2;
- };
-
- // FIXME: There is no reason this get function can't be simpler.
- // ie. typedef JSValue* (*GetFunction)(ExecState*, JSObject* baseObject)
- typedef PropertySlot::GetValueFunc GetFunction;
- typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue* value);
-
- class HashEntry {
- public:
- void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2)
- {
- m_key = key;
- m_attributes = attributes;
- m_u.store.value1 = v1;
- m_u.store.value2 = v2;
- }
-
- void setKey(UString::Rep* key) { m_key = key; }
- UString::Rep* key() const { return m_key; }
-
- unsigned char attributes() const { return m_attributes; }
-
- NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; }
- unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_u.function.length); }
-
- GetFunction propertyGetter() const { ASSERT(!(m_attributes & Function)); return m_u.property.get; }
- PutFunction propertyPutter() const { ASSERT(!(m_attributes & Function)); return m_u.property.put; }
-
- intptr_t lexerValue() const { ASSERT(!m_attributes); return m_u.lexer.value; }
-
- private:
- UString::Rep* m_key;
- unsigned char m_attributes; // JSObject attributes
-
- union {
- struct {
- intptr_t value1;
- intptr_t value2;
- } store;
- struct {
- NativeFunction functionValue;
- intptr_t length; // number of arguments for function
- } function;
- struct {
- GetFunction get;
- PutFunction put;
- } property;
- struct {
- intptr_t value;
- intptr_t unused;
- } lexer;
- } m_u;
- };
-
- struct HashTable {
- int hashSizeMask; // Precomputed size for the hash table (minus 1).
- const HashTableValue* values; // Fixed values generated by script.
- mutable const HashEntry* table; // Table allocated at runtime.
-
- ALWAYS_INLINE void initializeIfNeeded(JSGlobalData* globalData) const
- {
- if (!table)
- createTable(globalData);
- }
-
- ALWAYS_INLINE void initializeIfNeeded(ExecState* exec) const
- {
- if (!table)
- createTable(&exec->globalData());
- }
-
- void deleteTable() const;
-
- // Find an entry in the table, and return the entry.
- ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const
- {
- initializeIfNeeded(globalData);
- return entry(identifier);
- }
-
- ALWAYS_INLINE const HashEntry* entry(ExecState* exec, const Identifier& identifier) const
- {
- initializeIfNeeded(exec);
- return entry(identifier);
- }
-
- private:
- ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const
- {
- ASSERT(table);
- const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & hashSizeMask];
- if (entry->key() != identifier.ustring().rep())
- return 0;
- return entry;
- }
-
- // Convert the hash table keys to identifiers.
- void createTable(JSGlobalData*) const;
- };
-
- void setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
-
- /**
- * This method does it all (looking in the hashtable, checking for function
- * overrides, creating the function or retrieving from cache, calling
- * getValueProperty in case of a non-function property, forwarding to parent if
- * unknown property).
- */
- template <class ThisImp, class ParentImp>
- inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
- {
- const HashEntry* entry = table->entry(exec, propertyName);
-
- if (!entry) // not found, forward to parent
- return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
-
- if (entry->attributes() & Function)
- setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
- else
- slot.setCustom(thisObj, entry->propertyGetter());
-
- return true;
- }
-
- /**
- * Simplified version of getStaticPropertySlot in case there are only functions.
- * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
- * a dummy getValueProperty.
- */
- template <class ParentImp>
- inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
- {
- if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertySlot(exec, propertyName, slot))
- return true;
-
- const HashEntry* entry = table->entry(exec, propertyName);
- if (!entry)
- return false;
-
- setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
- return true;
- }
-
- /**
- * Simplified version of getStaticPropertySlot in case there are no functions, only "values".
- * Using this instead of getStaticPropertySlot removes the need for a FuncImp class.
- */
- template <class ThisImp, class ParentImp>
- inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
- {
- const HashEntry* entry = table->entry(exec, propertyName);
-
- if (!entry) // not found, forward to parent
- return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
-
- ASSERT(!(entry->attributes() & Function));
-
- slot.setCustom(thisObj, entry->propertyGetter());
- return true;
- }
-
- /**
- * This one is for "put".
- * It looks up a hash entry for the property to be set. If an entry
- * is found it sets the value and returns true, else it returns false.
- */
- template <class ThisImp>
- inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue* value, const HashTable* table, ThisImp* thisObj)
- {
- const HashEntry* entry = table->entry(exec, propertyName);
-
- if (!entry)
- return false;
-
- if (entry->attributes() & Function) // function: put as override property
- thisObj->putDirect(propertyName, value);
- else if (!(entry->attributes() & ReadOnly))
- entry->propertyPutter()(exec, thisObj, value);
-
- return true;
- }
-
- /**
- * This one is for "put".
- * It calls lookupPut<ThisImp>() to set the value. If that call
- * returns false (meaning no entry in the hash table was found),
- * then it calls put() on the ParentImp class.
- */
- template <class ThisImp, class ParentImp>
- inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue* value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot)
- {
- if (!lookupPut<ThisImp>(exec, propertyName, value, table, thisObj))
- thisObj->ParentImp::put(exec, propertyName, value, slot); // not found: forward to parent
- }
-
-} // namespace JSC
-
-#endif // KJS_lookup_h
diff --git a/JavaScriptCore/kjs/nodes.cpp b/JavaScriptCore/kjs/nodes.cpp
deleted file mode 100644
index b4aeb28..0000000
--- a/JavaScriptCore/kjs/nodes.cpp
+++ /dev/null
@@ -1,1882 +0,0 @@
-/*
-* 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 Apple Inc. All rights reserved.
-* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
-* Copyright (C) 2007 Maks Orlovich
-* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Library General Public
-* License as published by the Free Software Foundation; either
-* version 2 of the License, or (at your option) any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Library General Public License for more details.
-*
-* You should have received a copy of the GNU Library General Public License
-* along with this library; see the file COPYING.LIB. If not, write to
-* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-* Boston, MA 02110-1301, USA.
-*
-*/
-
-#include "config.h"
-#include "nodes.h"
-
-#include "CodeGenerator.h"
-#include "ExecState.h"
-#include "JSGlobalObject.h"
-#include "JSStaticScopeObject.h"
-#include "LabelScope.h"
-#include "Parser.h"
-#include "PropertyNameArray.h"
-#include "RegExpObject.h"
-#include "SamplingTool.h"
-#include "Debugger.h"
-#include "lexer.h"
-#include "operations.h"
-#include <math.h>
-#include <wtf/Assertions.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/HashSet.h>
-#include <wtf/MathExtras.h>
-#include <wtf/RefCountedLeakCounter.h>
-#include <wtf/Threading.h>
-
-using namespace WTF;
-
-namespace JSC {
-
-// ------------------------------ Node -----------------------------------------
-
-#ifndef NDEBUG
-static RefCountedLeakCounter parserRefCountedCounter("JSC::Node");
-#endif
-
-ParserRefCounted::ParserRefCounted(JSGlobalData* globalData)
- : m_globalData(globalData)
-{
-#ifndef NDEBUG
- parserRefCountedCounter.increment();
-#endif
- if (!m_globalData->newParserObjects)
- m_globalData->newParserObjects = new HashSet<ParserRefCounted*>;
- m_globalData->newParserObjects->add(this);
- ASSERT(m_globalData->newParserObjects->contains(this));
-}
-
-ParserRefCounted::~ParserRefCounted()
-{
-#ifndef NDEBUG
- parserRefCountedCounter.decrement();
-#endif
-}
-
-void ParserRefCounted::ref()
-{
- // bumping from 0 to 1 is just removing from the new nodes set
- if (m_globalData->newParserObjects) {
- HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this);
- if (it != m_globalData->newParserObjects->end()) {
- m_globalData->newParserObjects->remove(it);
- ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
- return;
- }
- }
-
- ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
-
- if (!m_globalData->parserObjectExtraRefCounts)
- m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
- m_globalData->parserObjectExtraRefCounts->add(this);
-}
-
-void ParserRefCounted::deref()
-{
- ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
-
- if (!m_globalData->parserObjectExtraRefCounts) {
- delete this;
- return;
- }
-
- HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this);
- if (it == m_globalData->parserObjectExtraRefCounts->end())
- delete this;
- else
- m_globalData->parserObjectExtraRefCounts->remove(it);
-}
-
-bool ParserRefCounted::hasOneRef()
-{
- if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) {
- ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
- return false;
- }
-
- ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
-
- if (!m_globalData->parserObjectExtraRefCounts)
- return true;
-
- return !m_globalData->parserObjectExtraRefCounts->contains(this);
-}
-
-void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData)
-{
- if (!globalData->newParserObjects)
- return;
-
-#ifndef NDEBUG
- HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end();
- for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it)
- ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it));
-#endif
- deleteAllValues(*globalData->newParserObjects);
- delete globalData->newParserObjects;
- globalData->newParserObjects = 0;
-}
-
-Node::Node(JSGlobalData* globalData)
- : ParserRefCounted(globalData)
-{
- m_line = globalData->lexer->lineNo();
-}
-
-static void substitute(UString& string, const UString& substring) JSC_FAST_CALL;
-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(CodeGenerator& generator, ErrorType e, const char* msg)
-{
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg));
- generator.emitThrow(exception);
- return exception;
-}
-
-RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
-{
- UString message = msg;
- substitute(message, label.ustring());
- generator.emitExpressionInfo(m_divot, m_startOffset, m_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)
-{
- m_line = firstLine;
- m_lastLine = lastLine;
-}
-
-// ------------------------------ SourceElements --------------------------------
-
-void SourceElements::append(PassRefPtr<StatementNode> statement)
-{
- if (statement->isEmptyStatement())
- return;
-
- m_statements.append(statement);
-}
-
-// ------------------------------ NullNode -------------------------------------
-
-RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (dst == ignoredResult())
- return 0;
- return generator.emitLoad(dst, jsNull());
-}
-
-// ------------------------------ BooleanNode ----------------------------------
-
-RegisterID* BooleanNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (dst == ignoredResult())
- return 0;
- return generator.emitLoad(dst, m_value);
-}
-
-// ------------------------------ NumberNode -----------------------------------
-
-RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (dst == ignoredResult())
- return 0;
- return generator.emitLoad(dst, m_double);
-}
-
-// ------------------------------ StringNode -----------------------------------
-
-RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (dst == ignoredResult())
- return 0;
- return generator.emitLoad(dst, m_value);
-}
-
-// ------------------------------ RegExpNode -----------------------------------
-
-RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
- if (!regExp->isValid())
- return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
- if (dst == ignoredResult())
- return 0;
- return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
-}
-
-// ------------------------------ ThisNode -------------------------------------
-
-RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (dst == ignoredResult())
- return 0;
- return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
-}
-
-// ------------------------------ ResolveNode ----------------------------------
-
-bool ResolveNode::isPure(CodeGenerator& generator) const
-{
- return generator.isLocal(m_ident);
-}
-
-RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (dst == 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::emitCode(CodeGenerator& 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<RegisterID> 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());
-}
-
-// ------------------------------ ObjectLiteralNode ----------------------------
-
-RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (!m_list) {
- if (dst == ignoredResult())
- return 0;
- return generator.emitNewObject(generator.finalDestination(dst));
- }
- return generator.emitNode(dst, m_list.get());
-}
-
-// ------------------------------ PropertyListNode -----------------------------
-
-RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> newObj = generator.tempDestination(dst);
-
- generator.emitNewObject(newObj.get());
-
- for (PropertyListNode* p = this; p; p = p->m_next.get()) {
- RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
-
- 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator));
- RegisterID* property = generator.emitNode(m_subscript.get());
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
-}
-
-// ------------------------------ DotAccessorNode --------------------------------
-
-RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RegisterID* base = generator.emitNode(m_base.get());
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
-}
-
-// ------------------------------ ArgumentListNode -----------------------------
-
-RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- ASSERT(m_expr);
- return generator.emitNode(dst, m_expr.get());
-}
-
-// ------------------------------ NewExprNode ----------------------------------
-
-RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
- return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
-}
-
-RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.tempDestination(dst);
- RefPtr<RegisterID> func = generator.newTemporary();
- generator.emitResolveWithBase(base.get(), func.get(), generator.propertyNames().eval);
- return generator.emitCallEval(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
-}
-
-RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
- return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
-}
-
-RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (RefPtr<RegisterID> local = generator.registerFor(m_ident))
- return generator.emitCall(generator.finalDestination(dst), local.get(), 0, m_args.get(), m_divot, m_startOffset, m_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);
- return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
- }
-
- RefPtr<RegisterID> base = generator.tempDestination(dst);
- RefPtr<RegisterID> func = generator.newTemporary();
- int identifierStart = m_divot - m_startOffset;
- generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
- generator.emitResolveFunction(base.get(), func.get(), m_ident);
- return generator.emitCall(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
-}
-
-RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNode(m_base.get());
- RegisterID* property = generator.emitNode(m_subscript.get());
- generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
- RefPtr<RegisterID> function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
- return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
-}
-
-RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNode(m_base.get());
- generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
- RefPtr<RegisterID> function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
- return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
-}
-
-// ------------------------------ PostfixResolveNode ----------------------------------
-
-static RegisterID* emitPreIncOrDec(CodeGenerator& generator, RegisterID* srcDst, Operator oper)
-{
- return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
-}
-
-static RegisterID* emitPostIncOrDec(CodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
-{
- return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
-}
-
-RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (generator.isLocalConstant(m_ident)) {
- if (dst == ignoredResult())
- return 0;
- return generator.emitToJSNumber(generator.finalDestination(dst), local);
- }
-
- if (dst == 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 == 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(m_divot, m_startOffset, m_endOffset);
- RefPtr<RegisterID> value = generator.newTemporary();
- RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
- RegisterID* oldValue;
- if (dst == 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNode(m_base.get());
- RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
-
- generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
- RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
- RegisterID* oldValue;
- if (dst == 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(m_divot, m_startOffset, m_endOffset);
- generator.emitPutByVal(base.get(), property.get(), value.get());
- return oldValue;
-}
-
-// ------------------------------ PostfixDotNode ----------------------------------
-
-RegisterID* PostfixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNode(m_base.get());
-
- generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
- RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
- RegisterID* oldValue;
- if (dst == 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(m_divot, m_startOffset, m_endOffset);
- generator.emitPutById(base.get(), m_ident, value.get());
- return oldValue;
-}
-
-// ------------------------------ PostfixErrorNode -----------------------------------
-
-RegisterID* PostfixErrorNode::emitCode(CodeGenerator& 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (generator.registerFor(m_ident))
- return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
-
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
- return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
-}
-
-// ------------------------------ DeleteBracketNode -----------------------------------
-
-RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
- RegisterID* r1 = generator.emitNode(m_subscript.get());
-
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
-}
-
-// ------------------------------ DeleteDotNode -----------------------------------
-
-RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RegisterID* r0 = generator.emitNode(m_base.get());
-
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
-}
-
-// ------------------------------ DeleteValueNode -----------------------------------
-
-RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- generator.emitNode(ignoredResult(), m_expr.get());
-
- // delete on a non-location expression ignores the value and returns true
- return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
-}
-
-// ------------------------------ VoidNode -------------------------------------
-
-RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (dst == ignoredResult()) {
- generator.emitNode(ignoredResult(), m_expr.get());
- return 0;
- }
- RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
- return generator.emitLoad(dst, jsUndefined());
-}
-
-// ------------------------------ TypeOfValueNode -----------------------------------
-
-RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (dst == 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 == ignoredResult())
- return 0;
- return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
-}
-
-// ------------------------------ TypeOfValueNode -----------------------------------
-
-RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (dst == ignoredResult()) {
- generator.emitNode(ignoredResult(), m_expr.get());
- return 0;
- }
- RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
- return generator.emitTypeOf(generator.finalDestination(dst), src.get());
-}
-
-// ------------------------------ PrefixResolveNode ----------------------------------
-
-RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (generator.isLocalConstant(m_ident)) {
- if (dst == ignoredResult())
- return 0;
- RefPtr<RegisterID> 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<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(m_divot, m_startOffset, m_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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNode(m_base.get());
- RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
- RefPtr<RegisterID> propDst = generator.tempDestination(dst);
-
- generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_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(m_divot, m_startOffset, m_endOffset);
- generator.emitPutByVal(base.get(), property.get(), value);
- return generator.moveToDestinationIfNeeded(dst, propDst.get());
-}
-
-// ------------------------------ PrefixDotNode ----------------------------------
-
-RegisterID* PrefixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNode(m_base.get());
- RefPtr<RegisterID> propDst = generator.tempDestination(dst);
-
- generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_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(m_divot, m_startOffset, m_endOffset);
- generator.emitPutById(base.get(), m_ident, value);
- return generator.moveToDestinationIfNeeded(dst, propDst.get());
-}
-
-// ------------------------------ PrefixErrorNode -----------------------------------
-
-RegisterID* PrefixErrorNode::emitCode(CodeGenerator& 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RegisterID* src = generator.emitNode(m_expr.get());
- return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src, m_expr->resultDescriptor());
-}
-
-// ------------------------------ Binary Operation Nodes -----------------------------------
-
-RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- OpcodeID opcode = this->opcode();
- if (opcode == op_neq) {
- if (m_expr1->isNull() || m_expr2->isNull()) {
- RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
- return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown());
- }
- }
-
- RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
- RegisterID* src2 = generator.emitNode(m_expr2.get());
- return generator.emitBinaryOp(opcode, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
-}
-
-RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (m_expr1->isNull() || m_expr2->isNull()) {
- RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
- return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown());
- }
-
- RefPtr<RegisterID> 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
- RegisterID* src2 = generator.emitNode(m_expr2.get());
- return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
-}
-
-RegisterID* ThrowableBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
- RegisterID* src2 = generator.emitNode(m_expr2.get());
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
-}
-
-RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
- RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
-
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
-
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
-}
-
-// ------------------------------ Binary Logical Nodes ----------------------------
-
-RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> temp = generator.tempDestination(dst);
- RefPtr<LabelID> target = generator.newLabel();
-
- generator.emitNode(temp.get(), m_expr1.get());
- if (m_operator == OpLogicalAnd)
- generator.emitJumpIfFalse(temp.get(), target.get());
- else
- generator.emitJumpIfTrue(temp.get(), target.get());
- generator.emitNode(temp.get(), m_expr2.get());
- generator.emitLabel(target.get());
-
- return generator.moveToDestinationIfNeeded(dst, temp.get());
-}
-
-// ------------------------------ ConditionalNode ------------------------------
-
-RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> newDst = generator.finalDestination(dst);
- RefPtr<LabelID> beforeElse = generator.newLabel();
- RefPtr<LabelID> afterElse = generator.newLabel();
-
- RegisterID* cond = generator.emitNode(m_logical.get());
- generator.emitJumpIfFalse(cond, beforeElse.get());
-
- generator.emitNode(newDst.get(), m_expr1.get());
- generator.emitJump(afterElse.get());
-
- generator.emitLabel(beforeElse.get());
- generator.emitNode(newDst.get(), m_expr2.get());
-
- generator.emitLabel(afterElse.get());
-
- return newDst.get();
-}
-
-// ------------------------------ ReadModifyResolveNode -----------------------------------
-
-// FIXME: should this be moved to be a method on CodeGenerator?
-static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types)
-{
- OpcodeID opcode;
- switch (oper) {
- case OpMultEq:
- opcode = op_mul;
- break;
- case OpDivEq:
- opcode = op_div;
- break;
- case OpPlusEq:
- opcode = op_add;
- break;
- case OpMinusEq:
- opcode = op_sub;
- break;
- case OpLShift:
- opcode = op_lshift;
- break;
- case OpRShift:
- opcode = op_rshift;
- break;
- case OpURShift:
- opcode = op_urshift;
- break;
- case OpAndEq:
- opcode = op_bitand;
- break;
- case OpXOrEq:
- opcode = op_bitxor;
- break;
- case OpOrEq:
- opcode = op_bitor;
- break;
- case OpModEq:
- opcode = op_mod;
- break;
- default:
- ASSERT_NOT_REACHED();
- return dst;
- }
-
- return generator.emitBinaryOp(opcode, dst, src1, src2, types);
-}
-
-RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (generator.isLocalConstant(m_ident)) {
- RegisterID* src2 = generator.emitNode(m_right.get());
- return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
- }
-
- if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
- RefPtr<RegisterID> result = generator.newTemporary();
- generator.emitMove(result.get(), local);
- RegisterID* src2 = generator.emitNode(m_right.get());
- emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
- generator.emitMove(local, result.get());
- return generator.moveToDestinationIfNeeded(dst, result.get());
- }
-
- RegisterID* src2 = generator.emitNode(m_right.get());
- RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
- 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* src2 = generator.emitNode(m_right.get());
- RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
- generator.emitPutScopedVar(depth, index, result, globalObject);
- return result;
- }
-
- RefPtr<RegisterID> src1 = generator.tempDestination(dst);
- generator.emitExpressionInfo(m_divot - m_startOffset + m_ident.size(), m_ident.size(), 0);
- RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
- RegisterID* src2 = generator.emitNode(m_right.get());
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
- return generator.emitPutById(base.get(), m_ident, result);
-}
-
-// ------------------------------ AssignResolveNode -----------------------------------
-
-RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (generator.isLocalConstant(m_ident))
- return generator.emitNode(dst, m_right.get());
-
- RegisterID* result = generator.emitNode(local, m_right.get());
- 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 == ignoredResult())
- dst = 0;
- RegisterID* value = generator.emitNode(dst, m_right.get());
- generator.emitPutScopedVar(depth, index, value, globalObject);
- return value;
- }
-
- RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
- if (dst == ignoredResult())
- dst = 0;
- RegisterID* value = generator.emitNode(dst, m_right.get());
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- return generator.emitPutById(base.get(), m_ident, value);
-}
-
-// ------------------------------ AssignDotNode -----------------------------------
-
-RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
- RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
- RegisterID* result = generator.emitNode(value.get(), m_right.get());
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- generator.emitPutById(base.get(), m_ident, result);
- return generator.moveToDestinationIfNeeded(dst, result);
-}
-
-// ------------------------------ ReadModifyDotNode -----------------------------------
-
-RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
-
- generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
- RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
- RegisterID* change = generator.emitNode(m_right.get());
- RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
-
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- return generator.emitPutById(base.get(), m_ident, updatedValue);
-}
-
-// ------------------------------ AssignErrorNode -----------------------------------
-
-RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
-{
- return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
-}
-
-// ------------------------------ AssignBracketNode -----------------------------------
-
-RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
- RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
- RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
- RegisterID* result = generator.emitNode(value.get(), m_right.get());
-
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- generator.emitPutByVal(base.get(), property.get(), result);
- return generator.moveToDestinationIfNeeded(dst, result);
-}
-
-RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
- RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
-
- generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
- RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
- RegisterID* change = generator.emitNode(m_right.get());
- RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
-
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- generator.emitPutByVal(base.get(), property.get(), updatedValue);
-
- return updatedValue;
-}
-
-// ------------------------------ CommaNode ------------------------------------
-
-RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- generator.emitNode(ignoredResult(), m_expr1.get());
- return generator.emitNode(dst, m_expr2.get());
-}
-
-// ------------------------------ ConstDeclNode ----------------------------------
-
-ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
- : ExpressionNode(globalData)
- , m_ident(ident)
- , m_init(init)
-{
-}
-
-RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
-{
- if (RegisterID* local = generator.constRegisterFor(m_ident)) {
- if (!m_init)
- return local;
-
- return generator.emitNode(local, m_init.get());
- }
-
- // FIXME: While this code should only be hit in eval code, it will potentially
- // assign to the wrong base if m_ident exists in an intervening dynamic scope.
- RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
- RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined());
- return generator.emitPutById(base.get(), m_ident, value);
-}
-
-RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
-{
- RegisterID* result = 0;
- for (ConstDeclNode* n = this; n; n = n->m_next.get())
- result = n->emitCodeSingle(generator);
-
- return result;
-}
-
-// ------------------------------ ConstStatementNode -----------------------------
-
-RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
-{
- return generator.emitNode(m_next.get());
-}
-
-// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
-
-static inline RegisterID* statementListEmitCode(StatementVector& statements, CodeGenerator& generator, RegisterID* dst)
-{
- StatementVector::iterator end = statements.end();
- for (StatementVector::iterator it = statements.begin(); it != end; ++it) {
- StatementNode* n = it->get();
- if (!n->isLoop())
- generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
- generator.emitNode(dst, n);
- }
- return 0;
-}
-
-static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
-{
- StatementVector::iterator it = statements.end();
- StatementVector::iterator begin = statements.begin();
- while (it != begin) {
- --it;
- stack.append((*it).get());
- }
-}
-
-// ------------------------------ BlockNode ------------------------------------
-
-BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
- : StatementNode(globalData)
-{
- if (children)
- children->releaseContentsIntoVector(m_children);
-}
-
-RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- return statementListEmitCode(m_children, generator, dst);
-}
-
-// ------------------------------ EmptyStatementNode ---------------------------
-
-RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
-{
- return dst;
-}
-
-// ------------------------------ DebuggerStatementNode ---------------------------
-
-RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
- return dst;
-}
-
-// ------------------------------ ExprStatementNode ----------------------------
-
-RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- ASSERT(m_expr);
- return generator.emitNode(dst, m_expr.get());
-}
-
-// ------------------------------ VarStatementNode ----------------------------
-
-RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
-{
- ASSERT(m_expr);
- return generator.emitNode(m_expr.get());
-}
-
-// ------------------------------ IfNode ---------------------------------------
-
-RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelID> afterThen = generator.newLabel();
-
- RegisterID* cond = generator.emitNode(m_condition.get());
- generator.emitJumpIfFalse(cond, afterThen.get());
-
- if (!m_ifBlock->isBlock())
- generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
-
- generator.emitNode(dst, m_ifBlock.get());
- generator.emitLabel(afterThen.get());
-
- // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
- return 0;
-}
-
-RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelID> beforeElse = generator.newLabel();
- RefPtr<LabelID> afterElse = generator.newLabel();
-
- RegisterID* cond = generator.emitNode(m_condition.get());
- generator.emitJumpIfFalse(cond, beforeElse.get());
-
- if (!m_ifBlock->isBlock())
- generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
-
- generator.emitNode(dst, m_ifBlock.get());
- generator.emitJump(afterElse.get());
-
- generator.emitLabel(beforeElse.get());
-
- if (!m_elseBlock->isBlock())
- generator.emitDebugHook(WillExecuteStatement, m_elseBlock->firstLine(), m_elseBlock->lastLine());
-
- generator.emitNode(dst, m_elseBlock.get());
-
- generator.emitLabel(afterElse.get());
-
- // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
- return 0;
-}
-
-// ------------------------------ DoWhileNode ----------------------------------
-
-RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
- RefPtr<LabelID> topOfLoop = generator.newLabel();
- generator.emitLabel(topOfLoop.get());
-
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-
- if (!m_statement->isBlock())
- generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
-
- RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
-
- generator.emitLabel(scope->continueTarget());
- generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
- RegisterID* cond = generator.emitNode(m_expr.get());
- generator.emitJumpIfTrue(cond, topOfLoop.get());
-
- generator.emitLabel(scope->breakTarget());
- return result.get();
-}
-
-// ------------------------------ WhileNode ------------------------------------
-
-RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
- generator.emitJump(scope->continueTarget());
-
- RefPtr<LabelID> topOfLoop = generator.newLabel();
- generator.emitLabel(topOfLoop.get());
-
- if (!m_statement->isBlock())
- generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
-
- generator.emitNode(dst, m_statement.get());
-
- generator.emitLabel(scope->continueTarget());
- generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
- RegisterID* cond = generator.emitNode(m_expr.get());
- 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (dst == ignoredResult())
- dst = 0;
-
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-
- if (m_expr1)
- generator.emitNode(ignoredResult(), m_expr1.get());
-
- RefPtr<LabelID> condition = generator.newLabel();
- generator.emitJump(condition.get());
-
- RefPtr<LabelID> topOfLoop = generator.newLabel();
- generator.emitLabel(topOfLoop.get());
-
- if (!m_statement->isBlock())
- generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
- RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
-
- generator.emitLabel(scope->continueTarget());
- if (m_expr3)
- generator.emitNode(ignoredResult(), m_expr3.get());
-
- generator.emitLabel(condition.get());
- if (m_expr2) {
- RegisterID* cond = generator.emitNode(m_expr2.get());
- generator.emitJumpIfTrue(cond, topOfLoop.get());
- } else
- generator.emitJump(topOfLoop.get());
-
- generator.emitLabel(scope->breakTarget());
- return result.get();
-}
-
-// ------------------------------ ForInNode ------------------------------------
-
-ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
- : StatementNode(globalData)
- , m_init(0L)
- , m_lexpr(l)
- , m_expr(expr)
- , m_statement(statement)
- , m_identIsVarDecl(false)
-{
-}
-
-ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
- : StatementNode(globalData)
- , m_ident(ident)
- , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset))
- , m_expr(expr)
- , m_statement(statement)
- , m_identIsVarDecl(true)
-{
- if (in) {
- AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true);
- node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot);
- m_init = node;
- }
- // for( var foo = bar in baz )
-}
-
-RegisterID* ForInNode::emitCode(CodeGenerator& 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<LabelID> continueTarget = generator.newLabel();
-
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-
- if (m_init)
- generator.emitNode(ignoredResult(), m_init.get());
- RegisterID* forInBase = generator.emitNode(m_expr.get());
- RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
- generator.emitJump(scope->continueTarget());
-
- RefPtr<LabelID> loopStart = generator.newLabel();
- generator.emitLabel(loopStart.get());
-
- RegisterID* propertyName;
- if (m_lexpr->isResolveNode()) {
- const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
- propertyName = generator.registerFor(ident);
- if (!propertyName) {
- propertyName = generator.newTemporary();
- RefPtr<RegisterID> protect = propertyName;
- RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
-
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- generator.emitPutById(base, ident, propertyName);
- }
- } else if (m_lexpr->isDotAccessorNode()) {
- DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
- 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.get());
- 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);
- }
-
- if (!m_statement->isBlock())
- generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
- generator.emitNode(dst, m_statement.get());
-
- generator.emitLabel(scope->continueTarget());
- generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
- generator.emitLabel(scope->breakTarget());
- return dst;
-}
-
-// ------------------------------ ContinueNode ---------------------------------
-
-// ECMA 12.7
-RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (generator.codeType() != FunctionCode)
- return emitThrowError(generator, SyntaxError, "Invalid return statement.");
-
- if (dst == ignoredResult())
- dst = 0;
- RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined());
- if (generator.scopeDepth()) {
- RefPtr<LabelID> l0 = generator.newLabel();
- generator.emitJumpScopes(l0.get(), 0);
- generator.emitLabel(l0.get());
- }
- generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
- return generator.emitReturn(r0);
-}
-
-// ------------------------------ WithNode -------------------------------------
-
-RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
- generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
- generator.emitPushScope(scope.get());
- RegisterID* result = generator.emitNode(dst, m_statement.get());
- generator.emitPopScope();
- return result;
-}
-
-// ------------------------------ 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();
- if ((typeForTable & ~SwitchNumber) || !JSImmediate::from(value)) {
- typeForTable = SwitchNeither;
- break;
- }
- int32_t intVal = static_cast<int32_t>(value);
- ASSERT(intVal == value);
- 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.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
- processClauseList(m_list2.get(), 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::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
-{
- RefPtr<LabelID> defaultLabel;
- Vector<RefPtr<LabelID>, 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.get(); 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.get(); 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.get(); list; list = list->getNext()) {
- generator.emitLabel(labelVector[i++].get());
- result = statementListEmitCode(list->getClause()->children(), generator, dst);
- }
-
- if (m_defaultClause) {
- generator.emitLabel(defaultLabel.get());
- result = statementListEmitCode(m_defaultClause->children(), generator, dst);
- }
-
- for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
- generator.emitLabel(labelVector[i++].get());
- result = statementListEmitCode(list->getClause()->children(), 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::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
-
- RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
- RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
-
- generator.emitLabel(scope->breakTarget());
- return r1;
-}
-
-// ------------------------------ LabelNode ------------------------------------
-
-RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (generator.breakTarget(m_name))
- return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
-
- RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
- RegisterID* r0 = generator.emitNode(dst, m_statement.get());
-
- generator.emitLabel(scope->breakTarget());
- return r0;
-}
-
-// ------------------------------ ThrowNode ------------------------------------
-
-RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- if (dst == ignoredResult())
- dst = 0;
- RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get());
- generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
- generator.emitThrow(expr.get());
- return dst;
-}
-
-// ------------------------------ TryNode --------------------------------------
-
-RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- RefPtr<LabelID> tryStartLabel = generator.newLabel();
- RefPtr<LabelID> tryEndLabel = generator.newLabel();
- RefPtr<LabelID> 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.get());
- generator.emitLabel(tryEndLabel.get());
-
- if (m_catchBlock) {
- RefPtr<LabelID> handlerEndLabel = generator.newLabel();
- generator.emitJump(handlerEndLabel.get());
- RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
- generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
- generator.emitNode(dst, m_catchBlock.get());
- generator.emitPopScope();
- generator.emitLabel(handlerEndLabel.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<LabelID> finallyEndLabel = generator.newLabel();
- generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
- // Use a label to record the subtle fact that sret will return to the
- // next instruction. sret is the only way to jump without an explicit label.
- generator.emitLabel(generator.newLabel().get());
- generator.emitJump(finallyEndLabel.get());
-
- // Finally block for exception path
- RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
- generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
- // Use a label to record the subtle fact that sret will return to the
- // next instruction. sret is the only way to jump without an explicit label.
- generator.emitLabel(generator.newLabel().get());
- generator.emitThrow(tempExceptionRegister.get());
-
- // emit the finally block itself
- generator.emitLabel(finallyStart.get());
- generator.emitNode(dst, m_finallyBlock.get());
- generator.emitSubroutineReturn(finallyReturnAddr.get());
-
- generator.emitLabel(finallyEndLabel.get());
- }
-
- return dst;
-}
-
-
-// ------------------------------ ScopeNode -----------------------------
-
-ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
- : BlockNode(globalData, children)
- , m_source(source)
- , m_features(features)
- , m_numConstants(numConstants)
-{
- if (varStack)
- m_varStack = *varStack;
- if (funcStack)
- m_functionStack = *funcStack;
-#if ENABLE(OPCODE_SAMPLING)
- globalData->machine->sampler()->notifyOfScope(this);
-#endif
-}
-
-// ------------------------------ ProgramNode -----------------------------
-
-ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
- : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
-{
-}
-
-ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
-{
- return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
-}
-
-// ------------------------------ EvalNode -----------------------------
-
-EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
- : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
-{
-}
-
-RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
-{
- generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
-
- RefPtr<RegisterID> dstRegister = generator.newTemporary();
- generator.emitLoad(dstRegister.get(), jsUndefined());
- statementListEmitCode(m_children, generator, dstRegister.get());
-
- generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
- generator.emitEnd(dstRegister.get());
- return 0;
-}
-
-void EvalNode::generateCode(ScopeChainNode* scopeChainNode)
-{
- ScopeChain scopeChain(scopeChainNode);
- JSGlobalObject* globalObject = scopeChain.globalObject();
-
- SymbolTable symbolTable;
- m_code.set(new EvalCodeBlock(this, globalObject, source().provider()));
-
- CodeGenerator generator(this, globalObject->debugger(), scopeChain, &symbolTable, m_code.get());
- generator.generate();
-}
-
-EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
-{
- return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
-}
-
-// ------------------------------ FunctionBodyNode -----------------------------
-
-FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
- : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
- , m_parameters(0)
- , m_parameterCount(0)
- , m_refCount(0)
-{
-}
-
-FunctionBodyNode::~FunctionBodyNode()
-{
- if (m_parameters)
- fastFree(m_parameters);
-}
-
-void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
-{
- Vector<Identifier> parameters;
- for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
- parameters.append(parameter->ident());
- size_t count = parameters.size();
-
- setSource(source);
- finishParsing(parameters.releaseBuffer(), count);
-}
-
-void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
-{
- ASSERT(!source().isNull());
- m_parameters = parameters;
- m_parameterCount = parameterCount;
-}
-
-void FunctionBodyNode::mark()
-{
- if (m_code)
- m_code->mark();
-}
-
-FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
-{
- return new FunctionBodyNode(globalData, children, varStack, funcStack, SourceCode(), features, numConstants);
-}
-
-FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
-{
- return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
-}
-
-void FunctionBodyNode::generateCode(ScopeChainNode* scopeChainNode)
-{
- ScopeChain scopeChain(scopeChainNode);
- JSGlobalObject* globalObject = scopeChain.globalObject();
-
- m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
-
- CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get());
- generator.generate();
-}
-
-RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
-{
- generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
- statementListEmitCode(m_children, generator, ignoredResult());
- if (!m_children.size() || !m_children.last()->isReturnNode()) {
- RegisterID* r0 = generator.emitLoad(0, jsUndefined());
- generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
- generator.emitReturn(r0);
- }
- return 0;
-}
-
-RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
-{
- generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
-
- RefPtr<RegisterID> dstRegister = generator.newTemporary();
- generator.emitLoad(dstRegister.get(), jsUndefined());
- statementListEmitCode(m_children, generator, dstRegister.get());
-
- generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
- generator.emitEnd(dstRegister.get());
- return 0;
-}
-
-void ProgramNode::generateCode(ScopeChainNode* scopeChainNode)
-{
- ScopeChain scopeChain(scopeChainNode);
- JSGlobalObject* globalObject = scopeChain.globalObject();
-
- m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
-
- CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack);
- generator.generate();
-}
-
-UString FunctionBodyNode::paramString() const
-{
- UString s("");
- for (size_t pos = 0; pos < m_parameterCount; ++pos) {
- if (!s.isEmpty())
- s += ", ";
- s += parameters()[pos].ustring();
- }
-
- return s;
-}
-
-Identifier* FunctionBodyNode::copyParameters()
-{
- Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
- VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
- return parameters;
-}
-
-// ------------------------------ FuncDeclNode ---------------------------------
-
-JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
-{
- return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
-}
-
-RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
-{
- return dst;
-}
-
-// ------------------------------ FuncExprNode ---------------------------------
-
-RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
- return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
-}
-
-JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
-{
- JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
-
- /*
- The Identifier in a FunctionExpression can be referenced from inside
- the FunctionExpression's FunctionBody to allow the function to call
- itself recursively. However, unlike in a FunctionDeclaration, the
- Identifier in a FunctionExpression cannot be referenced from and
- does not affect the scope enclosing the FunctionExpression.
- */
-
- if (!m_ident.isNull()) {
- JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
- func->scope().push(functionScopeObject);
- }
-
- return func;
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/nodes.h b/JavaScriptCore/kjs/nodes.h
deleted file mode 100644
index a70d350..0000000
--- a/JavaScriptCore/kjs/nodes.h
+++ /dev/null
@@ -1,2493 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef NODES_H_
-#define NODES_H_
-
-#include "Error.h"
-#include "JSString.h"
-#include "JSType.h"
-#include "Opcode.h"
-#include "RegisterID.h"
-#include "ResultType.h"
-#include "SourceCode.h"
-#include "SymbolTable.h"
-#include "regexp.h"
-#include <wtf/ListRefPtr.h>
-#include <wtf/MathExtras.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/UnusedParam.h>
-#include <wtf/Vector.h>
-
-#if PLATFORM(X86) && COMPILER(GCC)
-#define JSC_FAST_CALL __attribute__((regparm(3)))
-#else
-#define JSC_FAST_CALL
-#endif
-
-namespace JSC {
-
- class CodeBlock;
- class CodeGenerator;
- class FuncDeclNode;
- class Node;
- class EvalCodeBlock;
- class JSFunction;
- class ProgramCodeBlock;
- class PropertyListNode;
- class SourceStream;
-
- typedef unsigned int CodeFeatures;
-
- const CodeFeatures NoFeatures = 0;
- const CodeFeatures EvalFeature = 1 << 0;
- const CodeFeatures ClosureFeature = 1 << 1;
- const CodeFeatures AssignFeature = 1 << 2;
- const CodeFeatures ArgumentsFeature = 1 << 3;
- const CodeFeatures WithFeature = 1 << 4;
- const CodeFeatures CatchFeature = 1 << 5;
- const CodeFeatures ThisFeature = 1 << 6;
- const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature;
-
- enum Operator {
- OpEqual,
- OpPlusEq,
- OpMinusEq,
- OpMultEq,
- OpDivEq,
- OpPlusPlus,
- OpMinusMinus,
- OpAndEq,
- OpXOrEq,
- OpOrEq,
- OpModEq,
- OpLShift,
- OpRShift,
- OpURShift
- };
-
- enum LogicalOperator {
- OpLogicalAnd,
- OpLogicalOr
- };
-
- enum Precedence {
- PrecPrimary,
- PrecMember,
- PrecCall,
- PrecLeftHandSide,
- PrecPostfix,
- PrecUnary,
- PrecMultiplicative,
- PrecAdditive,
- PrecShift,
- PrecRelational,
- PrecEquality,
- PrecBitwiseAnd,
- PrecBitwiseXor,
- PrecBitwiseOr,
- PrecLogicalAnd,
- PrecLogicalOr,
- PrecConditional,
- PrecAssignment,
- PrecExpression
- };
-
- namespace DeclarationStacks {
- typedef Vector<Node*, 16> NodeStack;
- enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
- typedef Vector<std::pair<Identifier, unsigned>, 16> VarStack;
- typedef Vector<RefPtr<FuncDeclNode>, 16> FunctionStack;
- }
-
- struct SwitchInfo {
- enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString };
- uint32_t opcodeOffset;
- SwitchType switchType;
- };
-
- class ParserRefCounted : Noncopyable {
- protected:
- ParserRefCounted(JSGlobalData*) JSC_FAST_CALL;
-
- JSGlobalData* m_globalData;
-
- public:
- void ref() JSC_FAST_CALL;
- void deref() JSC_FAST_CALL;
- bool hasOneRef() JSC_FAST_CALL;
-
- static void deleteNewObjects(JSGlobalData*) JSC_FAST_CALL;
-
- virtual ~ParserRefCounted();
- };
-
- class Node : public ParserRefCounted {
- public:
- typedef DeclarationStacks::NodeStack NodeStack;
- typedef DeclarationStacks::VarStack VarStack;
- typedef DeclarationStacks::FunctionStack FunctionStack;
-
- Node(JSGlobalData*) JSC_FAST_CALL;
-
- /*
- 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.
-
- dst 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".
- */
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL
- {
- ASSERT_WITH_MESSAGE(0, "Don't know how to generate code for:\n%s\n", toString().ascii());
- UNUSED_PARAM(dst);
- return 0;
- } // FIXME: Make this pure virtual.
-
- UString toString() const JSC_FAST_CALL;
- int lineNo() const { return m_line; }
-
- virtual bool isReturnNode() const JSC_FAST_CALL { return false; }
-
- // Serialization.
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL = 0;
- virtual Precedence precedence() const = 0;
- virtual bool needsParensIfLeftmost() const { return false; }
-
- protected:
- int m_line;
- };
-
- class ExpressionNode : public Node {
- public:
- ExpressionNode(JSGlobalData* globalData, ResultType resultDesc = ResultType::unknown()) JSC_FAST_CALL
- : Node(globalData)
- , m_resultDesc(resultDesc)
- {
- }
-
- virtual bool isNumber() const JSC_FAST_CALL { return false; }
- virtual bool isString() const JSC_FAST_CALL { return false; }
- virtual bool isNull() const JSC_FAST_CALL { return false; }
- virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return false; }
- virtual bool isLocation() const JSC_FAST_CALL { return false; }
- virtual bool isResolveNode() const JSC_FAST_CALL { return false; }
- virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return false; }
- virtual bool isDotAccessorNode() const JSC_FAST_CALL { return false; }
-
- virtual ExpressionNode* stripUnaryPlus() { return this; }
-
- ResultType resultDescriptor() const JSC_FAST_CALL { return m_resultDesc; }
-
- // This needs to be in public in order to compile using GCC 3.x
- typedef enum { EvalOperator, FunctionCall } CallerType;
-
- private:
- ResultType m_resultDesc;
- };
-
- class StatementNode : public Node {
- public:
- StatementNode(JSGlobalData*) JSC_FAST_CALL;
- void setLoc(int line0, int line1) JSC_FAST_CALL;
- int firstLine() const JSC_FAST_CALL { return lineNo(); }
- int lastLine() const JSC_FAST_CALL { return m_lastLine; }
-
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- virtual bool isEmptyStatement() const JSC_FAST_CALL { return false; }
-
- virtual bool isBlock() const JSC_FAST_CALL { return false; }
- virtual bool isLoop() const JSC_FAST_CALL { return false; }
-
- private:
- int m_lastLine;
- };
-
- class NullNode : public ExpressionNode {
- public:
- NullNode(JSGlobalData* globalData) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::nullType())
- {
- }
-
- virtual bool isNull() const JSC_FAST_CALL { return true; }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
- };
-
- class BooleanNode : public ExpressionNode {
- public:
- BooleanNode(JSGlobalData* globalData, bool value) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::boolean())
- , m_value(value)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return true; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
-
- protected:
- bool m_value;
- };
-
- class NumberNode : public ExpressionNode {
- public:
- NumberNode(JSGlobalData* globalData, double v) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::constNumber())
- , m_double(v)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return signbit(m_double) ? PrecUnary : PrecPrimary; }
-
- virtual bool isNumber() const JSC_FAST_CALL { return true; }
- virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return true; }
- double value() const JSC_FAST_CALL { return m_double; }
- virtual void setValue(double d) JSC_FAST_CALL { m_double = d; }
-
- protected:
- double m_double;
- };
-
- class ImmediateNumberNode : public NumberNode {
- public:
- ImmediateNumberNode(JSGlobalData* globalData, JSValue* v, double d) JSC_FAST_CALL
- : NumberNode(globalData, d)
- , m_value(v)
- {
- ASSERT(v == JSImmediate::from(d));
- }
-
- virtual void setValue(double d) JSC_FAST_CALL { m_double = d; m_value = JSImmediate::from(d); ASSERT(m_value); }
-
- private:
- JSValue* m_value; // This is never a JSCell, only JSImmediate, thus no ProtectedPtr
- };
-
- class StringNode : public ExpressionNode {
- public:
- StringNode(JSGlobalData* globalData, const Identifier& v) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::string())
- , m_value(v)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual bool isString() const JSC_FAST_CALL { return true; }
- const Identifier& value() { return m_value; }
- virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return true; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
-
- private:
- Identifier m_value;
- };
-
- class ThrowableExpressionData {
- public:
- ThrowableExpressionData()
- : m_divot(static_cast<uint32_t>(-1))
- , m_startOffset(static_cast<uint16_t>(-1))
- , m_endOffset(static_cast<uint16_t>(-1))
- {
- }
-
- ThrowableExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset)
- : m_divot(divot)
- , m_startOffset(startOffset)
- , m_endOffset(endOffset)
- {
- }
-
- void setExceptionSourceCode(unsigned divot, unsigned startOffset, unsigned endOffset)
- {
- m_divot = divot;
- m_startOffset = startOffset;
- m_endOffset = endOffset;
- }
-
- uint32_t divot() const { return m_divot; }
- uint16_t startOffset() const { return m_startOffset; }
- uint16_t endOffset() const { return m_endOffset; }
-
- protected:
- RegisterID* emitThrowError(CodeGenerator&, ErrorType, const char* msg);
- RegisterID* emitThrowError(CodeGenerator&, ErrorType, const char* msg, const Identifier&);
- uint32_t m_divot;
- uint16_t m_startOffset;
- uint16_t m_endOffset;
- };
-
- class ThrowableSubExpressionData : public ThrowableExpressionData {
- public:
- ThrowableSubExpressionData()
- : ThrowableExpressionData()
- , m_subexpressionDivotOffset(0)
- , m_subexpressionEndOffset(0)
- {
- }
-
- ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset)
- : ThrowableExpressionData(divot, startOffset, endOffset)
- , m_subexpressionDivotOffset(0)
- , m_subexpressionEndOffset(0)
- {
- }
-
- void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) {
- ASSERT(subexpressionDivot <= m_divot);
- if ((m_divot - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot
- return;
- m_subexpressionDivotOffset = m_divot - subexpressionDivot;
- m_subexpressionEndOffset = subexpressionOffset;
- }
-
- protected:
- uint16_t m_subexpressionDivotOffset;
- uint16_t m_subexpressionEndOffset;
- };
-
- class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData {
- public:
- ThrowablePrefixedSubExpressionData()
- : ThrowableExpressionData()
- , m_subexpressionDivotOffset(0)
- , m_subexpressionStartOffset(0)
- {
- }
-
- ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset)
- : ThrowableExpressionData(divot, startOffset, endOffset)
- , m_subexpressionDivotOffset(0)
- , m_subexpressionStartOffset(0)
- {
- }
-
- void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) {
- ASSERT(subexpressionDivot >= m_divot);
- if ((subexpressionDivot - m_divot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot
- return;
- m_subexpressionDivotOffset = subexpressionDivot - m_divot;
- m_subexpressionStartOffset = subexpressionOffset;
- }
-
- protected:
- uint16_t m_subexpressionDivotOffset;
- uint16_t m_subexpressionStartOffset;
- };
-
- class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- RegExpNode(JSGlobalData* globalData, const UString& pattern, const UString& flags) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_pattern(pattern)
- , m_flags(flags)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
-
- private:
- UString m_pattern;
- UString m_flags;
- };
-
- class ThisNode : public ExpressionNode {
- public:
- ThisNode(JSGlobalData* globalData) JSC_FAST_CALL
- : ExpressionNode(globalData)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
- };
-
- class ResolveNode : public ExpressionNode {
- public:
- ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_ident(ident)
- , m_startOffset(startOffset)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
-
- virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL;
- virtual bool isLocation() const JSC_FAST_CALL { return true; }
- virtual bool isResolveNode() const JSC_FAST_CALL { return true; }
- const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
-
- protected:
- Identifier m_ident;
- int32_t m_startOffset;
-
- };
-
- class ElementNode : public Node {
- public:
- ElementNode(JSGlobalData* globalData, int elision, ExpressionNode* node) JSC_FAST_CALL
- : Node(globalData)
- , m_elision(elision)
- , m_node(node)
- {
- }
-
- ElementNode(JSGlobalData* globalData, ElementNode* l, int elision, ExpressionNode* node) JSC_FAST_CALL
- : Node(globalData)
- , m_elision(elision)
- , m_node(node)
- {
- l->m_next = this;
- }
-
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- int elision() const { return m_elision; }
- ExpressionNode* value() { return m_node.get(); }
-
- ElementNode* next() { return m_next.get(); }
- PassRefPtr<ElementNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
-
- private:
- ListRefPtr<ElementNode> m_next;
- int m_elision;
- RefPtr<ExpressionNode> m_node;
- };
-
- class ArrayNode : public ExpressionNode {
- public:
- ArrayNode(JSGlobalData* globalData, int elision) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_elision(elision)
- , m_optional(true)
- {
- }
-
- ArrayNode(JSGlobalData* globalData, ElementNode* element) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_element(element)
- , m_elision(0)
- , m_optional(false)
- {
- }
-
- ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_element(element)
- , m_elision(elision)
- , m_optional(true)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
-
- private:
- RefPtr<ElementNode> m_element;
- int m_elision;
- bool m_optional;
- };
-
- class PropertyNode : public Node {
- public:
- enum Type { Constant, Getter, Setter };
-
- PropertyNode(JSGlobalData* globalData, const Identifier& name, ExpressionNode* assign, Type type) JSC_FAST_CALL
- : Node(globalData)
- , m_name(name)
- , m_assign(assign)
- , m_type(type)
- {
- }
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- const Identifier& name() const { return m_name; }
-
- private:
- friend class PropertyListNode;
- Identifier m_name;
- RefPtr<ExpressionNode> m_assign;
- Type m_type;
- };
-
- class PropertyListNode : public Node {
- public:
- PropertyListNode(JSGlobalData* globalData, PropertyNode* node) JSC_FAST_CALL
- : Node(globalData)
- , m_node(node)
- {
- }
-
- PropertyListNode(JSGlobalData* globalData, PropertyNode* node, PropertyListNode* list) JSC_FAST_CALL
- : Node(globalData)
- , m_node(node)
- {
- list->m_next = this;
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- PassRefPtr<PropertyListNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
-
- private:
- friend class ObjectLiteralNode;
- RefPtr<PropertyNode> m_node;
- ListRefPtr<PropertyListNode> m_next;
- };
-
- class ObjectLiteralNode : public ExpressionNode {
- public:
- ObjectLiteralNode(JSGlobalData* globalData) JSC_FAST_CALL
- : ExpressionNode(globalData)
- {
- }
-
- ObjectLiteralNode(JSGlobalData* globalData, PropertyListNode* list) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_list(list)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
- virtual bool needsParensIfLeftmost() const { return true; }
-
- private:
- RefPtr<PropertyListNode> m_list;
- };
-
- class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- BracketAccessorNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_base(base)
- , m_subscript(subscript)
- , m_subscriptHasAssignments(subscriptHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecMember; }
-
- virtual bool isLocation() const JSC_FAST_CALL { return true; }
- virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return true; }
- ExpressionNode* base() JSC_FAST_CALL { return m_base.get(); }
- ExpressionNode* subscript() JSC_FAST_CALL { return m_subscript.get(); }
-
- private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- bool m_subscriptHasAssignments;
- };
-
- class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- DotAccessorNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_base(base)
- , m_ident(ident)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecMember; }
-
- virtual bool isLocation() const JSC_FAST_CALL { return true; }
- virtual bool isDotAccessorNode() const JSC_FAST_CALL { return true; }
- ExpressionNode* base() const JSC_FAST_CALL { return m_base.get(); }
- const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
-
- private:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- };
-
- class ArgumentListNode : public Node {
- public:
- ArgumentListNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : Node(globalData)
- , m_expr(expr)
- {
- }
-
- ArgumentListNode(JSGlobalData* globalData, ArgumentListNode* listNode, ExpressionNode* expr) JSC_FAST_CALL
- : Node(globalData)
- , m_expr(expr)
- {
- listNode->m_next = this;
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- PassRefPtr<ArgumentListNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
-
- ListRefPtr<ArgumentListNode> m_next;
- RefPtr<ExpressionNode> m_expr;
- };
-
- class ArgumentsNode : public Node {
- public:
- ArgumentsNode(JSGlobalData* globalData) JSC_FAST_CALL
- : Node(globalData)
- {
- }
-
- ArgumentsNode(JSGlobalData* globalData, ArgumentListNode* listNode) JSC_FAST_CALL
- : Node(globalData)
- , m_listNode(listNode)
- {
- }
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- RefPtr<ArgumentListNode> m_listNode;
- };
-
- class NewExprNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- NewExprNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_expr(expr)
- {
- }
-
- NewExprNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_expr(expr)
- , m_args(args)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecLeftHandSide; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<ArgumentsNode> m_args;
- };
-
- class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- EvalFunctionCallNode(JSGlobalData* globalData, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_args(args)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecCall; }
-
- private:
- RefPtr<ArgumentsNode> m_args;
- };
-
- class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- FunctionCallValueNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_expr(expr)
- , m_args(args)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecCall; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<ArgumentsNode> m_args;
- };
-
- class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- FunctionCallResolveNode(JSGlobalData* globalData, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_ident(ident)
- , m_args(args)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecCall; }
-
- protected:
- Identifier m_ident;
- RefPtr<ArgumentsNode> m_args;
- size_t m_index; // Used by LocalVarFunctionCallNode.
- size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode
- };
-
- class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
- public:
- FunctionCallBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableSubExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_subscript(subscript)
- , m_args(args)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecCall; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- RefPtr<ArgumentsNode> m_args;
- };
-
- class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData {
- public:
- FunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableSubExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_ident(ident)
- , m_args(args)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecCall; }
-
- private:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- RefPtr<ArgumentsNode> m_args;
- };
-
- class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::constNumber()) // could be reusable for pre?
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_ident(ident)
- {
- }
-
- protected:
- Identifier m_ident;
- };
-
- class PostfixResolveNode : public PrePostResolveNode {
- public:
- PostfixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
- , m_operator(oper)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
-
- protected:
- Operator m_operator;
- };
-
- class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
- public:
- PostfixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableSubExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_subscript(subscript)
- , m_operator(oper)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- Operator m_operator;
- };
-
- class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData {
- public:
- PostfixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableSubExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_ident(ident)
- , m_operator(oper)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- Operator m_operator;
- };
-
- class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData {
- public:
- PostfixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableSubExpressionData(divot, startOffset, endOffset)
- , m_expr(expr)
- , m_operator(oper)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- Operator m_operator;
- };
-
- class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- DeleteResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_ident(ident)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- Identifier m_ident;
- };
-
- class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- DeleteBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_subscript(subscript)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- };
-
- class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- DeleteDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_ident(ident)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- };
-
- class DeleteValueNode : public ExpressionNode {
- public:
- DeleteValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_expr(expr)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class VoidNode : public ExpressionNode {
- public:
- VoidNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_expr(expr)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class TypeOfResolveNode : public ExpressionNode {
- public:
- TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::string())
- , m_ident(ident)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
-
- protected:
- Identifier m_ident;
- size_t m_index; // Used by LocalTypeOfNode.
- };
-
- class TypeOfValueNode : public ExpressionNode {
- public:
- TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::string())
- , m_expr(expr)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class PrefixResolveNode : public PrePostResolveNode {
- public:
- PrefixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
- , m_operator(oper)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- protected:
- Operator m_operator;
- };
-
- class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
- public:
- PrefixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_subscript(subscript)
- , m_operator(oper)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- Operator m_operator;
- };
-
- class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
- public:
- PrefixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_ident(ident)
- , m_operator(oper)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- Operator m_operator;
- };
-
- class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- PrefixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_expr(expr)
- , m_operator(oper)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- Operator m_operator;
- };
-
- class UnaryOpNode : public ExpressionNode {
- public:
- UnaryOpNode(JSGlobalData* globalData, ExpressionNode* expr)
- : ExpressionNode(globalData)
- , m_expr(expr)
- {
- }
-
- UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr)
- : ExpressionNode(globalData, type)
- , m_expr(expr)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual OpcodeID opcode() const JSC_FAST_CALL = 0;
-
- protected:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class UnaryPlusNode : public UnaryOpNode {
- public:
- UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : UnaryOpNode(globalData, ResultType::constNumber(), expr)
- {
- }
-
- virtual ExpressionNode* stripUnaryPlus() { return m_expr.get(); }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_to_jsnumber; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
- };
-
- class NegateNode : public UnaryOpNode {
- public:
- NegateNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : UnaryOpNode(globalData, ResultType::reusableNumber(), expr)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_negate; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
- };
-
- class BitwiseNotNode : public UnaryOpNode {
- public:
- BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : UnaryOpNode(globalData, ResultType::reusableNumber(), expr)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitnot; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
- };
-
- class LogicalNotNode : public UnaryOpNode {
- public:
- LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : UnaryOpNode(globalData, ResultType::boolean(), expr)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_not; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
- };
-
- class BinaryOpNode : public ExpressionNode {
- public:
- BinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
- : ExpressionNode(globalData)
- , m_expr1(expr1)
- , m_expr2(expr2)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
- : ExpressionNode(globalData, type)
- , m_expr1(expr1)
- , m_expr2(expr2)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual OpcodeID opcode() const JSC_FAST_CALL = 0;
-
- protected:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- bool m_rightHasAssignments;
- };
-
- class ReverseBinaryOpNode : public ExpressionNode {
- public:
- ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
- : ExpressionNode(globalData)
- , m_expr1(expr1)
- , m_expr2(expr2)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
- : ExpressionNode(globalData, type)
- , m_expr1(expr1)
- , m_expr2(expr2)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual OpcodeID opcode() const JSC_FAST_CALL = 0;
-
- protected:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- bool m_rightHasAssignments;
- };
-
- class MultNode : public BinaryOpNode {
- public:
- MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_mul; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecMultiplicative; }
- };
-
- class DivNode : public BinaryOpNode {
- public:
- DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_div; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecMultiplicative; }
- };
-
- class ModNode : public BinaryOpNode {
- public:
- ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_mod; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecMultiplicative; }
- };
-
- class AddNode : public BinaryOpNode {
- public:
- AddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_add; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecAdditive; }
- };
-
- class SubNode : public BinaryOpNode {
- public:
- SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_sub; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecAdditive; }
- };
-
- class LeftShiftNode : public BinaryOpNode {
- public:
- LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_lshift; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecShift; }
- };
-
- class RightShiftNode : public BinaryOpNode {
- public:
- RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_rshift; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecShift; }
- };
-
- class UnsignedRightShiftNode : public BinaryOpNode {
- public:
- UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_urshift; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecShift; }
- };
-
- class LessNode : public BinaryOpNode {
- public:
- LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_less; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
- };
-
- class GreaterNode : public ReverseBinaryOpNode {
- public:
- GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : ReverseBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_less; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
- };
-
- class LessEqNode : public BinaryOpNode {
- public:
- LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_lesseq; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
- };
-
- class GreaterEqNode : public ReverseBinaryOpNode {
- public:
- GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : ReverseBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_lesseq; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
- };
-
- class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData {
- public:
- ThrowableBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments)
- {
- }
- ThrowableBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments)
- {
- }
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- };
-
- class InstanceOfNode : public ThrowableBinaryOpNode {
- public:
- InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : ThrowableBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_instanceof; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- };
-
- class InNode : public ThrowableBinaryOpNode {
- public:
- InNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : ThrowableBinaryOpNode(globalData, expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_in; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
- };
-
- class EqualNode : public BinaryOpNode {
- public:
- EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_eq; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecEquality; }
- };
-
- class NotEqualNode : public BinaryOpNode {
- public:
- NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_neq; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecEquality; }
- };
-
- class StrictEqualNode : public BinaryOpNode {
- public:
- StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_stricteq; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecEquality; }
- };
-
- class NotStrictEqualNode : public BinaryOpNode {
- public:
- NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_nstricteq; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecEquality; }
- };
-
- class BitAndNode : public BinaryOpNode {
- public:
- BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitand; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecBitwiseAnd; }
- };
-
- class BitOrNode : public BinaryOpNode {
- public:
- BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitor; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecBitwiseOr; }
- };
-
- class BitXOrNode : public BinaryOpNode {
- public:
- BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
- {
- }
-
- virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitxor; }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecBitwiseXor; }
- };
-
- /**
- * m_expr1 && m_expr2, m_expr1 || m_expr2
- */
- class LogicalOpNode : public ExpressionNode {
- public:
- LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::boolean())
- , m_expr1(expr1)
- , m_expr2(expr2)
- , m_operator(oper)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return (m_operator == OpLogicalAnd) ? PrecLogicalAnd : PrecLogicalOr; }
-
- private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- LogicalOperator m_operator;
- };
-
- /**
- * The ternary operator, "m_logical ? m_expr1 : m_expr2"
- */
- class ConditionalNode : public ExpressionNode {
- public:
- ConditionalNode(JSGlobalData* globalData, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_logical(logical)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecConditional; }
-
- private:
- RefPtr<ExpressionNode> m_logical;
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- ReadModifyResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_ident(ident)
- , m_right(right)
- , m_operator(oper)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
- size_t m_index; // Used by ReadModifyLocalVarNode.
- Operator m_operator : 31;
- bool m_rightHasAssignments : 1;
- };
-
- class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- AssignResolveNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_ident(ident)
- , m_right(right)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
- size_t m_index; // Used by ReadModifyLocalVarNode.
- bool m_rightHasAssignments;
- };
-
- class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
- public:
- ReadModifyBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableSubExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_subscript(subscript)
- , m_right(right)
- , m_operator(oper)
- , m_subscriptHasAssignments(subscriptHasAssignments)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- RefPtr<ExpressionNode> m_right;
- Operator m_operator : 30;
- bool m_subscriptHasAssignments : 1;
- bool m_rightHasAssignments : 1;
- };
-
- class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- AssignBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_subscript(subscript)
- , m_right(right)
- , m_subscriptHasAssignments(subscriptHasAssignments)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- RefPtr<ExpressionNode> m_right;
- bool m_subscriptHasAssignments : 1;
- bool m_rightHasAssignments : 1;
- };
-
- class AssignDotNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- AssignDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_ident(ident)
- , m_right(right)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
- bool m_rightHasAssignments;
- };
-
- class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData {
- public:
- ReadModifyDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableSubExpressionData(divot, startOffset, endOffset)
- , m_base(base)
- , m_ident(ident)
- , m_right(right)
- , m_operator(oper)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
- Operator m_operator : 31;
- bool m_rightHasAssignments : 1;
- };
-
- class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData {
- public:
- AssignErrorNode(JSGlobalData* globalData, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , ThrowableExpressionData(divot, startOffset, endOffset)
- , m_left(left)
- , m_operator(oper)
- , m_right(right)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_left;
- Operator m_operator;
- RefPtr<ExpressionNode> m_right;
- };
-
- class CommaNode : public ExpressionNode {
- public:
- CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecExpression; }
-
- private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class VarDeclCommaNode : public CommaNode {
- public:
- VarDeclCommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
- : CommaNode(globalData, expr1, expr2)
- {
- }
- virtual Precedence precedence() const { return PrecAssignment; }
- };
-
- class ConstDeclNode : public ExpressionNode {
- public:
- ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- PassRefPtr<ConstDeclNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
-
- Identifier m_ident;
- ListRefPtr<ConstDeclNode> m_next;
- RefPtr<ExpressionNode> m_init;
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual RegisterID* emitCodeSingle(CodeGenerator&) JSC_FAST_CALL;
- };
-
- class ConstStatementNode : public StatementNode {
- public:
- ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_next(next)
- {
- }
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- private:
- RefPtr<ConstDeclNode> m_next;
- };
-
- typedef Vector<RefPtr<StatementNode> > StatementVector;
-
- class SourceElements : public ParserRefCounted {
- public:
- SourceElements(JSGlobalData* globalData) : ParserRefCounted(globalData) {}
-
- void append(PassRefPtr<StatementNode>);
- void releaseContentsIntoVector(StatementVector& destination)
- {
- ASSERT(destination.isEmpty());
- m_statements.swap(destination);
- }
-
- private:
- StatementVector m_statements;
- };
-
- class BlockNode : public StatementNode {
- public:
- BlockNode(JSGlobalData*, SourceElements* children) JSC_FAST_CALL;
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- StatementVector& children() { return m_children; }
-
- virtual bool isBlock() const JSC_FAST_CALL { return true; }
- protected:
- StatementVector m_children;
- };
-
- class EmptyStatementNode : public StatementNode {
- public:
- EmptyStatementNode(JSGlobalData* globalData) JSC_FAST_CALL // debug
- : StatementNode(globalData)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual bool isEmptyStatement() const JSC_FAST_CALL { return true; }
- };
-
- class DebuggerStatementNode : public StatementNode {
- public:
- DebuggerStatementNode(JSGlobalData* globalData) JSC_FAST_CALL
- : StatementNode(globalData)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- };
-
- class ExprStatementNode : public StatementNode {
- public:
- ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_expr(expr)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class VarStatementNode : public StatementNode {
- public:
- VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_expr(expr)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class IfNode : public StatementNode {
- public:
- IfNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_condition(condition)
- , m_ifBlock(ifBlock)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- protected:
- RefPtr<ExpressionNode> m_condition;
- RefPtr<StatementNode> m_ifBlock;
- };
-
- class IfElseNode : public IfNode {
- public:
- IfElseNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) JSC_FAST_CALL
- : IfNode(globalData, condition, ifBlock)
- , m_elseBlock(elseBlock)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- private:
- RefPtr<StatementNode> m_elseBlock;
- };
-
- class DoWhileNode : public StatementNode {
- public:
- DoWhileNode(JSGlobalData* globalData, StatementNode* statement, ExpressionNode* expr) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_statement(statement)
- , m_expr(expr)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- virtual bool isLoop() const JSC_FAST_CALL { return true; }
- private:
- RefPtr<StatementNode> m_statement;
- RefPtr<ExpressionNode> m_expr;
- };
-
- class WhileNode : public StatementNode {
- public:
- WhileNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_expr(expr)
- , m_statement(statement)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- virtual bool isLoop() const JSC_FAST_CALL { return true; }
- private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<StatementNode> m_statement;
- };
-
- class ForNode : public StatementNode {
- public:
- ForNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_expr1(expr1)
- , m_expr2(expr2)
- , m_expr3(expr3)
- , m_statement(statement)
- , m_expr1WasVarDecl(expr1 && expr1WasVarDecl)
- {
- ASSERT(statement);
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- virtual bool isLoop() const JSC_FAST_CALL { return true; }
- private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- RefPtr<ExpressionNode> m_expr3;
- RefPtr<StatementNode> m_statement;
- bool m_expr1WasVarDecl;
- };
-
- class ForInNode : public StatementNode, public ThrowableExpressionData {
- public:
- ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*) JSC_FAST_CALL;
- ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset) JSC_FAST_CALL;
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- virtual bool isLoop() const JSC_FAST_CALL { return true; }
- private:
- Identifier m_ident;
- RefPtr<ExpressionNode> m_init;
- RefPtr<ExpressionNode> m_lexpr;
- RefPtr<ExpressionNode> m_expr;
- RefPtr<StatementNode> m_statement;
- bool m_identIsVarDecl;
- };
-
- class ContinueNode : public StatementNode, public ThrowableExpressionData {
- public:
- ContinueNode(JSGlobalData* globalData) JSC_FAST_CALL
- : StatementNode(globalData)
- {
- }
-
- ContinueNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_ident(ident)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- private:
- Identifier m_ident;
- };
-
- class BreakNode : public StatementNode, public ThrowableExpressionData {
- public:
- BreakNode(JSGlobalData* globalData) JSC_FAST_CALL
- : StatementNode(globalData)
- {
- }
-
- BreakNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_ident(ident)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- private:
- Identifier m_ident;
- };
-
- class ReturnNode : public StatementNode, public ThrowableExpressionData {
- public:
- ReturnNode(JSGlobalData* globalData, ExpressionNode* value) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_value(value)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual bool isReturnNode() const JSC_FAST_CALL { return true; }
-
- private:
- RefPtr<ExpressionNode> m_value;
- };
-
- class WithNode : public StatementNode {
- public:
- WithNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_expr(expr)
- , m_statement(statement)
- , m_divot(divot)
- , m_expressionLength(expressionLength)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<StatementNode> m_statement;
- uint32_t m_divot;
- uint32_t m_expressionLength;
- };
-
- class LabelNode : public StatementNode, public ThrowableExpressionData {
- public:
- LabelNode(JSGlobalData* globalData, const Identifier& name, StatementNode* statement) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_name(name)
- , m_statement(statement)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- private:
- Identifier m_name;
- RefPtr<StatementNode> m_statement;
- };
-
- class ThrowNode : public StatementNode, public ThrowableExpressionData {
- public:
- ThrowNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_expr(expr)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class TryNode : public StatementNode {
- public:
- TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_tryBlock(tryBlock)
- , m_exceptionIdent(exceptionIdent)
- , m_catchBlock(catchBlock)
- , m_finallyBlock(finallyBlock)
- {
- }
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL;
-
- private:
- RefPtr<StatementNode> m_tryBlock;
- Identifier m_exceptionIdent;
- RefPtr<StatementNode> m_catchBlock;
- RefPtr<StatementNode> m_finallyBlock;
- };
-
- class ParameterNode : public Node {
- public:
- ParameterNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
- : Node(globalData)
- , m_ident(ident)
- {
- }
-
- ParameterNode(JSGlobalData* globalData, ParameterNode* l, const Identifier& ident) JSC_FAST_CALL
- : Node(globalData)
- , m_ident(ident)
- {
- l->m_next = this;
- }
-
- Identifier ident() JSC_FAST_CALL { return m_ident; }
- ParameterNode *nextParam() JSC_FAST_CALL { return m_next.get(); }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- PassRefPtr<ParameterNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- private:
- friend class FuncDeclNode;
- friend class FuncExprNode;
- Identifier m_ident;
- ListRefPtr<ParameterNode> m_next;
- };
-
- class ScopeNode : public BlockNode {
- public:
- ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- const SourceCode& source() const { return m_source; }
- const UString& sourceURL() const JSC_FAST_CALL { return m_source.provider()->url(); }
- intptr_t sourceID() const { return m_source.provider()->asID(); }
-
- bool usesEval() const { return m_features & EvalFeature; }
- bool usesArguments() const { return m_features & ArgumentsFeature; }
- void setUsesArguments() { m_features |= ArgumentsFeature; }
- bool usesThis() const { return m_features & ThisFeature; }
- bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
-
- VarStack& varStack() { return m_varStack; }
- FunctionStack& functionStack() { return m_functionStack; }
-
- int neededConstants()
- {
- // We may need 1 more constant than the count given by the parser,
- // because of the various uses of jsUndefined().
- return m_numConstants + 1;
- }
-
- protected:
- void setSource(const SourceCode& source) { m_source = source; }
-
- VarStack m_varStack;
- FunctionStack m_functionStack;
-
- private:
- SourceCode m_source;
- CodeFeatures m_features;
- int m_numConstants;
- };
-
- class ProgramNode : public ScopeNode {
- public:
- static ProgramNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
-
- ProgramCodeBlock& byteCode(ScopeChainNode* scopeChain) JSC_FAST_CALL
- {
- if (!m_code)
- generateCode(scopeChain);
- return *m_code;
- }
-
- private:
- ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
-
- void generateCode(ScopeChainNode*) JSC_FAST_CALL;
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- Vector<size_t> m_varIndexes; // Storage indexes belonging to the nodes in m_varStack. (Recorded to avoid double lookup.)
- Vector<size_t> m_functionIndexes; // Storage indexes belonging to the nodes in m_functionStack. (Recorded to avoid double lookup.)
-
- OwnPtr<ProgramCodeBlock> m_code;
- };
-
- class EvalNode : public ScopeNode {
- public:
- static EvalNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
-
- EvalCodeBlock& byteCode(ScopeChainNode* scopeChain) JSC_FAST_CALL
- {
- if (!m_code)
- generateCode(scopeChain);
- return *m_code;
- }
-
- private:
- EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
-
- void generateCode(ScopeChainNode*) JSC_FAST_CALL;
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- OwnPtr<EvalCodeBlock> m_code;
- };
-
- class FunctionBodyNode : public ScopeNode {
- public:
- static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
- static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL;
- ~FunctionBodyNode();
-
- const Identifier* parameters() const JSC_FAST_CALL { return m_parameters; }
- size_t parameterCount() const { return m_parameterCount; }
- UString paramString() const JSC_FAST_CALL;
- Identifier* copyParameters();
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- SymbolTable& symbolTable() { return m_symbolTable; } // FIXME: Remove this
-
- CodeBlock& byteCode(ScopeChainNode* scopeChain) JSC_FAST_CALL
- {
- ASSERT(scopeChain);
- if (!m_code)
- generateCode(scopeChain);
- return *m_code;
- }
-
- CodeBlock& generatedByteCode() JSC_FAST_CALL
- {
- ASSERT(m_code);
- return *m_code;
- }
-
- bool isGenerated() JSC_FAST_CALL
- {
- return m_code;
- }
-
- void mark();
-
- void finishParsing(const SourceCode&, ParameterNode*);
- void finishParsing(Identifier* parameters, size_t parameterCount);
-
- UString toSourceString() const JSC_FAST_CALL { return UString("{") + source().toString() + UString("}"); }
-
- // These objects are ref/deref'd a lot in the scope chain, so this is a faster ref/deref.
- // If the virtual machine changes so this doesn't happen as much we can change back.
- void ref()
- {
- if (++m_refCount == 1)
- ScopeNode::ref();
- }
- void deref()
- {
- ASSERT(m_refCount);
- if (!--m_refCount)
- ScopeNode::deref();
- }
-
- protected:
- FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
-
- private:
- void generateCode(ScopeChainNode*) JSC_FAST_CALL;
-
- Identifier* m_parameters;
- size_t m_parameterCount;
- SymbolTable m_symbolTable;
- OwnPtr<CodeBlock> m_code;
- unsigned m_refCount;
- };
-
- class FuncExprNode : public ExpressionNode {
- public:
- FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_ident(ident)
- , m_parameter(parameter)
- , m_body(body)
- {
- m_body->finishParsing(source, m_parameter.get());
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL;
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { return PrecMember; }
- virtual bool needsParensIfLeftmost() const { return true; }
-
- FunctionBodyNode* body() { return m_body.get(); }
-
- private:
- // Used for streamTo
- friend class PropertyNode;
- Identifier m_ident;
- RefPtr<ParameterNode> m_parameter;
- RefPtr<FunctionBodyNode> m_body;
- };
-
- class FuncDeclNode : public StatementNode {
- public:
- FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_ident(ident)
- , m_parameter(parameter)
- , m_body(body)
- {
- m_body->finishParsing(source, m_parameter.get());
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL;
-
- Identifier m_ident;
-
- FunctionBodyNode* body() { return m_body.get(); }
-
- private:
- RefPtr<ParameterNode> m_parameter;
- RefPtr<FunctionBodyNode> m_body;
- };
-
- class CaseClauseNode : public Node {
- public:
- CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : Node(globalData)
- , m_expr(expr)
- {
- }
-
- CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr, SourceElements* children) JSC_FAST_CALL
- : Node(globalData)
- , m_expr(expr)
- {
- if (children)
- children->releaseContentsIntoVector(m_children);
- }
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- ExpressionNode* expr() const { return m_expr.get(); }
- StatementVector& children() { return m_children; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- StatementVector m_children;
- };
-
- class ClauseListNode : public Node {
- public:
- ClauseListNode(JSGlobalData* globalData, CaseClauseNode* clause) JSC_FAST_CALL
- : Node(globalData)
- , m_clause(clause)
- {
- }
-
- ClauseListNode(JSGlobalData* globalData, ClauseListNode* clauseList, CaseClauseNode* clause) JSC_FAST_CALL
- : Node(globalData)
- , m_clause(clause)
- {
- clauseList->m_next = this;
- }
-
- CaseClauseNode* getClause() const JSC_FAST_CALL { return m_clause.get(); }
- ClauseListNode* getNext() const JSC_FAST_CALL { return m_next.get(); }
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- PassRefPtr<ClauseListNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- private:
- friend class CaseBlockNode;
- RefPtr<CaseClauseNode> m_clause;
- ListRefPtr<ClauseListNode> m_next;
- };
-
- class CaseBlockNode : public Node {
- public:
- CaseBlockNode(JSGlobalData* globalData, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) JSC_FAST_CALL
- : Node(globalData)
- , m_list1(list1)
- , m_defaultClause(defaultClause)
- , m_list2(list2)
- {
- }
-
- RegisterID* emitCodeForBlock(CodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- private:
- SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num);
- RefPtr<ClauseListNode> m_list1;
- RefPtr<CaseClauseNode> m_defaultClause;
- RefPtr<ClauseListNode> m_list2;
- };
-
- class SwitchNode : public StatementNode {
- public:
- SwitchNode(JSGlobalData* globalData, ExpressionNode* expr, CaseBlockNode* block) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_expr(expr)
- , m_block(block)
- {
- }
-
- virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<CaseBlockNode> m_block;
- };
-
- struct ElementList {
- ElementNode* head;
- ElementNode* tail;
- };
-
- struct PropertyList {
- PropertyListNode* head;
- PropertyListNode* tail;
- };
-
- struct ArgumentList {
- ArgumentListNode* head;
- ArgumentListNode* tail;
- };
-
- struct ConstDeclList {
- ConstDeclNode* head;
- ConstDeclNode* tail;
- };
-
- struct ParameterList {
- ParameterNode* head;
- ParameterNode* tail;
- };
-
- struct ClauseList {
- ClauseListNode* head;
- ClauseListNode* tail;
- };
-
-} // namespace JSC
-
-#endif // NODES_H_
diff --git a/JavaScriptCore/kjs/nodes2string.cpp b/JavaScriptCore/kjs/nodes2string.cpp
deleted file mode 100644
index 4afefe0..0000000
--- a/JavaScriptCore/kjs/nodes2string.cpp
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- * Copyright (C) 2002 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "nodes.h"
-
-#include <wtf/MathExtras.h>
-#include <wtf/StringExtras.h>
-#include <wtf/unicode/Unicode.h>
-
-using namespace WTF;
-using namespace Unicode;
-
-namespace JSC {
-
-// A simple text streaming class that helps with code indentation.
-
-enum EndlType { Endl };
-enum IndentType { Indent };
-enum UnindentType { Unindent };
-enum DotExprType { DotExpr };
-
-class SourceStream {
-public:
- SourceStream()
- : m_numberNeedsParens(false)
- , m_atStartOfStatement(true)
- , m_precedence(PrecExpression)
- {
- }
-
- UString toString() const { return m_string; }
-
- SourceStream& operator<<(const Identifier&);
- SourceStream& operator<<(const UString&);
- SourceStream& operator<<(const char*);
- SourceStream& operator<<(double);
- SourceStream& operator<<(char);
- SourceStream& operator<<(EndlType);
- SourceStream& operator<<(IndentType);
- SourceStream& operator<<(UnindentType);
- SourceStream& operator<<(DotExprType);
- SourceStream& operator<<(Precedence);
- SourceStream& operator<<(const Node*);
- template <typename T> SourceStream& operator<<(const RefPtr<T>& n) { return *this << n.get(); }
-
-private:
- UString m_string;
- UString m_spacesForIndentation;
- bool m_numberNeedsParens;
- bool m_atStartOfStatement;
- Precedence m_precedence;
-};
-
-// --------
-
-static UString escapeStringForPrettyPrinting(const UString& s)
-{
- UString escapedString;
-
- for (int i = 0; i < s.size(); i++) {
- UChar c = s.data()[i];
- switch (c) {
- case '\"':
- escapedString += "\\\"";
- break;
- case '\n':
- escapedString += "\\n";
- break;
- case '\r':
- escapedString += "\\r";
- break;
- case '\t':
- escapedString += "\\t";
- break;
- case '\\':
- escapedString += "\\\\";
- break;
- default:
- if (c < 128 && isPrintableChar(c))
- escapedString.append(c);
- else {
- char hexValue[7];
- snprintf(hexValue, 7, "\\u%04x", c);
- escapedString += hexValue;
- }
- }
- }
-
- return escapedString;
-}
-
-static const char* operatorString(Operator oper)
-{
- switch (oper) {
- case OpEqual:
- return "=";
- case OpMultEq:
- return "*=";
- case OpDivEq:
- return "/=";
- case OpPlusEq:
- return "+=";
- case OpMinusEq:
- return "-=";
- case OpLShift:
- return "<<=";
- case OpRShift:
- return ">>=";
- case OpURShift:
- return ">>>=";
- case OpAndEq:
- return "&=";
- case OpXOrEq:
- return "^=";
- case OpOrEq:
- return "|=";
- case OpModEq:
- return "%=";
- case OpPlusPlus:
- return "++";
- case OpMinusMinus:
- return "--";
- }
- ASSERT_NOT_REACHED();
- return "???";
-}
-
-static bool isParserRoundTripNumber(const UString& string)
-{
- double number = string.toDouble(false, false);
- if (isnan(number) || isinf(number))
- return false;
- return string == UString::from(number);
-}
-
-// --------
-
-SourceStream& SourceStream::operator<<(char c)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- // use unsigned char to zero-extend instead of sign-extend
- UChar ch(static_cast<unsigned char>(c));
- m_string.append(ch);
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(const char* s)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_string += s;
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(double value)
-{
- bool needParens = m_numberNeedsParens;
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
-
- if (needParens)
- m_string.append('(');
- m_string += UString::from(value);
- if (needParens)
- m_string.append(')');
-
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(const UString& s)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_string += s;
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(const Identifier& s)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_string += s.ustring();
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(const Node* n)
-{
- bool needParens = (m_precedence != PrecExpression && n->precedence() > m_precedence) || (m_atStartOfStatement && n->needsParensIfLeftmost());
- m_precedence = PrecExpression;
- if (!n)
- return *this;
- if (needParens) {
- m_numberNeedsParens = false;
- m_string.append('(');
- }
- n->streamTo(*this);
- if (needParens)
- m_string.append(')');
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(EndlType)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = true;
- m_string.append('\n');
- m_string.append(m_spacesForIndentation);
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(IndentType)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_spacesForIndentation += " ";
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(UnindentType)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_spacesForIndentation = m_spacesForIndentation.substr(0, m_spacesForIndentation.size() - 2);
- return *this;
-}
-
-inline SourceStream& SourceStream::operator<<(DotExprType)
-{
- m_numberNeedsParens = true;
- return *this;
-}
-
-inline SourceStream& SourceStream::operator<<(Precedence precedence)
-{
- m_precedence = precedence;
- return *this;
-}
-
-static void streamLeftAssociativeBinaryOperator(SourceStream& s, Precedence precedence,
- const char* operatorString, const Node* left, const Node* right)
-{
- s << precedence << left
- << ' ' << operatorString << ' '
- << static_cast<Precedence>(precedence - 1) << right;
-}
-
-template <typename T> static inline void streamLeftAssociativeBinaryOperator(SourceStream& s,
- Precedence p, const char* o, const RefPtr<T>& l, const RefPtr<T>& r)
-{
- streamLeftAssociativeBinaryOperator(s, p, o, l.get(), r.get());
-}
-
-static inline void bracketNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const RefPtr<ExpressionNode>& subscript)
-{
- s << PrecCall << base.get() << "[" << subscript.get() << "]";
-}
-
-static inline void dotNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const Identifier& ident)
-{
- s << DotExpr << PrecCall << base.get() << "." << ident;
-}
-
-// --------
-
-UString Node::toString() const
-{
- SourceStream stream;
- streamTo(stream);
- return stream.toString();
-}
-
-// --------
-
-void NullNode::streamTo(SourceStream& s) const
-{
- s << "null";
-}
-
-void BooleanNode::streamTo(SourceStream& s) const
-{
- s << (m_value ? "true" : "false");
-}
-
-void NumberNode::streamTo(SourceStream& s) const
-{
- s << value();
-}
-
-void StringNode::streamTo(SourceStream& s) const
-{
- s << '"' << escapeStringForPrettyPrinting(m_value.ustring()) << '"';
-}
-
-void RegExpNode::streamTo(SourceStream& s) const
-{
- s << '/' << m_pattern << '/' << m_flags;
-}
-
-void ThisNode::streamTo(SourceStream& s) const
-{
- s << "this";
-}
-
-void ResolveNode::streamTo(SourceStream& s) const
-{
- s << m_ident;
-}
-
-void ElementNode::streamTo(SourceStream& s) const
-{
- for (const ElementNode* n = this; n; n = n->m_next.get()) {
- for (int i = 0; i < n->m_elision; i++)
- s << ',';
- s << PrecAssignment << n->m_node;
- if (n->m_next)
- s << ',';
- }
-}
-
-void ArrayNode::streamTo(SourceStream& s) const
-{
- s << '[' << m_element;
- for (int i = 0; i < m_elision; i++)
- s << ',';
- // Parser consumes one elision comma if there's array elements
- // present in the expression.
- if (m_optional && m_element)
- s << ',';
- s << ']';
-}
-
-void ObjectLiteralNode::streamTo(SourceStream& s) const
-{
- if (m_list)
- s << "{ " << m_list << " }";
- else
- s << "{ }";
-}
-
-void PropertyListNode::streamTo(SourceStream& s) const
-{
- s << m_node;
- for (const PropertyListNode* n = m_next.get(); n; n = n->m_next.get())
- s << ", " << n->m_node;
-}
-
-void PropertyNode::streamTo(SourceStream& s) const
-{
- switch (m_type) {
- case Constant: {
- UString propertyName = name().ustring();
- if (isParserRoundTripNumber(propertyName))
- s << propertyName;
- else
- s << '"' << escapeStringForPrettyPrinting(propertyName) << '"';
- s << ": " << PrecAssignment << m_assign;
- break;
- }
- case Getter:
- case Setter: {
- const FuncExprNode* func = static_cast<const FuncExprNode*>(m_assign.get());
- if (m_type == Getter)
- s << "get ";
- else
- s << "set ";
- s << escapeStringForPrettyPrinting(name().ustring())
- << "(" << func->m_parameter << ')' << func->m_body;
- break;
- }
- }
-}
-
-void BracketAccessorNode::streamTo(SourceStream& s) const
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
-}
-
-void DotAccessorNode::streamTo(SourceStream& s) const
-{
- dotNodeStreamTo(s, m_base, m_ident);
-}
-
-void ArgumentListNode::streamTo(SourceStream& s) const
-{
- s << PrecAssignment << m_expr;
- for (ArgumentListNode* n = m_next.get(); n; n = n->m_next.get())
- s << ", " << PrecAssignment << n->m_expr;
-}
-
-void ArgumentsNode::streamTo(SourceStream& s) const
-{
- s << '(' << m_listNode << ')';
-}
-
-void NewExprNode::streamTo(SourceStream& s) const
-{
- s << "new " << PrecMember << m_expr << m_args;
-}
-
-void EvalFunctionCallNode::streamTo(SourceStream& s) const
-{
- s << "eval" << m_args;
-}
-
-void FunctionCallValueNode::streamTo(SourceStream& s) const
-{
- s << PrecCall << m_expr << m_args;
-}
-
-void FunctionCallResolveNode::streamTo(SourceStream& s) const
-{
- s << m_ident << m_args;
-}
-
-void FunctionCallBracketNode::streamTo(SourceStream& s) const
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
- s << m_args;
-}
-
-void FunctionCallDotNode::streamTo(SourceStream& s) const
-{
- dotNodeStreamTo(s, m_base, m_ident);
- s << m_args;
-}
-
-void PostfixResolveNode::streamTo(SourceStream& s) const
-{
- s << m_ident << operatorString(m_operator);
-}
-
-void PostfixBracketNode::streamTo(SourceStream& s) const
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
- s << operatorString(m_operator);
-}
-
-void PostfixDotNode::streamTo(SourceStream& s) const
-{
- dotNodeStreamTo(s, m_base, m_ident);
- s << operatorString(m_operator);
-}
-
-void PostfixErrorNode::streamTo(SourceStream& s) const
-{
- s << PrecLeftHandSide << m_expr;
- if (m_operator == OpPlusPlus)
- s << "++";
- else
- s << "--";
-}
-
-void DeleteResolveNode::streamTo(SourceStream& s) const
-{
- s << "delete " << m_ident;
-}
-
-void DeleteBracketNode::streamTo(SourceStream& s) const
-{
- s << "delete ";
- bracketNodeStreamTo(s, m_base, m_subscript);
-}
-
-void DeleteDotNode::streamTo(SourceStream& s) const
-{
- s << "delete ";
- dotNodeStreamTo(s, m_base, m_ident);
-}
-
-void DeleteValueNode::streamTo(SourceStream& s) const
-{
- s << "delete " << PrecUnary << m_expr;
-}
-
-void VoidNode::streamTo(SourceStream& s) const
-{
- s << "void " << PrecUnary << m_expr;
-}
-
-void TypeOfValueNode::streamTo(SourceStream& s) const
-{
- s << "typeof " << PrecUnary << m_expr;
-}
-
-void TypeOfResolveNode::streamTo(SourceStream& s) const
-{
- s << "typeof " << m_ident;
-}
-
-void PrefixResolveNode::streamTo(SourceStream& s) const
-{
- s << operatorString(m_operator) << m_ident;
-}
-
-void PrefixBracketNode::streamTo(SourceStream& s) const
-{
- s << operatorString(m_operator);
- bracketNodeStreamTo(s, m_base, m_subscript);
-}
-
-void PrefixDotNode::streamTo(SourceStream& s) const
-{
- s << operatorString(m_operator);
- dotNodeStreamTo(s, m_base, m_ident);
-}
-
-void PrefixErrorNode::streamTo(SourceStream& s) const
-{
- if (m_operator == OpPlusPlus)
- s << "++" << PrecUnary << m_expr;
- else
- s << "--" << PrecUnary << m_expr;
-}
-
-void UnaryPlusNode::streamTo(SourceStream& s) const
-{
- s << "+ " << PrecUnary << m_expr;
-}
-
-void NegateNode::streamTo(SourceStream& s) const
-{
- s << "- " << PrecUnary << m_expr;
-}
-
-void BitwiseNotNode::streamTo(SourceStream& s) const
-{
- s << "~" << PrecUnary << m_expr;
-}
-
-void LogicalNotNode::streamTo(SourceStream& s) const
-{
- s << "!" << PrecUnary << m_expr;
-}
-
-void MultNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "*", m_expr1, m_expr2);
-}
-
-void DivNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "/", m_expr1, m_expr2);
-}
-
-void ModNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "%", m_expr1, m_expr2);
-}
-
-void AddNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "+", m_expr1, m_expr2);
-}
-
-void SubNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "-", m_expr1, m_expr2);
-}
-
-void LeftShiftNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "<<", m_expr1, m_expr2);
-}
-
-void RightShiftNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), ">>", m_expr1, m_expr2);
-}
-
-void UnsignedRightShiftNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), ">>>", m_expr1, m_expr2);
-}
-
-void LessNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "<", m_expr1, m_expr2);
-}
-
-void GreaterNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), ">", m_expr1, m_expr2);
-}
-
-void LessEqNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "<=", m_expr1, m_expr2);
-}
-
-void GreaterEqNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), ">=", m_expr1, m_expr2);
-}
-
-void InstanceOfNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", m_expr1, m_expr2);
-}
-
-void InNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "in", m_expr1, m_expr2);
-}
-
-void EqualNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "==", m_expr1, m_expr2);
-}
-
-void NotEqualNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "!=", m_expr1, m_expr2);
-}
-
-void StrictEqualNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "===", m_expr1, m_expr2);
-}
-
-void NotStrictEqualNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "!==", m_expr1, m_expr2);
-}
-
-void BitAndNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "&", m_expr1, m_expr2);
-}
-
-void BitXOrNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "^", m_expr1, m_expr2);
-}
-
-void BitOrNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "|", m_expr1, m_expr2);
-}
-
-void LogicalOpNode::streamTo(SourceStream& s) const
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), (m_operator == OpLogicalAnd) ? "&&" : "||", m_expr1, m_expr2);
-}
-
-void ConditionalNode::streamTo(SourceStream& s) const
-{
- s << PrecLogicalOr << m_logical
- << " ? " << PrecAssignment << m_expr1
- << " : " << PrecAssignment << m_expr2;
-}
-
-void ReadModifyResolveNode::streamTo(SourceStream& s) const
-{
- s << m_ident << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
-}
-
-void AssignResolveNode::streamTo(SourceStream& s) const
-{
- s << m_ident << " = " << PrecAssignment << m_right;
-}
-
-void ReadModifyBracketNode::streamTo(SourceStream& s) const
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
- s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
-}
-
-void AssignBracketNode::streamTo(SourceStream& s) const
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
- s << " = " << PrecAssignment << m_right;
-}
-
-void ReadModifyDotNode::streamTo(SourceStream& s) const
-{
- dotNodeStreamTo(s, m_base, m_ident);
- s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
-}
-
-void AssignDotNode::streamTo(SourceStream& s) const
-{
- dotNodeStreamTo(s, m_base, m_ident);
- s << " = " << PrecAssignment << m_right;
-}
-
-void AssignErrorNode::streamTo(SourceStream& s) const
-{
- s << PrecLeftHandSide << m_left << ' '
- << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
-}
-
-void CommaNode::streamTo(SourceStream& s) const
-{
- s << PrecAssignment << m_expr1 << ", " << PrecAssignment << m_expr2;
-}
-
-void ConstDeclNode::streamTo(SourceStream& s) const
-{
- s << m_ident;
- if (m_init)
- s << " = " << PrecAssignment << m_init;
- for (ConstDeclNode* n = m_next.get(); n; n = n->m_next.get()) {
- s << ", " << n->m_ident;
- if (n->m_init)
- s << " = " << PrecAssignment << n->m_init;
- }
-}
-
-void ConstStatementNode::streamTo(SourceStream& s) const
-{
- s << Endl << "const " << m_next << ';';
-}
-
-static inline void statementListStreamTo(const Vector<RefPtr<StatementNode> >& nodes, SourceStream& s)
-{
- for (Vector<RefPtr<StatementNode> >::const_iterator ptr = nodes.begin(); ptr != nodes.end(); ptr++)
- s << *ptr;
-}
-
-void BlockNode::streamTo(SourceStream& s) const
-{
- s << Endl << "{" << Indent;
- statementListStreamTo(m_children, s);
- s << Unindent << Endl << "}";
-}
-
-void ScopeNode::streamTo(SourceStream& s) const
-{
- s << Endl << "{" << Indent;
-
- bool printedVar = false;
- for (size_t i = 0; i < m_varStack.size(); ++i) {
- if (m_varStack[i].second == 0) {
- if (!printedVar) {
- s << Endl << "var ";
- printedVar = true;
- } else
- s << ", ";
- s << m_varStack[i].first;
- }
- }
- if (printedVar)
- s << ';';
-
- statementListStreamTo(m_children, s);
- s << Unindent << Endl << "}";
-}
-
-void EmptyStatementNode::streamTo(SourceStream& s) const
-{
- s << Endl << ';';
-}
-
-void DebuggerStatementNode::streamTo(SourceStream& s) const
-{
- s << Endl << "debugger;";
-}
-
-void ExprStatementNode::streamTo(SourceStream& s) const
-{
- s << Endl << m_expr << ';';
-}
-
-void VarStatementNode::streamTo(SourceStream& s) const
-{
- s << Endl << "var " << m_expr << ';';
-}
-
-void IfNode::streamTo(SourceStream& s) const
-{
- s << Endl << "if (" << m_condition << ')' << Indent << m_ifBlock << Unindent;
-}
-
-void IfElseNode::streamTo(SourceStream& s) const
-{
- IfNode::streamTo(s);
- s << Endl << "else" << Indent << m_elseBlock << Unindent;
-}
-
-void DoWhileNode::streamTo(SourceStream& s) const
-{
- s << Endl << "do " << Indent << m_statement << Unindent << Endl
- << "while (" << m_expr << ");";
-}
-
-void WhileNode::streamTo(SourceStream& s) const
-{
- s << Endl << "while (" << m_expr << ')' << Indent << m_statement << Unindent;
-}
-
-void ForNode::streamTo(SourceStream& s) const
-{
- s << Endl << "for ("
- << (m_expr1WasVarDecl ? "var " : "")
- << m_expr1
- << "; " << m_expr2
- << "; " << m_expr3
- << ')' << Indent << m_statement << Unindent;
-}
-
-void ForInNode::streamTo(SourceStream& s) const
-{
- s << Endl << "for (";
- if (m_identIsVarDecl) {
- s << "var ";
- if (m_init)
- s << m_init;
- else
- s << PrecLeftHandSide << m_lexpr;
- } else
- s << PrecLeftHandSide << m_lexpr;
-
- s << " in " << m_expr << ')' << Indent << m_statement << Unindent;
-}
-
-void ContinueNode::streamTo(SourceStream& s) const
-{
- s << Endl << "continue";
- if (!m_ident.isNull())
- s << ' ' << m_ident;
- s << ';';
-}
-
-void BreakNode::streamTo(SourceStream& s) const
-{
- s << Endl << "break";
- if (!m_ident.isNull())
- s << ' ' << m_ident;
- s << ';';
-}
-
-void ReturnNode::streamTo(SourceStream& s) const
-{
- s << Endl << "return";
- if (m_value)
- s << ' ' << m_value;
- s << ';';
-}
-
-void WithNode::streamTo(SourceStream& s) const
-{
- s << Endl << "with (" << m_expr << ") " << m_statement;
-}
-
-void CaseClauseNode::streamTo(SourceStream& s) const
-{
- s << Endl;
- if (m_expr)
- s << "case " << m_expr;
- else
- s << "default";
- s << ":" << Indent;
- statementListStreamTo(m_children, s);
- s << Unindent;
-}
-
-void ClauseListNode::streamTo(SourceStream& s) const
-{
- for (const ClauseListNode* n = this; n; n = n->getNext())
- s << n->getClause();
-}
-
-void CaseBlockNode::streamTo(SourceStream& s) const
-{
- for (const ClauseListNode* n = m_list1.get(); n; n = n->getNext())
- s << n->getClause();
- s << m_defaultClause;
- for (const ClauseListNode* n = m_list2.get(); n; n = n->getNext())
- s << n->getClause();
-}
-
-void SwitchNode::streamTo(SourceStream& s) const
-{
- s << Endl << "switch (" << m_expr << ") {"
- << Indent << m_block << Unindent
- << Endl << "}";
-}
-
-void LabelNode::streamTo(SourceStream& s) const
-{
- s << Endl << m_name << ":" << Indent << m_statement << Unindent;
-}
-
-void ThrowNode::streamTo(SourceStream& s) const
-{
- s << Endl << "throw " << m_expr << ';';
-}
-
-void TryNode::streamTo(SourceStream& s) const
-{
- s << Endl << "try " << m_tryBlock;
- if (m_catchBlock)
- s << Endl << "catch (" << m_exceptionIdent << ')' << m_catchBlock;
- if (m_finallyBlock)
- s << Endl << "finally " << m_finallyBlock;
-}
-
-void ParameterNode::streamTo(SourceStream& s) const
-{
- s << m_ident;
- for (ParameterNode* n = m_next.get(); n; n = n->m_next.get())
- s << ", " << n->m_ident;
-}
-
-void FuncDeclNode::streamTo(SourceStream& s) const
-{
- s << Endl << "function " << m_ident << '(' << m_parameter << ')' << m_body;
-}
-
-void FuncExprNode::streamTo(SourceStream& s) const
-{
- s << "function " << m_ident << '(' << m_parameter << ')' << m_body;
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/operations.cpp b/JavaScriptCore/kjs/operations.cpp
deleted file mode 100644
index f2d8deb..0000000
--- a/JavaScriptCore/kjs/operations.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "operations.h"
-
-#include "Error.h"
-#include "JSObject.h"
-#include "JSString.h"
-#include <math.h>
-#include <stdio.h>
-#include <wtf/MathExtras.h>
-
-#if HAVE(FLOAT_H)
-#include <float.h>
-#endif
-
-namespace JSC {
-
-// ECMA 11.9.3
-bool equal(ExecState* exec, JSValue* v1, JSValue* v2)
-{
- if (JSImmediate::areBothImmediateNumbers(v1, v2))
- return v1 == v2;
-
- return equalSlowCaseInline(exec, v1, v2);
-}
-
-bool equalSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
-{
- return equalSlowCaseInline(exec, v1, v2);
-}
-
-bool strictEqual(JSValue* v1, JSValue* v2)
-{
- if (JSImmediate::areBothImmediate(v1, v2))
- return v1 == v2;
-
- if (JSImmediate::isEitherImmediate(v1, v2) & (v1 != JSImmediate::from(0)) & (v2 != JSImmediate::from(0)))
- return false;
-
- return strictEqualSlowCaseInline(v1, v2);
-}
-
-bool strictEqualSlowCase(JSValue* v1, JSValue* v2)
-{
- return strictEqualSlowCaseInline(v1, v2);
-}
-
-NEVER_INLINE JSValue* throwOutOfMemoryError(ExecState* exec)
-{
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- return error;
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/operations.h b/JavaScriptCore/kjs/operations.h
deleted file mode 100644
index fad9720..0000000
--- a/JavaScriptCore/kjs/operations.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef _KJS_OPERATIONS_H_
-#define _KJS_OPERATIONS_H_
-
-#include "JSImmediate.h"
-#include "JSNumberCell.h"
-#include "JSString.h"
-
-namespace JSC {
-
- // ECMA 11.9.3
- bool equal(ExecState*, JSValue*, JSValue*);
- bool equalSlowCase(ExecState*, JSValue*, JSValue*);
-
- ALWAYS_INLINE bool equalSlowCaseInline(ExecState* exec, JSValue* v1, JSValue* v2)
- {
- ASSERT(!JSImmediate::areBothImmediateNumbers(v1, v2));
-
- do {
- if (v1->isNumber() && v2->isNumber())
- return v1->uncheckedGetNumber() == v2->uncheckedGetNumber();
-
- bool s1 = v1->isString();
- bool s2 = v2->isString();
- if (s1 && s2)
- return asString(v1)->value() == asString(v2)->value();
-
- if (v1->isUndefinedOrNull()) {
- if (v2->isUndefinedOrNull())
- return true;
- if (JSImmediate::isImmediate(v2))
- return false;
- return v2->asCell()->structureID()->typeInfo().masqueradesAsUndefined();
- }
-
- if (v2->isUndefinedOrNull()) {
- if (JSImmediate::isImmediate(v1))
- return false;
- return v1->asCell()->structureID()->typeInfo().masqueradesAsUndefined();
- }
-
- if (v1->isObject()) {
- if (v2->isObject())
- return v1 == v2;
- JSValue* p1 = v1->toPrimitive(exec);
- if (exec->hadException())
- return false;
- v1 = p1;
- if (JSImmediate::areBothImmediateNumbers(v1, v2))
- return v1 == v2;
- continue;
- }
-
- if (v2->isObject()) {
- JSValue* p2 = v2->toPrimitive(exec);
- if (exec->hadException())
- return false;
- v2 = p2;
- if (JSImmediate::areBothImmediateNumbers(v1, v2))
- return v1 == v2;
- continue;
- }
-
- if (s1 || s2) {
- double d1 = v1->toNumber(exec);
- double d2 = v2->toNumber(exec);
- return d1 == d2;
- }
-
- if (v1->isBoolean()) {
- if (v2->isNumber())
- return static_cast<double>(v1->getBoolean()) == v2->uncheckedGetNumber();
- } else if (v2->isBoolean()) {
- if (v1->isNumber())
- return v1->uncheckedGetNumber() == static_cast<double>(v2->getBoolean());
- }
-
- return v1 == v2;
- } while (true);
- }
-
-
- bool strictEqual(JSValue*, JSValue*);
- bool strictEqualSlowCase(JSValue*, JSValue*);
-
- inline bool strictEqualSlowCaseInline(JSValue* v1, JSValue* v2)
- {
- ASSERT(!JSImmediate::areBothImmediate(v1, v2));
-
- if (JSImmediate::isEitherImmediate(v1, v2)) {
- ASSERT(v1 == JSImmediate::zeroImmediate() || v2 == JSImmediate::zeroImmediate());
- ASSERT(v1 != v2);
-
- // The reason we can't just return false here is that 0 === -0,
- // and while the former is an immediate number, the latter is not.
- if (v1 == JSImmediate::zeroImmediate())
- return asCell(v2)->isNumber() && asNumberCell(v2)->value() == 0;
- return asCell(v1)->isNumber() && asNumberCell(v1)->value() == 0;
- }
-
- if (asCell(v1)->isNumber()) {
- return asCell(v2)->isNumber()
- && asNumberCell(v1)->value() == asNumberCell(v2)->value();
- }
-
- if (asCell(v1)->isString()) {
- return asCell(v2)->isString()
- && asString(v1)->value() == asString(v2)->value();
- }
-
- return v1 == v2;
- }
-
- JSValue* throwOutOfMemoryError(ExecState*);
-}
-
-#endif
diff --git a/JavaScriptCore/kjs/protect.h b/JavaScriptCore/kjs/protect.h
deleted file mode 100644
index b317424..0000000
--- a/JavaScriptCore/kjs/protect.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-
-#ifndef protect_h
-#define protect_h
-
-#include "JSCell.h"
-#include "collector.h"
-
-namespace JSC {
-
- inline void gcProtect(JSCell* val)
- {
- Heap::heap(val)->protect(val);
- }
-
- inline void gcUnprotect(JSCell* val)
- {
- Heap::heap(val)->unprotect(val);
- }
-
- inline void gcProtectNullTolerant(JSCell* val)
- {
- if (val)
- gcProtect(val);
- }
-
- inline void gcUnprotectNullTolerant(JSCell* val)
- {
- if (val)
- gcUnprotect(val);
- }
-
- inline void gcProtect(JSValue* value)
- {
- if (JSImmediate::isImmediate(value))
- return;
- gcProtect(asCell(value));
- }
-
- inline void gcUnprotect(JSValue* value)
- {
- if (JSImmediate::isImmediate(value))
- return;
- gcUnprotect(asCell(value));
- }
-
- inline void gcProtectNullTolerant(JSValue* value)
- {
- if (!value || JSImmediate::isImmediate(value))
- return;
- gcProtect(asCell(value));
- }
-
- inline void gcUnprotectNullTolerant(JSValue* value)
- {
- if (!value || JSImmediate::isImmediate(value))
- return;
- gcUnprotect(asCell(value));
- }
-
- // FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation
- // and the implicit conversion to raw pointer
- template <class T> class ProtectedPtr {
- public:
- ProtectedPtr() : m_ptr(0) { }
- ProtectedPtr(T* ptr);
- ProtectedPtr(const ProtectedPtr&);
- ~ProtectedPtr();
-
- template <class U> ProtectedPtr(const ProtectedPtr<U>&);
-
- T* get() const { return m_ptr; }
- operator T*() const { return m_ptr; }
- T* operator->() const { return m_ptr; }
-
- bool operator!() const { return !m_ptr; }
-
- ProtectedPtr& operator=(const ProtectedPtr&);
- ProtectedPtr& operator=(T*);
-
- private:
- T* m_ptr;
- };
-
- template <class T> ProtectedPtr<T>::ProtectedPtr(T* ptr)
- : m_ptr(ptr)
- {
- gcProtectNullTolerant(m_ptr);
- }
-
- template <class T> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr& o)
- : m_ptr(o.get())
- {
- gcProtectNullTolerant(m_ptr);
- }
-
- template <class T> ProtectedPtr<T>::~ProtectedPtr()
- {
- gcUnprotectNullTolerant(m_ptr);
- }
-
- template <class T> template <class U> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U>& o)
- : m_ptr(o.get())
- {
- gcProtectNullTolerant(m_ptr);
- }
-
- template <class T> ProtectedPtr<T>& ProtectedPtr<T>::operator=(const ProtectedPtr<T>& o)
- {
- T* optr = o.m_ptr;
- gcProtectNullTolerant(optr);
- gcUnprotectNullTolerant(m_ptr);
- m_ptr = optr;
- return *this;
- }
-
- template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(T* optr)
- {
- gcProtectNullTolerant(optr);
- gcUnprotectNullTolerant(m_ptr);
- m_ptr = optr;
- return *this;
- }
-
- template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() == b.get(); }
- template <class T> inline bool operator==(const ProtectedPtr<T>& a, const T* b) { return a.get() == b; }
- template <class T> inline bool operator==(const T* a, const ProtectedPtr<T>& b) { return a == b.get(); }
-
- template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() != b.get(); }
- template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const T* b) { return a.get() != b; }
- template <class T> inline bool operator!=(const T* a, const ProtectedPtr<T>& b) { return a != b.get(); }
-
-} // namespace JSC
-
-#endif // protect_h
diff --git a/JavaScriptCore/kjs/regexp.cpp b/JavaScriptCore/kjs/regexp.cpp
deleted file mode 100644
index 7397232..0000000
--- a/JavaScriptCore/kjs/regexp.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
- * Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "regexp.h"
-
-#include "CTI.h"
-#include "lexer.h"
-#include <pcre/pcre.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wrec/WREC.h>
-#include <wtf/Assertions.h>
-#include <wtf/OwnArrayPtr.h>
-
-namespace JSC {
-
-inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern)
- : m_pattern(pattern)
- , m_flagBits(0)
- , m_regExp(0)
- , m_constructionError(0)
- , m_numSubpatterns(0)
-{
-#if ENABLE(WREC)
- m_wrecFunction = CTI::compileRegExp(globalData->machine, pattern, &m_numSubpatterns, &m_constructionError);
- if (m_wrecFunction)
- return;
- // Fall through to non-WREC case.
-#else
- UNUSED_PARAM(globalData);
-#endif
- m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
- JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError);
-}
-
-PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern)
-{
- return adoptRef(new RegExp(globalData, pattern));
-}
-
-inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
- : m_pattern(pattern)
- , m_flags(flags)
- , m_flagBits(0)
- , m_regExp(0)
- , m_constructionError(0)
- , m_numSubpatterns(0)
-{
- // NOTE: The global flag is handled on a case-by-case basis by functions like
- // String::match and RegExpObject::match.
- if (flags.find('g') != -1)
- m_flagBits |= Global;
-
- // FIXME: Eliminate duplication by adding a way ask a JSRegExp what its flags are?
- JSRegExpIgnoreCaseOption ignoreCaseOption = JSRegExpDoNotIgnoreCase;
- if (flags.find('i') != -1) {
- m_flagBits |= IgnoreCase;
- ignoreCaseOption = JSRegExpIgnoreCase;
- }
-
- JSRegExpMultilineOption multilineOption = JSRegExpSingleLine;
- if (flags.find('m') != -1) {
- m_flagBits |= Multiline;
- multilineOption = JSRegExpMultiline;
- }
-
-#if ENABLE(WREC)
- m_wrecFunction = CTI::compileRegExp(globalData->machine, pattern, &m_numSubpatterns, &m_constructionError, (m_flagBits & IgnoreCase), (m_flagBits & Multiline));
- if (m_wrecFunction)
- return;
- // Fall through to non-WREC case.
-#else
- UNUSED_PARAM(globalData);
-#endif
- m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
- ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
-}
-
-PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
-{
- return adoptRef(new RegExp(globalData, pattern, flags));
-}
-
-RegExp::~RegExp()
-{
- jsRegExpFree(m_regExp);
-#if ENABLE(WREC)
- if (m_wrecFunction)
- WTF::fastFreeExecutable(m_wrecFunction);
-#endif
-}
-
-int RegExp::match(const UString& s, int i, OwnArrayPtr<int>* ovector)
-{
- if (i < 0)
- i = 0;
- if (ovector)
- ovector->clear();
-
- if (i > s.size() || s.isNull())
- return -1;
-
-#if ENABLE(WREC)
- if (m_wrecFunction) {
- int offsetVectorSize = (m_numSubpatterns + 1) * 2;
- int* offsetVector = new int [offsetVectorSize];
- for (int j = 0; j < offsetVectorSize; ++j)
- offsetVector[j] = -1;
-
- OwnArrayPtr<int> nonReturnedOvector;
- if (!ovector)
- nonReturnedOvector.set(offsetVector);
- else
- ovector->set(offsetVector);
-
- int result = reinterpret_cast<WRECFunction>(m_wrecFunction)(s.data(), i, s.size(), offsetVector);
-
- if (result < 0) {
-#ifndef NDEBUG
- // TODO: define up a symbol, rather than magic -1
- if (result != -1)
- fprintf(stderr, "jsRegExpExecute failed with result %d\n", result);
-#endif
- if (ovector)
- ovector->clear();
- }
- return result;
- } else
-#endif
- if (m_regExp) {
- // Set up the offset vector for the result.
- // First 2/3 used for result, the last third used by PCRE.
- int* offsetVector;
- int offsetVectorSize;
- int fixedSizeOffsetVector[3];
- if (!ovector) {
- offsetVectorSize = 3;
- offsetVector = fixedSizeOffsetVector;
- } else {
- offsetVectorSize = (m_numSubpatterns + 1) * 3;
- offsetVector = new int [offsetVectorSize];
- ovector->set(offsetVector);
- }
-
- int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), i, offsetVector, offsetVectorSize);
-
- if (numMatches < 0) {
-#ifndef NDEBUG
- if (numMatches != JSRegExpErrorNoMatch)
- fprintf(stderr, "jsRegExpExecute failed with result %d\n", numMatches);
-#endif
- if (ovector)
- ovector->clear();
- return -1;
- }
-
- return offsetVector[0];
- }
-
- return -1;
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/regexp.h b/JavaScriptCore/kjs/regexp.h
deleted file mode 100644
index 1842d94..0000000
--- a/JavaScriptCore/kjs/regexp.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef KJS_REGEXP_H
-#define KJS_REGEXP_H
-
-#include "ustring.h"
-#include <wtf/Forward.h>
-#include <wtf/RefCounted.h>
-
-struct JSRegExp;
-
-namespace JSC {
-
- class JSGlobalData;
-
- class RegExp : public RefCounted<RegExp> {
- public:
- static PassRefPtr<RegExp> create(JSGlobalData*, const UString& pattern);
- static PassRefPtr<RegExp> create(JSGlobalData*, const UString& pattern, const UString& flags);
- ~RegExp();
-
- bool global() const { return m_flagBits & Global; }
- bool ignoreCase() const { return m_flagBits & IgnoreCase; }
- bool multiline() const { return m_flagBits & Multiline; }
-
- const UString& pattern() const { return m_pattern; }
- const UString& flags() const { return m_flags; }
-
- bool isValid() const { return !m_constructionError; }
- const char* errorMessage() const { return m_constructionError; }
-
- int match(const UString&, int offset, OwnArrayPtr<int>* ovector = 0);
- unsigned numSubpatterns() const { return m_numSubpatterns; }
-
- private:
- RegExp(JSGlobalData*, const UString& pattern);
- RegExp(JSGlobalData*, const UString& pattern, const UString& flags);
-
- void compile();
-
- enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 };
-
- UString m_pattern; // FIXME: Just decompile m_regExp instead of storing this.
- UString m_flags; // FIXME: Just decompile m_regExp instead of storing this.
- int m_flagBits;
- JSRegExp* m_regExp;
- const char* m_constructionError;
- unsigned m_numSubpatterns;
-
-#if ENABLE(WREC)
- // Called as a WRECFunction
- void* m_wrecFunction;
-#endif
- };
-
-} // namespace JSC
-
-#endif // KJS_REGEXP_H
diff --git a/JavaScriptCore/kjs/ustring.cpp b/JavaScriptCore/kjs/ustring.cpp
deleted file mode 100644
index 3a85b1d..0000000
--- a/JavaScriptCore/kjs/ustring.cpp
+++ /dev/null
@@ -1,1638 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "ustring.h"
-
-#include "JSGlobalObjectFunctions.h"
-#include "collector.h"
-#include "dtoa.h"
-#include "identifier.h"
-#include "operations.h"
-#include <ctype.h>
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <wtf/ASCIICType.h>
-#include <wtf/Assertions.h>
-#include <wtf/MathExtras.h>
-#include <wtf/Vector.h>
-#include <wtf/unicode/UTF8.h>
-
-#if HAVE(STRING_H)
-#include <string.h>
-#endif
-#if HAVE(STRINGS_H)
-#include <strings.h>
-#endif
-
-using namespace WTF;
-using namespace WTF::Unicode;
-using namespace std;
-
-// This can be tuned differently per platform by putting platform #ifs right here.
-// If you don't define this macro at all, then copyChars will just call directly
-// to memcpy.
-#define USTRING_COPY_CHARS_INLINE_CUTOFF 20
-
-namespace JSC {
-
-extern const double NaN;
-extern const double Inf;
-
-static inline size_t overflowIndicator() { return std::numeric_limits<size_t>::max(); }
-static inline size_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); }
-
-static inline UChar* allocChars(size_t length)
-{
- ASSERT(length);
- if (length > maxUChars())
- return 0;
- return static_cast<UChar*>(tryFastMalloc(sizeof(UChar) * length));
-}
-
-static inline UChar* reallocChars(UChar* buffer, size_t length)
-{
- ASSERT(length);
- if (length > maxUChars())
- return 0;
- return static_cast<UChar*>(tryFastRealloc(buffer, sizeof(UChar) * length));
-}
-
-static inline void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
-{
-#ifdef USTRING_COPY_CHARS_INLINE_CUTOFF
- if (numCharacters <= USTRING_COPY_CHARS_INLINE_CUTOFF) {
- for (unsigned i = 0; i < numCharacters; ++i)
- destination[i] = source[i];
- return;
- }
-#endif
- memcpy(destination, source, numCharacters * sizeof(UChar));
-}
-
-COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes)
-
-CString::CString(const char* c)
- : m_length(strlen(c))
- , m_data(new char[m_length + 1])
-{
- memcpy(m_data, c, m_length + 1);
-}
-
-CString::CString(const char* c, size_t length)
- : m_length(length)
- , m_data(new char[length + 1])
-{
- memcpy(m_data, c, m_length);
- m_data[m_length] = 0;
-}
-
-CString::CString(const CString& b)
-{
- m_length = b.m_length;
- if (b.m_data) {
- m_data = new char[m_length + 1];
- memcpy(m_data, b.m_data, m_length + 1);
- } else
- m_data = 0;
-}
-
-CString::~CString()
-{
- delete [] m_data;
-}
-
-CString CString::adopt(char* c, size_t length)
-{
- CString s;
- s.m_data = c;
- s.m_length = length;
- return s;
-}
-
-CString& CString::append(const CString& t)
-{
- char* n;
- n = new char[m_length + t.m_length + 1];
- if (m_length)
- memcpy(n, m_data, m_length);
- if (t.m_length)
- memcpy(n + m_length, t.m_data, t.m_length);
- m_length += t.m_length;
- n[m_length] = 0;
-
- delete [] m_data;
- m_data = n;
-
- return *this;
-}
-
-CString& CString::operator=(const char* c)
-{
- if (m_data)
- delete [] m_data;
- m_length = strlen(c);
- m_data = new char[m_length + 1];
- memcpy(m_data, c, m_length + 1);
-
- return *this;
-}
-
-CString& CString::operator=(const CString& str)
-{
- if (this == &str)
- return *this;
-
- if (m_data)
- delete [] m_data;
- m_length = str.m_length;
- if (str.m_data) {
- m_data = new char[m_length + 1];
- memcpy(m_data, str.m_data, m_length + 1);
- } else
- m_data = 0;
-
- return *this;
-}
-
-bool operator==(const CString& c1, const CString& c2)
-{
- size_t len = c1.size();
- return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
-}
-
-// These static strings are immutable, except for rc, whose initial value is chosen to
-// reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
-static UChar sharedEmptyChar;
-UString::Rep UString::Rep::null = { 0, 0, INT_MAX / 2, 0, 1, &UString::Rep::null, 0, 0, 0, 0, 0, 0 };
-UString::Rep UString::Rep::empty = { 0, 0, INT_MAX / 2, 0, 1, &UString::Rep::empty, 0, &sharedEmptyChar, 0, 0, 0, 0 };
-
-static char* statBuffer = 0; // Only used for debugging via UString::ascii().
-
-PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar* d, int l)
-{
- UChar* copyD = static_cast<UChar*>(fastMalloc(l * sizeof(UChar)));
- copyChars(copyD, d, l);
- return create(copyD, l);
-}
-
-PassRefPtr<UString::Rep> UString::Rep::create(UChar* d, int l)
-{
- Rep* r = new Rep;
- r->offset = 0;
- r->len = l;
- r->rc = 1;
- r->_hash = 0;
- r->m_identifierTable = 0;
- r->baseString = r;
- r->reportedCost = 0;
- r->buf = d;
- r->usedCapacity = l;
- r->capacity = l;
- r->usedPreCapacity = 0;
- r->preCapacity = 0;
-
- r->checkConsistency();
-
- // steal the single reference this Rep was created with
- return adoptRef(r);
-}
-
-PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length)
-{
- ASSERT(base);
- base->checkConsistency();
-
- int baseOffset = base->offset;
-
- base = base->baseString;
-
- ASSERT(-(offset + baseOffset) <= base->usedPreCapacity);
- ASSERT(offset + baseOffset + length <= base->usedCapacity);
-
- Rep* r = new Rep;
- r->offset = baseOffset + offset;
- r->len = length;
- r->rc = 1;
- r->_hash = 0;
- r->m_identifierTable = 0;
- r->baseString = base.releaseRef();
- r->reportedCost = 0;
- r->buf = 0;
- r->usedCapacity = 0;
- r->capacity = 0;
- r->usedPreCapacity = 0;
- r->preCapacity = 0;
-
- r->checkConsistency();
-
- // steal the single reference this Rep was created with
- return adoptRef(r);
-}
-
-PassRefPtr<UString::Rep> UString::Rep::createFromUTF8(const char* string)
-{
- if (!string)
- return &UString::Rep::null;
-
- size_t length = strlen(string);
- Vector<UChar, 1024> buffer(length);
- UChar* p = buffer.data();
- if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
- return &UString::Rep::null;
-
- return UString::Rep::createCopying(buffer.data(), p - buffer.data());
-}
-
-void UString::Rep::destroy()
-{
- checkConsistency();
-
- // Static null and empty strings can never be destroyed, but we cannot rely on
- // reference counting, because ref/deref are not thread-safe.
- if (!isStatic()) {
- if (identifierTable())
- Identifier::remove(this);
- if (baseString == this)
- fastFree(buf);
- else
- baseString->deref();
-
- delete this;
- }
-}
-
-// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
-// or anything like that.
-const unsigned PHI = 0x9e3779b9U;
-
-// Paul Hsieh's SuperFastHash
-// http://www.azillionmonkeys.com/qed/hash.html
-unsigned UString::Rep::computeHash(const UChar* s, int len)
-{
- unsigned l = len;
- uint32_t hash = PHI;
- uint32_t tmp;
-
- int rem = l & 1;
- l >>= 1;
-
- // Main loop
- for (; l > 0; l--) {
- hash += s[0];
- tmp = (s[1] << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- s += 2;
- hash += hash >> 11;
- }
-
- // Handle end case
- if (rem) {
- hash += s[0];
- hash ^= hash << 11;
- hash += hash >> 17;
- }
-
- // Force "avalanching" of final 127 bits
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 2;
- hash += hash >> 15;
- hash ^= hash << 10;
-
- // this avoids ever returning a hash code of 0, since that is used to
- // signal "hash not computed yet", using a value that is likely to be
- // effectively the same as 0 when the low bits are masked
- if (hash == 0)
- hash = 0x80000000;
-
- return hash;
-}
-
-// Paul Hsieh's SuperFastHash
-// http://www.azillionmonkeys.com/qed/hash.html
-unsigned UString::Rep::computeHash(const char* s, int l)
-{
- // This hash is designed to work on 16-bit chunks at a time. But since the normal case
- // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
- // were 16-bit chunks, which should give matching results
-
- uint32_t hash = PHI;
- uint32_t tmp;
-
- size_t rem = l & 1;
- l >>= 1;
-
- // Main loop
- for (; l > 0; l--) {
- hash += static_cast<unsigned char>(s[0]);
- tmp = (static_cast<unsigned char>(s[1]) << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- s += 2;
- hash += hash >> 11;
- }
-
- // Handle end case
- if (rem) {
- hash += static_cast<unsigned char>(s[0]);
- hash ^= hash << 11;
- hash += hash >> 17;
- }
-
- // Force "avalanching" of final 127 bits
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 2;
- hash += hash >> 15;
- hash ^= hash << 10;
-
- // this avoids ever returning a hash code of 0, since that is used to
- // signal "hash not computed yet", using a value that is likely to be
- // effectively the same as 0 when the low bits are masked
- if (hash == 0)
- hash = 0x80000000;
-
- return hash;
-}
-
-#ifndef NDEBUG
-void UString::Rep::checkConsistency() const
-{
- // Only base strings have non-zero shared data.
- if (this != baseString) {
- ASSERT(!buf);
- ASSERT(!usedCapacity);
- ASSERT(!capacity);
- ASSERT(!usedPreCapacity);
- ASSERT(!preCapacity);
- }
-
- // There is no recursion for base strings.
- ASSERT(baseString == baseString->baseString);
-
- if (isStatic()) {
- // There are only two static strings: null and empty.
- ASSERT(!len);
-
- // Static strings cannot get in identifier tables, because they are globally shared.
- ASSERT(!identifierTable());
- }
-
- // The string fits in buffer.
- ASSERT(baseString->usedPreCapacity <= baseString->preCapacity);
- ASSERT(baseString->usedCapacity <= baseString->capacity);
- ASSERT(-offset <= baseString->usedPreCapacity);
- ASSERT(offset + len <= baseString->usedCapacity);
-}
-#endif
-
-// put these early so they can be inlined
-static inline size_t expandedSize(size_t size, size_t otherSize)
-{
- // Do the size calculation in two parts, returning overflowIndicator if
- // we overflow the maximum value that we can handle.
-
- if (size > maxUChars())
- return overflowIndicator();
-
- size_t expandedSize = ((size + 10) / 10 * 11) + 1;
- if (maxUChars() - expandedSize < otherSize)
- return overflowIndicator();
-
- return expandedSize + otherSize;
-}
-
-inline int UString::usedCapacity() const
-{
- return m_rep->baseString->usedCapacity;
-}
-
-inline int UString::usedPreCapacity() const
-{
- return m_rep->baseString->usedPreCapacity;
-}
-
-
-static inline bool expandCapacity(UString::Rep* rep, int requiredLength)
-{
- rep->checkConsistency();
-
- UString::Rep* r = rep->baseString;
-
- if (requiredLength > r->capacity) {
- size_t newCapacity = expandedSize(requiredLength, r->preCapacity);
- UChar* oldBuf = r->buf;
- r->buf = reallocChars(r->buf, newCapacity);
- if (!r->buf) {
- r->buf = oldBuf;
- return false;
- }
- r->capacity = newCapacity - r->preCapacity;
- }
- if (requiredLength > r->usedCapacity)
- r->usedCapacity = requiredLength;
-
- rep->checkConsistency();
- return true;
-}
-
-void UString::expandCapacity(int requiredLength)
-{
- if (!JSC::expandCapacity(m_rep.get(), requiredLength))
- makeNull();
-}
-
-void UString::expandPreCapacity(int requiredPreCap)
-{
- m_rep->checkConsistency();
-
- Rep* r = m_rep->baseString;
-
- if (requiredPreCap > r->preCapacity) {
- size_t newCapacity = expandedSize(requiredPreCap, r->capacity);
- int delta = newCapacity - r->capacity - r->preCapacity;
-
- UChar* newBuf = allocChars(newCapacity);
- if (!newBuf) {
- makeNull();
- return;
- }
- copyChars(newBuf + delta, r->buf, r->capacity + r->preCapacity);
- fastFree(r->buf);
- r->buf = newBuf;
-
- r->preCapacity = newCapacity - r->capacity;
- }
- if (requiredPreCap > r->usedPreCapacity)
- r->usedPreCapacity = requiredPreCap;
-
- m_rep->checkConsistency();
-}
-
-PassRefPtr<UString::Rep> createRep(const char* c)
-{
- if (!c)
- return &UString::Rep::null;
-
- if (!c[0])
- return &UString::Rep::empty;
-
- size_t length = strlen(c);
- UChar* d = allocChars(length);
- if (!d)
- return &UString::Rep::null;
- else {
- for (size_t i = 0; i < length; i++)
- d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
- return UString::Rep::create(d, static_cast<int>(length));
- }
-
-}
-
-UString::UString(const char* c)
- : m_rep(createRep(c))
-{
-}
-
-UString::UString(const UChar* c, int length)
-{
- if (length == 0)
- m_rep = &Rep::empty;
- else
- m_rep = Rep::createCopying(c, length);
-}
-
-UString::UString(UChar* c, int length, bool copy)
-{
- if (length == 0)
- m_rep = &Rep::empty;
- else if (copy)
- m_rep = Rep::createCopying(c, length);
- else
- m_rep = Rep::create(c, length);
-}
-
-UString::UString(const Vector<UChar>& buffer)
-{
- if (!buffer.size())
- m_rep = &Rep::empty;
- else
- m_rep = Rep::createCopying(buffer.data(), buffer.size());
-}
-
-static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const UChar* tData, int tSize)
-{
- RefPtr<UString::Rep> rep = r;
-
- rep->checkConsistency();
-
- int thisSize = rep->size();
- int thisOffset = rep->offset;
- int length = thisSize + tSize;
-
- // possible cases:
- if (tSize == 0) {
- // t is empty
- } else if (thisSize == 0) {
- // this is empty
- rep = UString::Rep::createCopying(tData, tSize);
- } else if (rep->baseIsSelf() && rep->rc == 1) {
- // this is direct and has refcount of 1 (so we can just alter it directly)
- if (!expandCapacity(rep.get(), thisOffset + length))
- rep = &UString::Rep::null;
- if (rep->data()) {
- copyChars(rep->data() + thisSize, tData, tSize);
- rep->len = length;
- rep->_hash = 0;
- }
- } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) {
- // this reaches the end of the buffer - extend it if it's long enough to append to
- if (!expandCapacity(rep.get(), thisOffset + length))
- rep = &UString::Rep::null;
- if (rep->data()) {
- copyChars(rep->data() + thisSize, tData, tSize);
- rep = UString::Rep::create(rep, 0, length);
- }
- } else {
- // this is shared with someone using more capacity, gotta make a whole new string
- size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- rep = &UString::Rep::null;
- else {
- copyChars(d, rep->data(), thisSize);
- copyChars(d + thisSize, tData, tSize);
- rep = UString::Rep::create(d, length);
- rep->capacity = newCapacity;
- }
- }
-
- rep->checkConsistency();
-
- return rep.release();
-}
-
-static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const char* t)
-{
- RefPtr<UString::Rep> rep = r;
-
- rep->checkConsistency();
-
- int thisSize = rep->size();
- int thisOffset = rep->offset;
- int tSize = static_cast<int>(strlen(t));
- int length = thisSize + tSize;
-
- // possible cases:
- if (thisSize == 0) {
- // this is empty
- rep = createRep(t);
- } else if (tSize == 0) {
- // t is empty, we'll just return *this below.
- } else if (rep->baseIsSelf() && rep->rc == 1) {
- // this is direct and has refcount of 1 (so we can just alter it directly)
- expandCapacity(rep.get(), thisOffset + length);
- UChar* d = rep->data();
- if (d) {
- for (int i = 0; i < tSize; ++i)
- d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
- rep->len = length;
- rep->_hash = 0;
- }
- } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) {
- // this string reaches the end of the buffer - extend it
- expandCapacity(rep.get(), thisOffset + length);
- UChar* d = rep->data();
- if (d) {
- for (int i = 0; i < tSize; ++i)
- d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
- rep = UString::Rep::create(rep, 0, length);
- }
- } else {
- // this is shared with someone using more capacity, gotta make a whole new string
- size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- rep = &UString::Rep::null;
- else {
- copyChars(d, rep->data(), thisSize);
- for (int i = 0; i < tSize; ++i)
- d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
- rep = UString::Rep::create(d, length);
- rep->capacity = newCapacity;
- }
- }
-
- rep->checkConsistency();
-
- return rep.release();
-}
-
-PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b)
-{
- a->checkConsistency();
- b->checkConsistency();
-
- int aSize = a->size();
- int aOffset = a->offset;
- int bSize = b->size();
- int bOffset = b->offset;
- int length = aSize + bSize;
-
- // possible cases:
-
- // a is empty
- if (aSize == 0)
- return b;
- // b is empty
- if (bSize == 0)
- return a;
-
- if (bSize == 1 && aOffset + aSize == a->baseString->usedCapacity && aOffset + length <= a->baseString->capacity) {
- // b is a single character (common fast case)
- a->baseString->usedCapacity = aOffset + length;
- a->data()[aSize] = b->data()[0];
- return UString::Rep::create(a, 0, length);
- }
-
- if (aOffset + aSize == a->baseString->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize &&
- (-bOffset != b->baseString->usedPreCapacity || aSize >= bSize)) {
- // - a reaches the end of its buffer so it qualifies for shared append
- // - also, it's at least a quarter the length of b - appending to a much shorter
- // string does more harm than good
- // - however, if b qualifies for prepend and is longer than a, we'd rather prepend
- UString x(a);
- x.expandCapacity(aOffset + length);
- if (!a->data() || !x.data())
- return 0;
- copyChars(a->data() + aSize, b->data(), bSize);
- PassRefPtr<UString::Rep> result = UString::Rep::create(a, 0, length);
-
- a->checkConsistency();
- b->checkConsistency();
- result->checkConsistency();
-
- return result;
- }
-
- if (-bOffset == b->baseString->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) {
- // - b reaches the beginning of its buffer so it qualifies for shared prepend
- // - also, it's at least a quarter the length of a - prepending to a much shorter
- // string does more harm than good
- UString y(b);
- y.expandPreCapacity(-bOffset + aSize);
- if (!b->data() || !y.data())
- return 0;
- copyChars(b->data() - aSize, a->data(), aSize);
- PassRefPtr<UString::Rep> result = UString::Rep::create(b, -aSize, length);
-
- a->checkConsistency();
- b->checkConsistency();
- result->checkConsistency();
-
- return result;
- }
-
- // a does not qualify for append, and b does not qualify for prepend, gotta make a whole new string
- size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- return 0;
- copyChars(d, a->data(), aSize);
- copyChars(d + aSize, b->data(), bSize);
- PassRefPtr<UString::Rep> result = UString::Rep::create(d, length);
- result->capacity = newCapacity;
-
- a->checkConsistency();
- b->checkConsistency();
- result->checkConsistency();
-
- return result;
-}
-
-PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, int i)
-{
- UChar buf[1 + sizeof(i) * 3];
- UChar* end = buf + sizeof(buf) / sizeof(UChar);
- UChar* p = end;
-
- if (i == 0)
- *--p = '0';
- else if (i == INT_MIN) {
- char minBuf[1 + sizeof(i) * 3];
- sprintf(minBuf, "%d", INT_MIN);
- return concatenate(rep, minBuf);
- } else {
- bool negative = false;
- if (i < 0) {
- negative = true;
- i = -i;
- }
- while (i) {
- *--p = static_cast<unsigned short>((i % 10) + '0');
- i /= 10;
- }
- if (negative)
- *--p = '-';
- }
-
- return concatenate(rep, p, static_cast<int>(end - p));
-
-}
-
-PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, double d)
-{
- // avoid ever printing -NaN, in JS conceptually there is only one NaN value
- if (isnan(d))
- return concatenate(rep, "NaN");
-
- if (d == 0.0) // stringify -0 as 0
- d = 0.0;
-
- char buf[80];
- int decimalPoint;
- int sign;
-
- char* result = dtoa(d, 0, &decimalPoint, &sign, NULL);
- int length = static_cast<int>(strlen(result));
-
- int i = 0;
- if (sign)
- buf[i++] = '-';
-
- if (decimalPoint <= 0 && decimalPoint > -6) {
- buf[i++] = '0';
- buf[i++] = '.';
- for (int j = decimalPoint; j < 0; j++)
- buf[i++] = '0';
- strcpy(buf + i, result);
- } else if (decimalPoint <= 21 && decimalPoint > 0) {
- if (length <= decimalPoint) {
- strcpy(buf + i, result);
- i += length;
- for (int j = 0; j < decimalPoint - length; j++)
- buf[i++] = '0';
- buf[i] = '\0';
- } else {
- strncpy(buf + i, result, decimalPoint);
- i += decimalPoint;
- buf[i++] = '.';
- strcpy(buf + i, result + decimalPoint);
- }
- } else if (result[0] < '0' || result[0] > '9')
- strcpy(buf + i, result);
- else {
- buf[i++] = result[0];
- if (length > 1) {
- buf[i++] = '.';
- strcpy(buf + i, result + 1);
- i += length - 1;
- }
-
- buf[i++] = 'e';
- buf[i++] = (decimalPoint >= 0) ? '+' : '-';
- // decimalPoint can't be more than 3 digits decimal given the
- // nature of float representation
- int exponential = decimalPoint - 1;
- if (exponential < 0)
- exponential = -exponential;
- if (exponential >= 100)
- buf[i++] = static_cast<char>('0' + exponential / 100);
- if (exponential >= 10)
- buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
- buf[i++] = static_cast<char>('0' + exponential % 10);
- buf[i++] = '\0';
- }
-
- freedtoa(result);
-
- return concatenate(rep, buf);
-}
-
-const UString& UString::null()
-{
- static UString* n = new UString; // Should be called from main thread at least once to be safely initialized.
- return *n;
-}
-
-UString UString::from(int i)
-{
- UChar buf[1 + sizeof(i) * 3];
- UChar* end = buf + sizeof(buf) / sizeof(UChar);
- UChar* p = end;
-
- if (i == 0)
- *--p = '0';
- else if (i == INT_MIN) {
- char minBuf[1 + sizeof(i) * 3];
- sprintf(minBuf, "%d", INT_MIN);
- return UString(minBuf);
- } else {
- bool negative = false;
- if (i < 0) {
- negative = true;
- i = -i;
- }
- while (i) {
- *--p = static_cast<unsigned short>((i % 10) + '0');
- i /= 10;
- }
- if (negative)
- *--p = '-';
- }
-
- return UString(p, static_cast<int>(end - p));
-}
-
-UString UString::from(unsigned int u)
-{
- UChar buf[sizeof(u) * 3];
- UChar* end = buf + sizeof(buf) / sizeof(UChar);
- UChar* p = end;
-
- if (u == 0)
- *--p = '0';
- else {
- while (u) {
- *--p = static_cast<unsigned short>((u % 10) + '0');
- u /= 10;
- }
- }
-
- return UString(p, static_cast<int>(end - p));
-}
-
-UString UString::from(long l)
-{
- UChar buf[1 + sizeof(l) * 3];
- UChar* end = buf + sizeof(buf) / sizeof(UChar);
- UChar* p = end;
-
- if (l == 0)
- *--p = '0';
- else if (l == LONG_MIN) {
- char minBuf[1 + sizeof(l) * 3];
- sprintf(minBuf, "%ld", LONG_MIN);
- return UString(minBuf);
- } else {
- bool negative = false;
- if (l < 0) {
- negative = true;
- l = -l;
- }
- while (l) {
- *--p = static_cast<unsigned short>((l % 10) + '0');
- l /= 10;
- }
- if (negative)
- *--p = '-';
- }
-
- return UString(p, static_cast<int>(end - p));
-}
-
-UString UString::from(double d)
-{
- // avoid ever printing -NaN, in JS conceptually there is only one NaN value
- if (isnan(d))
- return "NaN";
-
- char buf[80];
- int decimalPoint;
- int sign;
-
- char* result = dtoa(d, 0, &decimalPoint, &sign, NULL);
- int length = static_cast<int>(strlen(result));
-
- int i = 0;
- if (sign)
- buf[i++] = '-';
-
- if (decimalPoint <= 0 && decimalPoint > -6) {
- buf[i++] = '0';
- buf[i++] = '.';
- for (int j = decimalPoint; j < 0; j++)
- buf[i++] = '0';
- strcpy(buf + i, result);
- } else if (decimalPoint <= 21 && decimalPoint > 0) {
- if (length <= decimalPoint) {
- strcpy(buf + i, result);
- i += length;
- for (int j = 0; j < decimalPoint - length; j++)
- buf[i++] = '0';
- buf[i] = '\0';
- } else {
- strncpy(buf + i, result, decimalPoint);
- i += decimalPoint;
- buf[i++] = '.';
- strcpy(buf + i, result + decimalPoint);
- }
- } else if (result[0] < '0' || result[0] > '9')
- strcpy(buf + i, result);
- else {
- buf[i++] = result[0];
- if (length > 1) {
- buf[i++] = '.';
- strcpy(buf + i, result + 1);
- i += length - 1;
- }
-
- buf[i++] = 'e';
- buf[i++] = (decimalPoint >= 0) ? '+' : '-';
- // decimalPoint can't be more than 3 digits decimal given the
- // nature of float representation
- int exponential = decimalPoint - 1;
- if (exponential < 0)
- exponential = -exponential;
- if (exponential >= 100)
- buf[i++] = static_cast<char>('0' + exponential / 100);
- if (exponential >= 10)
- buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
- buf[i++] = static_cast<char>('0' + exponential % 10);
- buf[i++] = '\0';
- }
-
- freedtoa(result);
-
- return UString(buf);
-}
-
-UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
-{
- m_rep->checkConsistency();
-
- if (rangeCount == 1 && separatorCount == 0) {
- int thisSize = size();
- int position = substringRanges[0].position;
- int length = substringRanges[0].length;
- if (position <= 0 && length >= thisSize)
- return *this;
- return UString::Rep::create(m_rep, max(0, position), min(thisSize, length));
- }
-
- int totalLength = 0;
- for (int i = 0; i < rangeCount; i++)
- totalLength += substringRanges[i].length;
- for (int i = 0; i < separatorCount; i++)
- totalLength += separators[i].size();
-
- if (totalLength == 0)
- return "";
-
- UChar* buffer = allocChars(totalLength);
- if (!buffer)
- return null();
-
- int maxCount = max(rangeCount, separatorCount);
- int bufferPos = 0;
- for (int i = 0; i < maxCount; i++) {
- if (i < rangeCount) {
- copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length);
- bufferPos += substringRanges[i].length;
- }
- if (i < separatorCount) {
- copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
- bufferPos += separators[i].size();
- }
- }
-
- return UString::Rep::create(buffer, totalLength);
-}
-
-UString& UString::append(const UString &t)
-{
- m_rep->checkConsistency();
- t.rep()->checkConsistency();
-
- int thisSize = size();
- int thisOffset = m_rep->offset;
- int tSize = t.size();
- int length = thisSize + tSize;
-
- // possible cases:
- if (thisSize == 0) {
- // this is empty
- *this = t;
- } else if (tSize == 0) {
- // t is empty
- } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
- // this is direct and has refcount of 1 (so we can just alter it directly)
- expandCapacity(thisOffset + length);
- if (data()) {
- copyChars(m_rep->data() + thisSize, t.data(), tSize);
- m_rep->len = length;
- m_rep->_hash = 0;
- }
- } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
- // this reaches the end of the buffer - extend it if it's long enough to append to
- expandCapacity(thisOffset + length);
- if (data()) {
- copyChars(m_rep->data() + thisSize, t.data(), tSize);
- m_rep = Rep::create(m_rep, 0, length);
- }
- } else {
- // this is shared with someone using more capacity, gotta make a whole new string
- size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- makeNull();
- else {
- copyChars(d, data(), thisSize);
- copyChars(d + thisSize, t.data(), tSize);
- m_rep = Rep::create(d, length);
- m_rep->capacity = newCapacity;
- }
- }
-
- m_rep->checkConsistency();
- t.rep()->checkConsistency();
-
- return *this;
-}
-
-UString& UString::append(const UChar* tData, int tSize)
-{
- m_rep = concatenate(m_rep.release(), tData, tSize);
- return *this;
-}
-
-UString& UString::append(const char* t)
-{
- m_rep = concatenate(m_rep.release(), t);
- return *this;
-}
-
-UString& UString::append(UChar c)
-{
- m_rep->checkConsistency();
-
- int thisOffset = m_rep->offset;
- int length = size();
-
- // possible cases:
- if (length == 0) {
- // this is empty - must make a new m_rep because we don't want to pollute the shared empty one
- size_t newCapacity = expandedSize(1, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- makeNull();
- else {
- d[0] = c;
- m_rep = Rep::create(d, 1);
- m_rep->capacity = newCapacity;
- }
- } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
- // this is direct and has refcount of 1 (so we can just alter it directly)
- expandCapacity(thisOffset + length + 1);
- UChar* d = m_rep->data();
- if (d) {
- d[length] = c;
- m_rep->len = length + 1;
- m_rep->_hash = 0;
- }
- } else if (thisOffset + length == usedCapacity() && length >= minShareSize) {
- // this reaches the end of the string - extend it and share
- expandCapacity(thisOffset + length + 1);
- UChar* d = m_rep->data();
- if (d) {
- d[length] = c;
- m_rep = Rep::create(m_rep, 0, length + 1);
- }
- } else {
- // this is shared with someone using more capacity, gotta make a whole new string
- size_t newCapacity = expandedSize(length + 1, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- makeNull();
- else {
- copyChars(d, data(), length);
- d[length] = c;
- m_rep = Rep::create(d, length + 1);
- m_rep->capacity = newCapacity;
- }
- }
-
- m_rep->checkConsistency();
-
- return *this;
-}
-
-bool UString::getCString(CStringBuffer& buffer) const
-{
- int length = size();
- int neededSize = length + 1;
- buffer.resize(neededSize);
- char* buf = buffer.data();
-
- UChar ored = 0;
- const UChar* p = data();
- char* q = buf;
- const UChar* limit = p + length;
- while (p != limit) {
- UChar c = p[0];
- ored |= c;
- *q = static_cast<char>(c);
- ++p;
- ++q;
- }
- *q = '\0';
-
- return !(ored & 0xFF00);
-}
-
-char* UString::ascii() const
-{
- int length = size();
- int neededSize = length + 1;
- delete[] statBuffer;
- statBuffer = new char[neededSize];
-
- const UChar* p = data();
- char* q = statBuffer;
- const UChar* limit = p + length;
- while (p != limit) {
- *q = static_cast<char>(p[0]);
- ++p;
- ++q;
- }
- *q = '\0';
-
- return statBuffer;
-}
-
-UString& UString::operator=(const char* c)
-{
- if (!c) {
- m_rep = &Rep::null;
- return *this;
- }
-
- if (!c[0]) {
- m_rep = &Rep::empty;
- return *this;
- }
-
- int l = static_cast<int>(strlen(c));
- UChar* d;
- if (m_rep->rc == 1 && l <= m_rep->capacity && m_rep->baseIsSelf() && m_rep->offset == 0 && m_rep->preCapacity == 0) {
- d = m_rep->buf;
- m_rep->_hash = 0;
- m_rep->len = l;
- } else {
- d = allocChars(l);
- if (!d) {
- makeNull();
- return *this;
- }
- m_rep = Rep::create(d, l);
- }
- for (int i = 0; i < l; i++)
- d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
-
- return *this;
-}
-
-bool UString::is8Bit() const
-{
- const UChar* u = data();
- const UChar* limit = u + size();
- while (u < limit) {
- if (u[0] > 0xFF)
- return false;
- ++u;
- }
-
- return true;
-}
-
-UChar UString::operator[](int pos) const
-{
- if (pos >= size())
- return '\0';
- return data()[pos];
-}
-
-double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
-{
- if (size() == 1) {
- UChar c = data()[0];
- if (isASCIIDigit(c))
- return c - '0';
- if (isASCIISpace(c) && tolerateEmptyString)
- return 0;
- return NaN;
- }
-
- // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk
- // after the number, so this is too strict a check.
- CStringBuffer s;
- if (!getCString(s))
- return NaN;
- const char* c = s.data();
-
- // skip leading white space
- while (isASCIISpace(*c))
- c++;
-
- // empty string ?
- if (*c == '\0')
- return tolerateEmptyString ? 0.0 : NaN;
-
- double d;
-
- // hex number ?
- if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
- const char* firstDigitPosition = c + 2;
- c++;
- d = 0.0;
- while (*(++c)) {
- if (*c >= '0' && *c <= '9')
- d = d * 16.0 + *c - '0';
- else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
- d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
- else
- break;
- }
-
- if (d >= mantissaOverflowLowerBound)
- d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
- } else {
- // regular number ?
- char* end;
- d = strtod(c, &end);
- if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
- c = end;
- } else {
- double sign = 1.0;
-
- if (*c == '+')
- c++;
- else if (*c == '-') {
- sign = -1.0;
- c++;
- }
-
- // We used strtod() to do the conversion. However, strtod() handles
- // infinite values slightly differently than JavaScript in that it
- // converts the string "inf" with any capitalization to infinity,
- // whereas the ECMA spec requires that it be converted to NaN.
-
- if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
- d = sign * Inf;
- c += 8;
- } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
- c = end;
- else
- return NaN;
- }
- }
-
- // allow trailing white space
- while (isASCIISpace(*c))
- c++;
- // don't allow anything after - unless tolerant=true
- if (!tolerateTrailingJunk && *c != '\0')
- d = NaN;
-
- return d;
-}
-
-double UString::toDouble(bool tolerateTrailingJunk) const
-{
- return toDouble(tolerateTrailingJunk, true);
-}
-
-double UString::toDouble() const
-{
- return toDouble(false, true);
-}
-
-uint32_t UString::toUInt32(bool* ok) const
-{
- double d = toDouble();
- bool b = true;
-
- if (d != static_cast<uint32_t>(d)) {
- b = false;
- d = 0;
- }
-
- if (ok)
- *ok = b;
-
- return static_cast<uint32_t>(d);
-}
-
-uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const
-{
- double d = toDouble(false, tolerateEmptyString);
- bool b = true;
-
- if (d != static_cast<uint32_t>(d)) {
- b = false;
- d = 0;
- }
-
- if (ok)
- *ok = b;
-
- return static_cast<uint32_t>(d);
-}
-
-uint32_t UString::toStrictUInt32(bool* ok) const
-{
- if (ok)
- *ok = false;
-
- // Empty string is not OK.
- int len = m_rep->len;
- if (len == 0)
- return 0;
- const UChar* p = m_rep->data();
- unsigned short c = p[0];
-
- // If the first digit is 0, only 0 itself is OK.
- if (c == '0') {
- if (len == 1 && ok)
- *ok = true;
- return 0;
- }
-
- // Convert to UInt32, checking for overflow.
- uint32_t i = 0;
- while (1) {
- // Process character, turning it into a digit.
- if (c < '0' || c > '9')
- return 0;
- const unsigned d = c - '0';
-
- // Multiply by 10, checking for overflow out of 32 bits.
- if (i > 0xFFFFFFFFU / 10)
- return 0;
- i *= 10;
-
- // Add in the digit, checking for overflow out of 32 bits.
- const unsigned max = 0xFFFFFFFFU - d;
- if (i > max)
- return 0;
- i += d;
-
- // Handle end of string.
- if (--len == 0) {
- if (ok)
- *ok = true;
- return i;
- }
-
- // Get next character.
- c = *(++p);
- }
-}
-
-int UString::find(const UString& f, int pos) const
-{
- int sz = size();
- int fsz = f.size();
- if (sz < fsz)
- return -1;
- if (pos < 0)
- pos = 0;
- if (fsz == 0)
- return pos;
- const UChar* end = data() + sz - fsz;
- int fsizeminusone = (fsz - 1) * sizeof(UChar);
- const UChar* fdata = f.data();
- unsigned short fchar = fdata[0];
- ++fdata;
- for (const UChar* c = data() + pos; c <= end; c++) {
- if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone))
- return static_cast<int>(c - data());
- }
-
- return -1;
-}
-
-int UString::find(UChar ch, int pos) const
-{
- if (pos < 0)
- pos = 0;
- const UChar* end = data() + size();
- for (const UChar* c = data() + pos; c < end; c++) {
- if (*c == ch)
- return static_cast<int>(c - data());
- }
-
- return -1;
-}
-
-int UString::rfind(const UString& f, int pos) const
-{
- int sz = size();
- int fsz = f.size();
- if (sz < fsz)
- return -1;
- if (pos < 0)
- pos = 0;
- if (pos > sz - fsz)
- pos = sz - fsz;
- if (fsz == 0)
- return pos;
- int fsizeminusone = (fsz - 1) * sizeof(UChar);
- const UChar* fdata = f.data();
- for (const UChar* c = data() + pos; c >= data(); c--) {
- if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
- return static_cast<int>(c - data());
- }
-
- return -1;
-}
-
-int UString::rfind(UChar ch, int pos) const
-{
- if (isEmpty())
- return -1;
- if (pos + 1 >= size())
- pos = size() - 1;
- for (const UChar* c = data() + pos; c >= data(); c--) {
- if (*c == ch)
- return static_cast<int>(c - data());
- }
-
- return -1;
-}
-
-UString UString::substr(int pos, int len) const
-{
- int s = size();
-
- if (pos < 0)
- pos = 0;
- else if (pos >= s)
- pos = s;
- if (len < 0)
- len = s;
- if (pos + len >= s)
- len = s - pos;
-
- if (pos == 0 && len == s)
- return *this;
-
- return UString(Rep::create(m_rep, pos, len));
-}
-
-bool operator==(const UString& s1, const UString& s2)
-{
- int size = s1.size();
- switch (size) {
- case 0:
- return !s2.size();
- case 1:
- return s2.size() == 1 && s1.data()[0] == s2.data()[0];
- default:
- return s2.size() == size && memcmp(s1.data(), s2.data(), size * sizeof(UChar)) == 0;
- }
-}
-
-bool operator==(const UString& s1, const char *s2)
-{
- if (s2 == 0)
- return s1.isEmpty();
-
- const UChar* u = s1.data();
- const UChar* uend = u + s1.size();
- while (u != uend && *s2) {
- if (u[0] != (unsigned char)*s2)
- return false;
- s2++;
- u++;
- }
-
- return u == uend && *s2 == 0;
-}
-
-bool operator<(const UString& s1, const UString& s2)
-{
- const int l1 = s1.size();
- const int l2 = s2.size();
- const int lmin = l1 < l2 ? l1 : l2;
- const UChar* c1 = s1.data();
- const UChar* c2 = s2.data();
- int l = 0;
- while (l < lmin && *c1 == *c2) {
- c1++;
- c2++;
- l++;
- }
- if (l < lmin)
- return (c1[0] < c2[0]);
-
- return (l1 < l2);
-}
-
-bool operator>(const UString& s1, const UString& s2)
-{
- const int l1 = s1.size();
- const int l2 = s2.size();
- const int lmin = l1 < l2 ? l1 : l2;
- const UChar* c1 = s1.data();
- const UChar* c2 = s2.data();
- int l = 0;
- while (l < lmin && *c1 == *c2) {
- c1++;
- c2++;
- l++;
- }
- if (l < lmin)
- return (c1[0] > c2[0]);
-
- return (l1 > l2);
-}
-
-int compare(const UString& s1, const UString& s2)
-{
- const int l1 = s1.size();
- const int l2 = s2.size();
- const int lmin = l1 < l2 ? l1 : l2;
- const UChar* c1 = s1.data();
- const UChar* c2 = s2.data();
- int l = 0;
- while (l < lmin && *c1 == *c2) {
- c1++;
- c2++;
- l++;
- }
-
- if (l < lmin)
- return (c1[0] > c2[0]) ? 1 : -1;
-
- if (l1 == l2)
- return 0;
-
- return (l1 > l2) ? 1 : -1;
-}
-
-bool equal(const UString::Rep* r, const UString::Rep* b)
-{
- int length = r->len;
- if (length != b->len)
- return false;
- const UChar* d = r->data();
- const UChar* s = b->data();
- for (int i = 0; i != length; ++i) {
- if (d[i] != s[i])
- return false;
- }
- return true;
-}
-
-CString UString::UTF8String(bool strict) const
-{
- // Allocate a buffer big enough to hold all the characters.
- const int length = size();
- Vector<char, 1024> buffer(length * 3);
-
- // Convert to runs of 8-bit characters.
- char* p = buffer.data();
- const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
- ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
- if (result != conversionOK)
- return CString();
-
- return CString(buffer.data(), p - buffer.data());
-}
-
-// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
-NEVER_INLINE void UString::makeNull()
-{
- m_rep = &Rep::null;
-}
-
-// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
-NEVER_INLINE UString::Rep* UString::nullRep()
-{
- return &Rep::null;
-}
-
-} // namespace JSC
diff --git a/JavaScriptCore/kjs/ustring.h b/JavaScriptCore/kjs/ustring.h
deleted file mode 100644
index f47b134..0000000
--- a/JavaScriptCore/kjs/ustring.h
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef _KJS_USTRING_H_
-#define _KJS_USTRING_H_
-
-#include "collector.h"
-#include <stdint.h>
-#include <string.h>
-#include <wtf/Assertions.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-#include <wtf/unicode/Unicode.h>
-
-namespace JSC {
-
- using WTF::PlacementNewAdoptType;
- using WTF::PlacementNewAdopt;
-
- class IdentifierTable;
-
- class CString {
- public:
- CString()
- : m_length(0)
- , m_data(0)
- {
- }
-
- CString(const char*);
- CString(const char*, size_t);
- CString(const CString&);
-
- ~CString();
-
- static CString adopt(char*, size_t); // buffer should be allocated with new[].
-
- CString& append(const CString&);
- CString& operator=(const char* c);
- CString& operator=(const CString&);
- CString& operator+=(const CString& c) { return append(c); }
-
- size_t size() const { return m_length; }
- const char* c_str() const { return m_data; }
-
- private:
- size_t m_length;
- char* m_data;
- };
-
- typedef Vector<char, 32> CStringBuffer;
-
- class UString {
- friend class CTI;
-
- public:
- struct Rep {
- friend class CTI;
-
- static PassRefPtr<Rep> create(UChar*, int);
- static PassRefPtr<Rep> createCopying(const UChar*, int);
- static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length);
-
- // Constructs a string from a UTF-8 string, using strict conversion (see comments in UTF8.h).
- // Returns UString::Rep::null for null input or conversion failure.
- static PassRefPtr<Rep> createFromUTF8(const char*);
-
- void destroy();
-
- bool baseIsSelf() const { return baseString == this; }
- UChar* data() const { return baseString->buf + baseString->preCapacity + offset; }
- int size() const { return len; }
-
- unsigned hash() const { if (_hash == 0) _hash = computeHash(data(), len); return _hash; }
- unsigned computedHash() const { ASSERT(_hash); return _hash; } // fast path for Identifiers
-
- static unsigned computeHash(const UChar*, int length);
- static unsigned computeHash(const char*, int length);
- static unsigned computeHash(const char* s) { return computeHash(s, strlen(s)); }
-
- IdentifierTable* identifierTable() const { return reinterpret_cast<IdentifierTable*>(m_identifierTable & ~static_cast<uintptr_t>(1)); }
- void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTable = reinterpret_cast<intptr_t>(table); }
-
- bool isStatic() const { return m_identifierTable & 1; }
- void setStatic(bool v) { ASSERT(!identifierTable()); m_identifierTable = v; }
-
- Rep* ref() { ++rc; return this; }
- ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); }
-
- void checkConsistency() const;
-
- // unshared data
- int offset;
- int len;
- int rc; // For null and empty static strings, this field does not reflect a correct count, because ref/deref are not thread-safe. A special case in destroy() guarantees that these do not get deleted.
- mutable unsigned _hash;
- intptr_t m_identifierTable; // A pointer to identifier table. The lowest bit is used to indicate whether the string is static (null or empty).
- UString::Rep* baseString;
- size_t reportedCost;
-
- // potentially shared data. 0 if backed up by a base string.
- UChar* buf;
- int usedCapacity;
- int capacity;
- int usedPreCapacity;
- int preCapacity;
-
- static Rep null;
- static Rep empty;
- };
-
- public:
- UString();
- UString(const char*);
- UString(const UChar*, int length);
- UString(UChar*, int length, bool copy);
-
- UString(const UString& s)
- : m_rep(s.m_rep)
- {
- }
-
- UString(const Vector<UChar>& buffer);
-
- ~UString()
- {
- }
-
- // Special constructor for cases where we overwrite an object in place.
- UString(PlacementNewAdoptType)
- : m_rep(PlacementNewAdopt)
- {
- }
-
- static UString from(int);
- static UString from(unsigned int);
- static UString from(long);
- static UString from(double);
-
- struct Range {
- public:
- Range(int pos, int len)
- : position(pos)
- , length(len)
- {
- }
-
- Range()
- {
- }
-
- int position;
- int length;
- };
-
- UString spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const;
-
- UString& append(const UString&);
- UString& append(const char*);
- UString& append(UChar);
- UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); }
- UString& append(const UChar*, int size);
-
- bool getCString(CStringBuffer&) const;
-
- // NOTE: This method should only be used for *debugging* purposes as it
- // is neither Unicode safe nor free from side effects nor thread-safe.
- char* ascii() const;
-
- /**
- * Convert the string to UTF-8, assuming it is UTF-16 encoded.
- * In non-strict mode, this function is tolerant of badly formed UTF-16, it
- * can create UTF-8 strings that are invalid because they have characters in
- * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is
- * guaranteed to be otherwise valid.
- * In strict mode, error is returned as null CString.
- */
- CString UTF8String(bool strict = false) const;
-
- UString& operator=(const char*c);
-
- UString& operator+=(const UString& s) { return append(s); }
- UString& operator+=(const char* s) { return append(s); }
-
- const UChar* data() const { return m_rep->data(); }
-
- bool isNull() const { return (m_rep == &Rep::null); }
- bool isEmpty() const { return (!m_rep->len); }
-
- bool is8Bit() const;
-
- int size() const { return m_rep->size(); }
-
- UChar operator[](int pos) const;
-
- double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const;
- double toDouble(bool tolerateTrailingJunk) const;
- double toDouble() const;
-
- uint32_t toUInt32(bool* ok = 0) const;
- uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const;
- uint32_t toStrictUInt32(bool* ok = 0) const;
-
- unsigned toArrayIndex(bool* ok = 0) const;
-
- int find(const UString& f, int pos = 0) const;
- int find(UChar, int pos = 0) const;
- int rfind(const UString& f, int pos) const;
- int rfind(UChar, int pos) const;
-
- UString substr(int pos = 0, int len = -1) const;
-
- static const UString& null();
-
- Rep* rep() const { return m_rep.get(); }
- static Rep* nullRep();
-
- UString(PassRefPtr<Rep> r)
- : m_rep(r)
- {
- ASSERT(m_rep);
- }
-
- size_t cost() const;
-
- private:
- int usedCapacity() const;
- int usedPreCapacity() const;
- void expandCapacity(int requiredLength);
- void expandPreCapacity(int requiredPreCap);
- void makeNull();
-
- RefPtr<Rep> m_rep;
-
- friend bool operator==(const UString&, const UString&);
- friend PassRefPtr<Rep> concatenate(Rep*, Rep*); // returns 0 if out of memory
- };
- PassRefPtr<UString::Rep> concatenate(UString::Rep*, UString::Rep*);
- PassRefPtr<UString::Rep> concatenate(UString::Rep*, int);
- PassRefPtr<UString::Rep> concatenate(UString::Rep*, double);
-
- bool operator==(const UString&, const UString&);
-
- inline bool operator!=(const UString& s1, const UString& s2)
- {
- return !JSC::operator==(s1, s2);
- }
-
- bool operator<(const UString& s1, const UString& s2);
- bool operator>(const UString& s1, const UString& s2);
-
- bool operator==(const UString& s1, const char* s2);
-
- inline bool operator!=(const UString& s1, const char* s2)
- {
- return !JSC::operator==(s1, s2);
- }
-
- inline bool operator==(const char *s1, const UString& s2)
- {
- return operator==(s2, s1);
- }
-
- inline bool operator!=(const char *s1, const UString& s2)
- {
- return !JSC::operator==(s1, s2);
- }
-
- bool operator==(const CString&, const CString&);
-
- inline UString operator+(const UString& s1, const UString& s2)
- {
- RefPtr<UString::Rep> result = concatenate(s1.rep(), s2.rep());
- return UString(result ? result.release() : UString::nullRep());
- }
-
- int compare(const UString&, const UString&);
-
- bool equal(const UString::Rep*, const UString::Rep*);
-
-#ifdef NDEBUG
- inline void UString::Rep::checkConsistency() const
- {
- }
-#endif
-
- inline UString::UString()
- : m_rep(&Rep::null)
- {
- }
-
- // Rule from ECMA 15.2 about what an array index is.
- // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
- inline unsigned UString::toArrayIndex(bool* ok) const
- {
- unsigned i = toStrictUInt32(ok);
- if (ok && i >= 0xFFFFFFFFU)
- *ok = false;
- return i;
- }
-
- // We'd rather not do shared substring append for small strings, since
- // this runs too much risk of a tiny initial string holding down a
- // huge buffer.
- // FIXME: this should be size_t but that would cause warnings until we
- // fix UString sizes to be size_t instead of int
- static const int minShareSize = Heap::minExtraCostSize / sizeof(UChar);
-
- inline size_t UString::cost() const
- {
- size_t capacity = (m_rep->baseString->capacity + m_rep->baseString->preCapacity) * sizeof(UChar);
- size_t reportedCost = m_rep->baseString->reportedCost;
- ASSERT(capacity >= reportedCost);
-
- size_t capacityDelta = capacity - reportedCost;
-
- if (capacityDelta < static_cast<size_t>(minShareSize))
- return 0;
-
- m_rep->baseString->reportedCost = capacity;
-
- return capacityDelta;
- }
-
- struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > {
- static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->computedHash(); }
- static unsigned hash(JSC::UString::Rep* key) { return key->computedHash(); }
- };
-
-} // namespace JSC
-
-namespace WTF {
-
- template<typename T> struct DefaultHash;
- template<typename T> struct StrHash;
-
- template<> struct StrHash<JSC::UString::Rep*> {
- static unsigned hash(const JSC::UString::Rep* key) { return key->hash(); }
- static bool equal(const JSC::UString::Rep* a, const JSC::UString::Rep* b) { return JSC::equal(a, b); }
- static const bool safeToCompareToEmptyOrDeleted = false;
- };
-
- template<> struct StrHash<RefPtr<JSC::UString::Rep> > : public StrHash<JSC::UString::Rep*> {
- using StrHash<JSC::UString::Rep*>::hash;
- static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->hash(); }
- using StrHash<JSC::UString::Rep*>::equal;
- static bool equal(const RefPtr<JSC::UString::Rep>& a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a.get(), b.get()); }
- static bool equal(const JSC::UString::Rep* a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a, b.get()); }
- static bool equal(const RefPtr<JSC::UString::Rep>& a, const JSC::UString::Rep* b) { return JSC::equal(a.get(), b); }
-
- static const bool safeToCompareToEmptyOrDeleted = false;
- };
-
- template<> struct DefaultHash<JSC::UString::Rep*> {
- typedef StrHash<JSC::UString::Rep*> Hash;
- };
-
- template<> struct DefaultHash<RefPtr<JSC::UString::Rep> > {
- typedef StrHash<RefPtr<JSC::UString::Rep> > Hash;
-
- };
-
-} // namespace WTF
-
-#endif