summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-06-28 16:42:48 +0100
committerKristian Monsen <kristianm@google.com>2010-07-02 10:29:56 +0100
commit06ea8e899e48f1f2f396b70e63fae369f2f23232 (patch)
tree20c1428cd05c76f32394ab354ea35ed99acd86d8 /JavaScriptCore
parent72aad67af14193199e29cdd5c4ddc095a8b9a8a8 (diff)
downloadexternal_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.zip
external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.gz
external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.bz2
Merge WebKit at r61871: Initial merge by git.
Change-Id: I6cff43abca9cc4782e088a469ad4f03f166a65d5
Diffstat (limited to 'JavaScriptCore')
-rw-r--r--JavaScriptCore/API/JSClassRef.h1
-rw-r--r--JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp1
-rw-r--r--JavaScriptCore/CMakeLists.txt16
-rw-r--r--JavaScriptCore/ChangeLog954
-rw-r--r--JavaScriptCore/Configurations/FeatureDefines.xcconfig3
-rw-r--r--JavaScriptCore/Configurations/Version.xcconfig2
-rw-r--r--JavaScriptCore/GNUmakefile.am7
-rw-r--r--JavaScriptCore/JavaScriptCore.gypi7
-rw-r--r--JavaScriptCore/JavaScriptCore.pri24
-rw-r--r--JavaScriptCore/JavaScriptCore.pro4
-rw-r--r--JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make2
-rw-r--r--JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj28
-rw-r--r--JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj28
-rw-r--r--JavaScriptCore/assembler/AssemblerBuffer.h3
-rw-r--r--JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h3
-rw-r--r--JavaScriptCore/bytecode/CodeBlock.cpp24
-rw-r--r--JavaScriptCore/bytecode/CodeBlock.h7
-rw-r--r--JavaScriptCore/bytecode/Opcode.h2
-rw-r--r--JavaScriptCore/bytecompiler/BytecodeGenerator.cpp6
-rw-r--r--JavaScriptCore/bytecompiler/BytecodeGenerator.h8
-rw-r--r--JavaScriptCore/bytecompiler/NodesCodegen.cpp3
-rw-r--r--JavaScriptCore/create_jit_stubs11
-rw-r--r--JavaScriptCore/interpreter/CallFrame.cpp6
-rw-r--r--JavaScriptCore/interpreter/CallFrame.h5
-rw-r--r--JavaScriptCore/interpreter/Interpreter.cpp67
-rw-r--r--JavaScriptCore/jit/ExecutableAllocator.h5
-rw-r--r--JavaScriptCore/jit/JITInlineMethods.h2
-rw-r--r--JavaScriptCore/jit/JITOpcodes.cpp51
-rw-r--r--JavaScriptCore/jit/JITOpcodes32_64.cpp94
-rw-r--r--JavaScriptCore/jit/JITPropertyAccess32_64.cpp34
-rw-r--r--JavaScriptCore/jit/JITStubs.cpp21
-rw-r--r--JavaScriptCore/jsc/CMakeLists.txt3
-rw-r--r--JavaScriptCore/parser/ASTBuilder.h925
-rw-r--r--JavaScriptCore/parser/JSParser.cpp1504
-rw-r--r--JavaScriptCore/parser/JSParser.h125
-rw-r--r--JavaScriptCore/parser/Lexer.cpp37
-rw-r--r--JavaScriptCore/parser/Lexer.h5
-rw-r--r--JavaScriptCore/parser/NodeConstructors.h4
-rw-r--r--JavaScriptCore/parser/Parser.cpp9
-rw-r--r--JavaScriptCore/parser/SyntaxChecker.h158
-rw-r--r--JavaScriptCore/qt/api/qscriptengine_p.cpp2
-rw-r--r--JavaScriptCore/qt/api/qscriptvalue.cpp28
-rw-r--r--JavaScriptCore/qt/api/qscriptvalue.h4
-rw-r--r--JavaScriptCore/qt/api/qscriptvalue_p.h193
-rw-r--r--JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp40
-rw-r--r--JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h1
-rw-r--r--JavaScriptCore/runtime/ArrayPrototype.cpp8
-rw-r--r--JavaScriptCore/runtime/Executable.cpp18
-rw-r--r--JavaScriptCore/runtime/Executable.h12
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.cpp5
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.h7
-rw-r--r--JavaScriptCore/runtime/JSImmediate.h8
-rw-r--r--JavaScriptCore/runtime/JSString.cpp1
-rw-r--r--JavaScriptCore/runtime/JSValue.cpp6
-rw-r--r--JavaScriptCore/runtime/JSZombie.cpp2
-rw-r--r--JavaScriptCore/runtime/RegExpCache.cpp78
-rw-r--r--JavaScriptCore/runtime/RegExpCache.h57
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.cpp3
-rw-r--r--JavaScriptCore/runtime/RegExpKey.h112
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.cpp3
-rw-r--r--JavaScriptCore/runtime/StringPrototype.cpp5
-rw-r--r--JavaScriptCore/runtime/SymbolTable.h7
-rw-r--r--JavaScriptCore/wtf/CMakeLists.txt1
-rw-r--r--JavaScriptCore/wtf/FastMalloc.h2
-rw-r--r--JavaScriptCore/wtf/Platform.h19
-rw-r--r--JavaScriptCore/wtf/RetainPtr.h24
-rw-r--r--JavaScriptCore/wtf/StringExtras.h1
-rw-r--r--JavaScriptCore/wtf/ThreadSafeShared.h10
-rw-r--r--JavaScriptCore/wtf/ThreadSpecific.h48
-rw-r--r--JavaScriptCore/wtf/Vector.h2
-rw-r--r--JavaScriptCore/yarr/RegexCompiler.cpp2
-rw-r--r--JavaScriptCore/yarr/RegexJIT.cpp24
72 files changed, 4676 insertions, 256 deletions
diff --git a/JavaScriptCore/API/JSClassRef.h b/JavaScriptCore/API/JSClassRef.h
index ae60aad..5a3a17e 100644
--- a/JavaScriptCore/API/JSClassRef.h
+++ b/JavaScriptCore/API/JSClassRef.h
@@ -33,7 +33,6 @@
#include <runtime/UString.h>
#include <runtime/WeakGCPtr.h>
#include <wtf/HashMap.h>
-#include <wtf/RefCounted.h>
struct StaticValueEntry : FastAllocBase {
StaticValueEntry(JSObjectGetPropertyCallback _getProperty, JSObjectSetPropertyCallback _setProperty, JSPropertyAttributes _attributes)
diff --git a/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp
index 9beeb82..8182075 100644
--- a/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp
+++ b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp
@@ -32,7 +32,6 @@
#include "JSValue.h"
#include "JSWeakObjectMapRefInternal.h"
#include <wtf/HashMap.h>
-#include <wtf/RefCounted.h>
#include <wtf/text/StringHash.h>
using namespace WTF;
diff --git a/JavaScriptCore/CMakeLists.txt b/JavaScriptCore/CMakeLists.txt
index d4a85d0..c1946ff 100644
--- a/JavaScriptCore/CMakeLists.txt
+++ b/JavaScriptCore/CMakeLists.txt
@@ -54,16 +54,19 @@ SET(JavaScriptCore_SOURCES
jit/ExecutableAllocatorPosix.cpp
jit/ExecutableAllocatorSymbian.cpp
jit/ExecutableAllocatorWin.cpp
- jit/JITStubs.cpp
- jit/JITOpcodes.cpp
- jit/JITOpcodes32_64.cpp
- jit/JITPropertyAccess.cpp
- jit/JITPropertyAccess32_64.cpp
+ jit/JITArithmetic32_64.cpp
jit/JITArithmetic.cpp
- jit/JITCall.cpp
jit/JITCall32_64.cpp
+ jit/JITCall.cpp
jit/JIT.cpp
+ jit/JITOpcodes32_64.cpp
+ jit/JITOpcodes.cpp
+ jit/JITPropertyAccess32_64.cpp
+ jit/JITPropertyAccess.cpp
+ jit/JITStubs.cpp
+ jit/ThunkGenerators.cpp
+ parser/JSParser.cpp
parser/Lexer.cpp
parser/Nodes.cpp
parser/Parser.cpp
@@ -149,6 +152,7 @@ SET(JavaScriptCore_SOURCES
runtime/PropertySlot.cpp
runtime/PrototypeFunction.cpp
runtime/RegExp.cpp
+ runtime/RegExpCache.cpp
runtime/RegExpConstructor.cpp
runtime/RegExpObject.cpp
runtime/RegExpPrototype.cpp
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 8d5b59e..ff017ca 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,957 @@
+2010-06-25 Jedrzej Nowacki <jedrzej.nowacki@nokia.com>
+
+ Reviewed by Simon Hausmann.
+
+ New QtScript API; setPrototype() and prototype().
+
+ This patch implements QScriptValue's prototype accessors.
+
+ [Qt] QScriptValue should have accessors to a prototype.
+ https://bugs.webkit.org/show_bug.cgi?id=39356
+
+ * qt/api/qscriptvalue.cpp:
+ (QScriptValue::prototype):
+ (QScriptValue::setPrototype):
+ * qt/api/qscriptvalue.h:
+ * qt/api/qscriptvalue_p.h:
+ (QScriptValuePrivate::prototype):
+ (QScriptValuePrivate::setPrototype):
+ * qt/tests/qscriptvalue/tst_qscriptvalue.cpp:
+ (tst_QScriptValue::getSetPrototype):
+ * qt/tests/qscriptvalue/tst_qscriptvalue.h:
+
+2010-06-25 Lucas De Marchi <lucas.demarchi@profusion.mobi>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [CMake] Add option to enable JIT.
+ JIT is disabled by default, but now it's possible to enable it through
+ an option to CMake: -DENABLE_JIT will enable it.
+ https://bugs.webkit.org/show_bug.cgi?id=40936
+
+ * CMakeLists.txt: Add missing files and re-sort.
+
+2010-06-25 Lucas De Marchi <lucas.demarchi@profusion.mobi>
+
+ Reviewed by Gustavo Noronha Silva.
+
+ [CMake] Remove unused variable in EFL build system. It was previously
+ being used to set the flags of each port but it was superseded by
+ other flags.
+ https://bugs.webkit.org/show_bug.cgi?id=40931
+
+ * jsc/CMakeLists.txt:
+
+2010-06-25 Nathan Lawrence <nlawrence@apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ Aligning AssemblerBuffer to 128 bytes gives a 0.4% speedup on
+ sunspider.
+
+ * assembler/AssemblerBuffer.h:
+ (JSC::AssemblerBuffer::AssemblerBuffer):
+
+2010-06-25 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r61842.
+ http://trac.webkit.org/changeset/61842
+ https://bugs.webkit.org/show_bug.cgi?id=41208
+
+ It broke Windows build (Requested by Ossy_ on #webkit).
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * wtf/OwnPtrCommon.h:
+ * wtf/brew/OwnPtrBrew.h: Removed.
+ * wtf/win/OwnPtrWin.h: Removed.
+
+2010-06-25 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r61833.
+ http://trac.webkit.org/changeset/61833
+ https://bugs.webkit.org/show_bug.cgi?id=41205
+
+ It broke Leopard and GTK (Requested by Ossy_ on #webkit).
+
+ * runtime/RegExp.cpp:
+ (JSC::RegExp::RegExp):
+ (JSC::RegExp::create):
+ * runtime/RegExp.h:
+ * runtime/RegExpCache.cpp:
+ (JSC::RegExpCache::lookupOrCreate):
+ (JSC::RegExpCache::create):
+ * runtime/RegExpCache.h:
+
+2010-06-25 Kwang Yul Seo <skyul@company100.net>
+
+ Reviewed by Adam Barth.
+
+ Change OwnPtrCommon to include platform-specific headers
+ https://bugs.webkit.org/show_bug.cgi?id=40279
+
+ Adding new type to OwnPtrCommon needlessly causes all ports to do full rebuilds.
+ Change OwnPtrCommon to include platform-specific headers to avoid all ports rebuilds.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * wtf/OwnPtrCommon.h:
+ * wtf/brew/OwnPtrBrew.h: Added.
+ * wtf/win/OwnPtrWin.h: Added.
+
+2010-06-25 Patrick Gansterer <paroga@paroga.com>
+
+ Reviewed by Darin Adler.
+
+ Add the possibility for a head and footer section to create_jit_stubs.
+ https://bugs.webkit.org/show_bug.cgi?id=36050
+
+ * create_jit_stubs:
+
+2010-06-24 Renata Hodovan <reni@inf.u-szeged.hu>
+
+ Reviewed by Geoffrey Garen.
+
+ Merge RegExp constructor and RegExp::create methods into one.
+ Both of function are called with tree parameters and check whether
+ flags (the third param) is given or not.
+ Simplify hash lookups in RegExpCache::create with giving them an extra
+ iterator parameter.
+ https://bugs.webkit.org/show_bug.cgi?id=41055
+
+ * runtime/RegExp.cpp:
+ (JSC::RegExp::RegExp):
+ * runtime/RegExp.h:
+ * runtime/RegExpCache.cpp:
+ (JSC::RegExpCache::lookupOrCreate):
+ (JSC::RegExpCache::create):
+ * runtime/RegExpCache.h:
+
+2010-06-24 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Incorrect use of '+ 4' and 0 instead of tag and payload offsets in JSValue32_64
+ https://bugs.webkit.org/show_bug.cgi?id=41193
+
+ I noticed a use of '+ 4' in some of the 32_64 code paths and realised there
+ were a few places where endianness was being hardcoded. This patch fixes
+ the errors i could find through code inspection.
+
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_resolve_global):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emit_op_put_by_val):
+ (JSC::JIT::compileGetDirectOffset):
+ (JSC::JIT::privateCompilePutByIdTransition):
+ (JSC::JIT::patchGetByIdSelf):
+ (JSC::JIT::patchPutByIdReplace):
+
+2010-06-24 Oliver Hunt <oliver@apple.com>
+
+ Build fix
+
+ Temporarily get the tiger bot working again by disabling the
+ new JS parser. GCC on tiger is miscompiling the parser and
+ I don't have access to a tiger machine right now.
+
+ * wtf/Platform.h:
+
+ 2010-06-21 Nathan Lawrence <nlawrence@apple.com>
+
+ Reviewed by Geoff Garen.
+
+ https://bugs.webkit.org/show_bug.cgi?id=40128
+ Fixed broken debug functionality.
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::dumpRegisters):
+ Fixed to work with updated call frame.
+ * runtime/JSImmediate.h:
+ (JSC::JSValue::isCell):
+ Added assert for aligned cell.
+ * runtime/JSValue.cpp:
+ (JSC::JSValue::description):
+ Fixed to work with current JSValue implementation.
+ * runtime/JSZombie.cpp:
+ (JSC::JSZombie::leakedZombieStructure):
+ JSombies compile again.
+
+2010-06-24 Leandro Pereira <leandro@profusion.mobi>
+
+ Unreviewed build fix.
+
+ * CMakeLists.txt: Add JSParser.cpp.
+
+2010-06-24 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Single character string replacement may replace too many characters
+ https://bugs.webkit.org/show_bug.cgi?id=41138
+ <rdar://problem/8097496>
+
+ Simple fix to stop the rope path of single character replacement
+ once the first replacement occurs.
+
+ * runtime/JSString.cpp:
+ (JSC::JSString::replaceCharacter):
+
+2010-06-24 Gabor Loki <loki@webkit.org>
+
+ Reviewed by Gavin Barraclough.
+
+ Fix the length of instruction stream controlled by constant pool
+ https://bugs.webkit.org/show_bug.cgi?id=40293
+
+ The initial/maximum length of instruction stream (m_maxDistance) should
+ be set when the first constant arrives to the constant pool. Otherwise
+ the constant pool could be placed into an uninterrupted sequence.
+
+ * assembler/AssemblerBufferWithConstantPool.h:
+ (JSC::):
+
+2010-06-24 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Gavin Barraclough.
+
+ We assume bytecodeOffset will always return a value > 1,
+ so we adjust the failure case to return 1 instead of 0.
+
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::bytecodeOffset):
+
+2010-06-23 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Gavin Barraclough.
+
+ Custom-written JavaScript parser
+ https://bugs.webkit.org/show_bug.cgi?id=34019
+
+ Implement a recursive descent parser similar to that used by V8 and
+ SpiderMonkey. Greater than 2x improvement in SunSpider parsing tests.
+
+ The parser consists of a JSParser class that uses a TreeBuilder to actually
+ build the AST. There are currently two builders -- the ASTBuilder and
+ SyntaxChecker which separate the job of building an AST for code generation
+ and simply checking syntactic correctness.
+
+ There's still some less than ideal code remaining in the parser to allow
+ us to retain the existing lexing code with minimal changes. We'll tidy
+ this up at a later date.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.gypi:
+ * JavaScriptCore.pro:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * parser/ASTBuilder.h: Added.
+ (JSC::ASTBuilder::BinaryOpInfo::BinaryOpInfo):
+ (JSC::ASTBuilder::AssignmentInfo::AssignmentInfo):
+ (JSC::ASTBuilder::ASTBuilder):
+ (JSC::ASTBuilder::createSourceElements):
+ (JSC::ASTBuilder::varDeclarations):
+ (JSC::ASTBuilder::funcDeclarations):
+ (JSC::ASTBuilder::features):
+ (JSC::ASTBuilder::numConstants):
+ (JSC::ASTBuilder::appendToComma):
+ (JSC::ASTBuilder::createCommaExpr):
+ (JSC::ASTBuilder::createLogicalNot):
+ (JSC::ASTBuilder::createUnaryPlus):
+ (JSC::ASTBuilder::createVoid):
+ (JSC::ASTBuilder::thisExpr):
+ (JSC::ASTBuilder::createResolve):
+ (JSC::ASTBuilder::createObjectLiteral):
+ (JSC::ASTBuilder::createArray):
+ (JSC::ASTBuilder::createNumberExpr):
+ (JSC::ASTBuilder::createString):
+ (JSC::ASTBuilder::createBoolean):
+ (JSC::ASTBuilder::createNull):
+ (JSC::ASTBuilder::createBracketAccess):
+ (JSC::ASTBuilder::createDotAccess):
+ (JSC::ASTBuilder::createRegex):
+ (JSC::ASTBuilder::createNewExpr):
+ (JSC::ASTBuilder::createConditionalExpr):
+ (JSC::ASTBuilder::createAssignResolve):
+ (JSC::ASTBuilder::createFunctionExpr):
+ (JSC::ASTBuilder::createFunctionBody):
+ (JSC::ASTBuilder::createGetterOrSetterProperty):
+ (JSC::ASTBuilder::createArguments):
+ (JSC::ASTBuilder::createArgumentsList):
+ (JSC::ASTBuilder::createProperty):
+ (JSC::ASTBuilder::createPropertyList):
+ (JSC::ASTBuilder::createElementList):
+ (JSC::ASTBuilder::createFormalParameterList):
+ (JSC::ASTBuilder::createClause):
+ (JSC::ASTBuilder::createClauseList):
+ (JSC::ASTBuilder::setUsesArguments):
+ (JSC::ASTBuilder::createFuncDeclStatement):
+ (JSC::ASTBuilder::createBlockStatement):
+ (JSC::ASTBuilder::createExprStatement):
+ (JSC::ASTBuilder::createIfStatement):
+ (JSC::ASTBuilder::createForLoop):
+ (JSC::ASTBuilder::createForInLoop):
+ (JSC::ASTBuilder::createEmptyStatement):
+ (JSC::ASTBuilder::createVarStatement):
+ (JSC::ASTBuilder::createReturnStatement):
+ (JSC::ASTBuilder::createBreakStatement):
+ (JSC::ASTBuilder::createContinueStatement):
+ (JSC::ASTBuilder::createTryStatement):
+ (JSC::ASTBuilder::createSwitchStatement):
+ (JSC::ASTBuilder::createWhileStatement):
+ (JSC::ASTBuilder::createDoWhileStatement):
+ (JSC::ASTBuilder::createLabelStatement):
+ (JSC::ASTBuilder::createWithStatement):
+ (JSC::ASTBuilder::createThrowStatement):
+ (JSC::ASTBuilder::createDebugger):
+ (JSC::ASTBuilder::createConstStatement):
+ (JSC::ASTBuilder::appendConstDecl):
+ (JSC::ASTBuilder::appendStatement):
+ (JSC::ASTBuilder::addVar):
+ (JSC::ASTBuilder::combineCommaNodes):
+ (JSC::ASTBuilder::evalCount):
+ (JSC::ASTBuilder::appendBinaryExpressionInfo):
+ (JSC::ASTBuilder::operatorStackPop):
+ (JSC::ASTBuilder::operatorStackHasHigherPrecedence):
+ (JSC::ASTBuilder::getFromOperandStack):
+ (JSC::ASTBuilder::shrinkOperandStackBy):
+ (JSC::ASTBuilder::appendBinaryOperation):
+ (JSC::ASTBuilder::operatorStackAppend):
+ (JSC::ASTBuilder::popOperandStack):
+ (JSC::ASTBuilder::appendUnaryToken):
+ (JSC::ASTBuilder::unaryTokenStackLastType):
+ (JSC::ASTBuilder::unaryTokenStackLastStart):
+ (JSC::ASTBuilder::unaryTokenStackRemoveLast):
+ (JSC::ASTBuilder::assignmentStackAppend):
+ (JSC::ASTBuilder::createAssignment):
+ (JSC::ASTBuilder::Scope::Scope):
+ (JSC::ASTBuilder::setExceptionLocation):
+ (JSC::ASTBuilder::incConstants):
+ (JSC::ASTBuilder::usesThis):
+ (JSC::ASTBuilder::usesCatch):
+ (JSC::ASTBuilder::usesClosures):
+ (JSC::ASTBuilder::usesArguments):
+ (JSC::ASTBuilder::usesAssignment):
+ (JSC::ASTBuilder::usesWith):
+ (JSC::ASTBuilder::usesEval):
+ (JSC::ASTBuilder::createNumber):
+ (JSC::ASTBuilder::makeTypeOfNode):
+ (JSC::ASTBuilder::makeDeleteNode):
+ (JSC::ASTBuilder::makeNegateNode):
+ (JSC::ASTBuilder::makeBitwiseNotNode):
+ (JSC::ASTBuilder::makeMultNode):
+ (JSC::ASTBuilder::makeDivNode):
+ (JSC::ASTBuilder::makeAddNode):
+ (JSC::ASTBuilder::makeSubNode):
+ (JSC::ASTBuilder::makeLeftShiftNode):
+ (JSC::ASTBuilder::makeRightShiftNode):
+ (JSC::ASTBuilder::makeFunctionCallNode):
+ (JSC::ASTBuilder::makeBinaryNode):
+ (JSC::ASTBuilder::makeAssignNode):
+ (JSC::ASTBuilder::makePrefixNode):
+ (JSC::ASTBuilder::makePostfixNode):
+ * parser/JSParser.cpp: Added.
+ (JSC::JSParser::AllowInOverride::AllowInOverride):
+ (JSC::JSParser::AllowInOverride::~AllowInOverride):
+ (JSC::JSParser::token):
+ (JSC::JSParser::next):
+ (JSC::JSParser::consume):
+ (JSC::JSParser::match):
+ (JSC::JSParser::tokenStart):
+ (JSC::JSParser::tokenLine):
+ (JSC::JSParser::tokenEnd):
+ (JSC::JSParser::):
+ (JSC::JSParser::autoSemiColon):
+ (JSC::JSParser::canRecurse):
+ (JSC::JSParser::lastTokenEnd):
+ (JSC::jsParse):
+ (JSC::JSParser::JSParser):
+ (JSC::JSParser::parseProgram):
+ (JSC::JSParser::allowAutomaticSemicolon):
+ (JSC::JSParser::parseSourceElements):
+ (JSC::JSParser::parseVarDeclaration):
+ (JSC::JSParser::parseConstDeclaration):
+ (JSC::JSParser::parseDoWhileStatement):
+ (JSC::JSParser::parseWhileStatement):
+ (JSC::JSParser::parseVarDeclarationList):
+ (JSC::JSParser::parseConstDeclarationList):
+ (JSC::JSParser::parseForStatement):
+ (JSC::JSParser::parseBreakStatement):
+ (JSC::JSParser::parseContinueStatement):
+ (JSC::JSParser::parseReturnStatement):
+ (JSC::JSParser::parseThrowStatement):
+ (JSC::JSParser::parseWithStatement):
+ (JSC::JSParser::parseSwitchStatement):
+ (JSC::JSParser::parseSwitchClauses):
+ (JSC::JSParser::parseSwitchDefaultClause):
+ (JSC::JSParser::parseTryStatement):
+ (JSC::JSParser::parseDebuggerStatement):
+ (JSC::JSParser::parseBlockStatement):
+ (JSC::JSParser::parseStatement):
+ (JSC::JSParser::parseFormalParameters):
+ (JSC::JSParser::parseFunctionBody):
+ (JSC::JSParser::parseFunctionInfo):
+ (JSC::JSParser::parseFunctionDeclaration):
+ (JSC::JSParser::parseExpressionOrLabelStatement):
+ (JSC::JSParser::parseExpressionStatement):
+ (JSC::JSParser::parseIfStatement):
+ (JSC::JSParser::parseExpression):
+ (JSC::JSParser::parseAssignmentExpression):
+ (JSC::JSParser::parseConditionalExpression):
+ (JSC::isUnaryOp):
+ (JSC::JSParser::isBinaryOperator):
+ (JSC::JSParser::parseBinaryExpression):
+ (JSC::JSParser::parseProperty):
+ (JSC::JSParser::parseObjectLiteral):
+ (JSC::JSParser::parseArrayLiteral):
+ (JSC::JSParser::parsePrimaryExpression):
+ (JSC::JSParser::parseArguments):
+ (JSC::JSParser::parseMemberExpression):
+ (JSC::JSParser::parseUnaryExpression):
+ * parser/JSParser.h: Added.
+ (JSC::):
+ (JSC::JSTokenInfo::JSTokenInfo):
+ * parser/Lexer.cpp:
+ (JSC::Lexer::lex):
+ * parser/Lexer.h:
+ (JSC::Lexer::setLastLineNumber):
+ (JSC::Lexer::lastLineNumber):
+ * parser/NodeConstructors.h:
+ (JSC::Node::Node):
+ * parser/Parser.cpp:
+ (JSC::Parser::parse):
+ * parser/SyntaxChecker.h: Added.
+ (JSC::SyntaxChecker::SyntaxChecker):
+ (JSC::SyntaxChecker::createSourceElements):
+ (JSC::SyntaxChecker::makeFunctionCallNode):
+ (JSC::SyntaxChecker::appendToComma):
+ (JSC::SyntaxChecker::createCommaExpr):
+ (JSC::SyntaxChecker::makeAssignNode):
+ (JSC::SyntaxChecker::makePrefixNode):
+ (JSC::SyntaxChecker::makePostfixNode):
+ (JSC::SyntaxChecker::makeTypeOfNode):
+ (JSC::SyntaxChecker::makeDeleteNode):
+ (JSC::SyntaxChecker::makeNegateNode):
+ (JSC::SyntaxChecker::makeBitwiseNotNode):
+ (JSC::SyntaxChecker::createLogicalNot):
+ (JSC::SyntaxChecker::createUnaryPlus):
+ (JSC::SyntaxChecker::createVoid):
+ (JSC::SyntaxChecker::thisExpr):
+ (JSC::SyntaxChecker::createResolve):
+ (JSC::SyntaxChecker::createObjectLiteral):
+ (JSC::SyntaxChecker::createArray):
+ (JSC::SyntaxChecker::createNumberExpr):
+ (JSC::SyntaxChecker::createString):
+ (JSC::SyntaxChecker::createBoolean):
+ (JSC::SyntaxChecker::createNull):
+ (JSC::SyntaxChecker::createBracketAccess):
+ (JSC::SyntaxChecker::createDotAccess):
+ (JSC::SyntaxChecker::createRegex):
+ (JSC::SyntaxChecker::createNewExpr):
+ (JSC::SyntaxChecker::createConditionalExpr):
+ (JSC::SyntaxChecker::createAssignResolve):
+ (JSC::SyntaxChecker::createFunctionExpr):
+ (JSC::SyntaxChecker::createFunctionBody):
+ (JSC::SyntaxChecker::createArguments):
+ (JSC::SyntaxChecker::createArgumentsList):
+ (JSC::SyntaxChecker::createProperty):
+ (JSC::SyntaxChecker::createPropertyList):
+ (JSC::SyntaxChecker::createElementList):
+ (JSC::SyntaxChecker::createFormalParameterList):
+ (JSC::SyntaxChecker::createClause):
+ (JSC::SyntaxChecker::createClauseList):
+ (JSC::SyntaxChecker::setUsesArguments):
+ (JSC::SyntaxChecker::createFuncDeclStatement):
+ (JSC::SyntaxChecker::createBlockStatement):
+ (JSC::SyntaxChecker::createExprStatement):
+ (JSC::SyntaxChecker::createIfStatement):
+ (JSC::SyntaxChecker::createForLoop):
+ (JSC::SyntaxChecker::createForInLoop):
+ (JSC::SyntaxChecker::createEmptyStatement):
+ (JSC::SyntaxChecker::createVarStatement):
+ (JSC::SyntaxChecker::createReturnStatement):
+ (JSC::SyntaxChecker::createBreakStatement):
+ (JSC::SyntaxChecker::createContinueStatement):
+ (JSC::SyntaxChecker::createTryStatement):
+ (JSC::SyntaxChecker::createSwitchStatement):
+ (JSC::SyntaxChecker::createWhileStatement):
+ (JSC::SyntaxChecker::createWithStatement):
+ (JSC::SyntaxChecker::createDoWhileStatement):
+ (JSC::SyntaxChecker::createLabelStatement):
+ (JSC::SyntaxChecker::createThrowStatement):
+ (JSC::SyntaxChecker::createDebugger):
+ (JSC::SyntaxChecker::createConstStatement):
+ (JSC::SyntaxChecker::appendConstDecl):
+ (JSC::SyntaxChecker::createGetterOrSetterProperty):
+ (JSC::SyntaxChecker::appendStatement):
+ (JSC::SyntaxChecker::addVar):
+ (JSC::SyntaxChecker::combineCommaNodes):
+ (JSC::SyntaxChecker::evalCount):
+ (JSC::SyntaxChecker::appendBinaryExpressionInfo):
+ (JSC::SyntaxChecker::operatorStackPop):
+ * runtime/JSGlobalData.h:
+ * wtf/Platform.h:
+ * wtf/ThreadSpecific.h:
+ (WTF::T):
+
+2010-06-23 Jedrzej Nowacki <jedrzej.nowacki@nokia.com>
+
+ Reviewed by Simon Hausmann.
+
+ Optimization of the QScriptValuePrivate.
+
+ Patch change only internals of the QScriptValuePrivate.
+ Most of the QScriptValuePrivate's attributes were moved
+ into an union.
+
+ [Qt] Optimization of the QScriptVAluePrivate.
+ https://bugs.webkit.org/show_bug.cgi?id=40415
+
+ * qt/api/qscriptengine_p.cpp:
+ (QScriptEnginePrivate::globalObject):
+ * qt/api/qscriptvalue_p.h:
+ (QScriptValuePrivate::):
+ (QScriptValuePrivate::~QScriptValuePrivate):
+ (QScriptValuePrivate::QScriptValuePrivate):
+ (QScriptValuePrivate::toString):
+ (QScriptValuePrivate::toNumber):
+ (QScriptValuePrivate::toBool):
+ (QScriptValuePrivate::toObject):
+ (QScriptValuePrivate::equals):
+ (QScriptValuePrivate::strictlyEquals):
+ (QScriptValuePrivate::assignEngine):
+ (QScriptValuePrivate::operator JSValueRef):
+ (QScriptValuePrivate::operator JSObjectRef):
+ (QScriptValuePrivate::refinedJSValue):
+
+2010-06-23 Kwang Yul Seo <skyul@company100.net>
+
+ Reviewed by Oliver Hunt.
+
+ [GTK] Implement ThreadSpecific with glib
+ https://bugs.webkit.org/show_bug.cgi?id=39829
+
+ Implement ThreadSpecific with glib's GStaticPrivate.
+ This patch makes it possible to build GTK port without pthread.
+
+ * wtf/ThreadSpecific.h:
+ (WTF::::ThreadSpecific):
+ (WTF::::~ThreadSpecific):
+ (WTF::::get):
+ (WTF::::set):
+ (WTF::::destroy):
+
+2010-06-23 Leandro Pereira <leandro@profusion.mobi>
+
+ Unreviewed build fix.
+
+ * CMakeLists.txt: Add runtime/RegExpCache.cpp.
+
+2010-06-22 Renata Hodovan <hodovan@inf.u-szeged.hu>
+
+ Reviewed by Geoffrey Garen.
+
+ Adding regular expression caching to JavaScriptCore
+ https://bugs.webkit.org/show_bug.cgi?id=38142
+
+ The cache is based on Round Robin eviction policy, and
+ can cache at most 256 character long regular expressions,
+ and at most 256 of them. These values can be changed at compile time.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.gypi:
+ * JavaScriptCore.pro:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::RegExpNode::emitBytecode):
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::JSGlobalData):
+ (JSC::JSGlobalData::~JSGlobalData):
+ * runtime/JSGlobalData.h:
+ (JSC::JSGlobalData::regExpCache):
+ * runtime/RegExpCache.cpp: Added.
+ (JSC::RegExpCache::lookupOrCreate):
+ (JSC::RegExpCache::create):
+ (JSC::RegExpCache::RegExpCache):
+ * runtime/RegExpCache.h: Added.
+ * runtime/RegExpConstructor.cpp:
+ (JSC::constructRegExp):
+ * runtime/RegExpKey.h: Added.
+ (JSC::RegExpKey::RegExpKey):
+ (JSC::RegExpKey::getFlagsValue):
+ (WTF::operator==):
+ (WTF::):
+ * runtime/RegExpPrototype.cpp:
+ (JSC::regExpProtoFuncCompile):
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncMatch):
+ (JSC::stringProtoFuncSearch):
+
+2010-06-22 Gabor Loki <loki@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Add native call support for ARM and Thumb-2 JIT.
+ https://bugs.webkit.org/show_bug.cgi?id=40231
+
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::privateCompileCTINativeCall):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::privateCompileCTINativeCall):
+ * wtf/Platform.h:
+
+2010-06-21 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ Make JSC more resilient in the face of parse failures
+ https://bugs.webkit.org/show_bug.cgi?id=40951
+
+ A number of recent bugs have occurred due to issues like miscounting
+ BOMs, etc which lead to interesting crashes later on. Adding this
+ logic hardens JSC in the face of these errors, and has no impact on
+ performance (32bit jit actually gets 0.7% faster but I put that down
+ to cache effects).
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::reparseForExceptionInfoIfNecessary):
+ (JSC::CodeBlock::lineNumberForBytecodeOffset):
+ (JSC::CodeBlock::expressionRangeForBytecodeOffset):
+ (JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::bytecodeOffset):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::execute):
+ (JSC::Interpreter::executeCall):
+ (JSC::Interpreter::executeConstruct):
+ (JSC::Interpreter::prepareForRepeatCall):
+ (JSC::Interpreter::privateExecute):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::privateCompileCTIMachineTrampolines):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::privateCompileCTIMachineTrampolines):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * runtime/ArrayPrototype.cpp:
+ (JSC::isNumericCompareFunction):
+ * runtime/Executable.cpp:
+ (JSC::FunctionExecutable::compileForCall):
+ (JSC::FunctionExecutable::compileForConstruct):
+ (JSC::FunctionExecutable::generateJITCodeForCall):
+ (JSC::FunctionExecutable::generateJITCodeForConstruct):
+ (JSC::FunctionExecutable::reparseExceptionInfo):
+ (JSC::EvalExecutable::reparseExceptionInfo):
+ * runtime/Executable.h:
+ (JSC::FunctionExecutable::bytecodeForCall):
+ (JSC::FunctionExecutable::bytecodeForConstruct):
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::numericCompareFunction):
+
+2010-06-21 John Sullivan <sullivan@apple.com>
+
+ Reviewed by Adam Roben.
+
+ RetainPtr can't be used in HashMaps or HashSets
+ <https://bugs.webkit.org/show_bug.cgi?id=40938>
+
+ Added hashing knowledge similar to that in COMPtr.h.
+
+ * wtf/RetainPtr.h:
+ (WTF::RetainPtr::RetainPtr):
+ New function, copied from COMPtr.h but for the type change.
+ (WTF::RetainPtr::isHashTableDeletedValue):
+ Ditto.
+ (WTF::RetainPtr::hashTableDeletedValue):
+ Ditto.
+ Added template code for HashTraits and PtrHash copied from COMPtr.h but for the type change.
+ The only difference is that constructDeletedValue() matches the RefPtr implementation (in HashTraits.h)
+ rather than the COMPtr implementation.
+
+2010-06-19 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ Need to ensure that we grow the RegisterFile when creating a callframe for host code
+ https://bugs.webkit.org/show_bug.cgi?id=40858
+ <rdar://problem/8108986>
+
+ In the past the use of the callframe in hostcode was much more
+ limited. Now that we expect the callframe to always be valid
+ we need to grow the RegisterFile so that this is actually the
+ case. In this particular case the problem was failing to grow
+ the registerfile could lead to a callframe that extended beyond
+ RegisterFiler::end(), so vm re-entry would clobber the callframe
+ other scenarios could also lead to badness.
+
+ I was unable to construct a simple testcase to trigger badness,
+ and any such testcase would be so dependent on exact vm stack
+ layout that it would be unlikely to work as a testcase following
+ any callframe or register allocation changes anyway.
+
+ Thankfully the new assertion I added should help to catch these
+ failures in future, and triggers on a couple of tests currently.
+
+ * interpreter/CallFrame.cpp:
+ (JSC::CallFrame::registerFile):
+ * interpreter/CallFrame.h:
+ (JSC::ExecState::init):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+
+2010-06-21 Satish Sampath <satish@chromium.org>
+
+ Reviewed by Steve Block.
+
+ Speech Input Patch 0: Added compilation argument to conditionally compile pending patches.
+ https://bugs.webkit.org/show_bug.cgi?id=40878
+
+ * Configurations/FeatureDefines.xcconfig:
+
+2010-06-21 Kwang Yul Seo <skyul@company100.net>
+
+ Reviewed by Kent Tamura.
+
+ [BREWMP] Use global new/delete operator overloading with USE_SYSTEM_MALLOC=1
+ https://bugs.webkit.org/show_bug.cgi?id=40653
+
+ Currently, other ports do not use global new/delete operator overloading
+ when USE_SYSTEM_MALLOC=1. Brew MP uses system malloc, but it needs to enable
+ "global fastMalloc new" because the default new/delete causes crash on device.
+ We need to replace them with Brew MP's MALLOC/FREE.
+
+ * wtf/FastMalloc.h:
+
+2010-06-18 Jocelyn Turcotte <jocelyn.turcotte@nokia.com>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] Work around a build problem with libjscore on Symbian.
+ https://bugs.webkit.org/show_bug.cgi?id=40840
+
+ Sbsv2 sometimes have problems with debug/release configuration
+ determination causing QtWebKit in release to try linking with the debug
+ JavaScriptCore static library. This patch limit the jscore/jscored
+ r58306 fix necessary for mac builds only to the mac platform to prevent the
+ different name problem.
+
+ The real fix would be to fix qmake or the toolchain, this patch might
+ help meanwhile.
+
+ * JavaScriptCore.pri:
+
+2010-06-21 Patrick Gansterer <paroga@paroga.com>
+
+ Reviewed by Kent Tamura.
+
+ Buildfix after r61338.
+ https://bugs.webkit.org/show_bug.cgi?id=40888
+
+ roundUpAllocationSize is needed in RegisterFile.h.
+
+ * jit/ExecutableAllocator.h:
+
+2010-06-19 Kwang Yul Seo <skyul@company100.net>
+
+ Reviewed by Darin Adler.
+
+ Include <string.h> in StringExtras.h
+ https://bugs.webkit.org/show_bug.cgi?id=40808
+
+ Without string.h, RVCT 2.2 can't compile StringExtras.h.
+ It can't find strlen and strncmp.
+
+ * wtf/StringExtras.h:
+
+2010-06-19 Thiago Macieira <thiago.macieira@nokia.com>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ Don't use __attribute__((may_alias)) with the Intel compiler,
+ as it doesn't understand it.
+
+ * wtf/Vector.h:
+
+2010-06-19 Thiago Macieira <thiago.macieira@nokia.com>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ Fix compilation with the Intel C++ compiler (11.1.072).
+
+ Like RVCT, label pointers must be void*, not const void*.
+
+ * bytecode/Opcode.h:
+
+2010-06-19 Thiago Macieira <thiago.macieira@nokia.com>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ Add the WTF_COMPILER_INTEL for when the Intel compiler is used
+ for building. Usually, the Intel compiler masquerades as
+ another compiler in the system and gets away with it, but some
+ times specific fixes are required (such as when using language
+ extensions).
+
+ * wtf/Platform.h:
+
+2010-06-18 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ Incorrect handling of multiple BOMs scattered through a file.
+ https://bugs.webkit.org/show_bug.cgi?id=40865
+
+ When determining the offset of open and close braces in a source
+ with BOMs we were finishing our count early as we failed to account
+ for BOMs prior to the open/close brace positions effecting those
+ positions.
+
+ * parser/Lexer.cpp:
+ (JSC::Lexer::sourceCode):
+
+2010-06-17 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Don't throw away exception information for functions that use exceptions
+ https://bugs.webkit.org/show_bug.cgi?id=40786
+
+ Simple patch to stop JSC from throwing away the exception information
+ of a function that uses "exceptiony" features like try and throw. This
+ is a speed up for catching expressions but it's difficult to quantify as
+ the old cost of reparsing is amortised over all exceptions caught in the
+ effected function.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::reparseForExceptionInfoIfNecessary):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::generate):
+ (JSC::BytecodeGenerator::emitCatch):
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::emitThrow):
+
+2010-06-18 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Add PlatformStrategies and PluginStrategy classes.
+ https://bugs.webkit.org/show_bug.cgi?id=40850
+
+ * wtf/Platform.h:
+
+2010-06-18 Leandro Pereira <leandro@profusion.mobi>
+
+ [EFL] Unreviewed build fix.
+
+ * wtf/CMakeLists.txt: Add MD5.cpp.
+
+2010-06-17 Shu Chang <chang.shu@nokia.com>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] Fix the link error on symbian with ENABLE_JIT=0.
+ 1. Add "#if ENABLE(JIT)" in the header file;
+ 2. Put feature enable/disable logic to a common.pri so
+ that both JavaScriptCore.pri and WebCore.pri can share.
+
+ https://bugs.webkit.org/show_bug.cgi?id=40780
+
+ * JavaScriptCore.pri:
+ * jit/ExecutableAllocator.h:
+
+2010-06-17 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Use adoptRef and create functions in more code paths
+ https://bugs.webkit.org/show_bug.cgi?id=40760
+
+ * API/JSClassRef.h: Removed unneeded include of RefCounted.h.
+ * API/JSWeakObjectMapRefPrivate.cpp: Ditto.
+
+ * bytecode/CodeBlock.h:
+ (JSC::FunctionCodeBlock::FunctionCodeBlock): Use the
+ SharedSymbolTable::create function instead of calling new directly.
+
+ * runtime/SymbolTable.h: Added a create function to the SharedSymbolTable
+ class and made the constructor private.
+
+2010-06-17 Mark Brand <mabrand@mabrand.nl>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] use "win32-g++*" scope to match all MinGW makespecs
+
+ The scope "win32-g++" comes from the name of the makespec. However, it
+ is frequently used to check for MinGW. This works fine as long as
+ win32-g++ is the only makespec for MinGW. Now we need the wildcard
+ to cover "win32-g++-cross" as well.
+
+ * JavaScriptCore.pro:
+
+2010-06-16 Darin Adler <darin@apple.com>
+
+ Reviewed by David Levin.
+
+ Deploy adoptRef in more places, including all HTML and MathML elements
+ https://bugs.webkit.org/show_bug.cgi?id=39941
+
+ * wtf/ThreadSafeShared.h: Made the constructor protected and removed the
+ unneeded support for initial reference counts other than 1.
+
+2010-06-16 Peter Varga <pvarga@inf.u-szeged.hu>
+
+ Reviewed by Geoffrey Garen.
+
+ Store matchBegin directly in the array of output instead of the stack.
+ https://bugs.webkit.org/show_bug.cgi?id=38988
+
+ * yarr/RegexJIT.cpp:
+ (JSC::Yarr::RegexGenerator::generateDisjunction):
+ (JSC::Yarr::RegexGenerator::generate):
+
+2010-06-15 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Make JavaScriptCore build with clang++.
+
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::emitPutVirtualRegister):
+ Explicitly cast to an int.
+
+ * yarr/RegexCompiler.cpp:
+ (JSC::Yarr::compileRegex):
+ Return 0 instead of false.
+
+2010-06-15 Adam Roben <aroben@apple.com>
+
+ Make WebCore's and JavaScriptCore's DerivedSources available for debugging in production builds
+
+ Fixes <http://webkit.org/b/40626> <rdar://problem/8094205>.
+
+ Reviewed by Sam Weinig.
+
+ * JavaScriptCore.vcproj/JavaScriptCore.make: Copy the contents of
+ JavaScriptCore's DerivedSources directory to
+ AppleInternal/Sources/JavaScriptCore.
+
+2010-06-15 Gabor Loki <loki@webkit.org>
+
+ Rubber-stamped by Eric Seidel.
+
+ Fix invalid access to non-static data member warning in JITPropertyAccess32_64 on ARM
+ https://bugs.webkit.org/show_bug.cgi?id=40423
+
+ Using OBJECT_OFFSETOF macro instead of objectof to bypass access to
+ non-static data member warning.
+
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::privateCompilePutByIdTransition):
+
2010-06-11 Eric Seidel <eric@webkit.org>
Reviewed by Adam Barth.
diff --git a/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/JavaScriptCore/Configurations/FeatureDefines.xcconfig
index 5b52793..08d9ef9 100644
--- a/JavaScriptCore/Configurations/FeatureDefines.xcconfig
+++ b/JavaScriptCore/Configurations/FeatureDefines.xcconfig
@@ -57,6 +57,7 @@ ENABLE_GEOLOCATION = ENABLE_GEOLOCATION;
ENABLE_ICONDATABASE = ENABLE_ICONDATABASE;
ENABLE_IMAGE_RESIZER = ;
ENABLE_INDEXED_DATABASE = ;
+ENABLE_INPUT_SPEECH = ;
ENABLE_JAVASCRIPT_DEBUGGER = ENABLE_JAVASCRIPT_DEBUGGER;
ENABLE_MATHML = ;
ENABLE_METER_TAG = ENABLE_METER_TAG;
@@ -81,4 +82,4 @@ ENABLE_XHTMLMP = ;
ENABLE_XPATH = ENABLE_XPATH;
ENABLE_XSLT = ENABLE_XSLT;
-FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB_SLICE) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_FILE_READER) $(ENABLE_FILE_WRITER) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_IMAGE_RESIZER) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_METER_TAG) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_PROGRESS_TAG) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
+FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB_SLICE) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_FILE_READER) $(ENABLE_FILE_WRITER) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_IMAGE_RESIZER) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_METER_TAG) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_PROGRESS_TAG) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
diff --git a/JavaScriptCore/Configurations/Version.xcconfig b/JavaScriptCore/Configurations/Version.xcconfig
index 6f999af..f775a54 100644
--- a/JavaScriptCore/Configurations/Version.xcconfig
+++ b/JavaScriptCore/Configurations/Version.xcconfig
@@ -22,7 +22,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
MAJOR_VERSION = 534;
-MINOR_VERSION = 1;
+MINOR_VERSION = 2;
TINY_VERSION = 0;
FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION);
diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am
index a9c19c6..957c743 100644
--- a/JavaScriptCore/GNUmakefile.am
+++ b/JavaScriptCore/GNUmakefile.am
@@ -381,6 +381,9 @@ javascriptcore_sources += \
JavaScriptCore/bytecompiler/LabelScope.h \
JavaScriptCore/debugger/Debugger.cpp \
JavaScriptCore/debugger/Debugger.h \
+ JavaScriptCore/parser/ASTBuilder.h \
+ JavaScriptCore/parser/JSParser.cpp \
+ JavaScriptCore/parser/JSParser.h \
JavaScriptCore/parser/Lexer.cpp \
JavaScriptCore/parser/Lexer.h \
JavaScriptCore/parser/NodeConstructors.h \
@@ -394,6 +397,7 @@ javascriptcore_sources += \
JavaScriptCore/parser/ResultType.h \
JavaScriptCore/parser/SourceCode.h \
JavaScriptCore/parser/SourceProvider.h \
+ JavaScriptCore/parser/SyntaxChecker.h \
JavaScriptCore/runtime/ArgList.cpp \
JavaScriptCore/runtime/ArgList.h \
JavaScriptCore/runtime/Arguments.cpp \
@@ -515,8 +519,11 @@ javascriptcore_sources += \
JavaScriptCore/runtime/PutPropertySlot.h \
JavaScriptCore/runtime/RegExp.cpp \
JavaScriptCore/runtime/RegExp.h \
+ JavaScriptCore/runtime/RegExpCache.cpp \
+ JavaScriptCore/runtime/RegExpCache.h \
JavaScriptCore/runtime/RegExpConstructor.cpp \
JavaScriptCore/runtime/RegExpConstructor.h \
+ JavaScriptCore/runtime/RegExpKey.h \
JavaScriptCore/runtime/RegExpMatchesArray.h \
JavaScriptCore/runtime/RegExpObject.cpp \
JavaScriptCore/runtime/RegExpObject.h \
diff --git a/JavaScriptCore/JavaScriptCore.gypi b/JavaScriptCore/JavaScriptCore.gypi
index c54ff17..066e1ff 100644
--- a/JavaScriptCore/JavaScriptCore.gypi
+++ b/JavaScriptCore/JavaScriptCore.gypi
@@ -130,6 +130,9 @@
'jsc.cpp',
'os-win32/stdbool.h',
'os-win32/stdint.h',
+ 'parser/ASTBuilder.h',
+ 'parser/JSParser.cpp',
+ 'parser/JSParser.h',
'parser/Lexer.cpp',
'parser/Lexer.h',
'parser/NodeConstructors.h',
@@ -143,6 +146,7 @@
'parser/ResultType.h',
'parser/SourceCode.h',
'parser/SourceProvider.h',
+ 'parser/SyntaxChecker.h',
'pcre/pcre.h',
'pcre/pcre_compile.cpp',
'pcre/pcre_exec.cpp',
@@ -305,8 +309,11 @@
'runtime/PutPropertySlot.h',
'runtime/RegExp.cpp',
'runtime/RegExp.h',
+ 'runtime/RegExpCache.cpp',
+ 'runtime/RegExpCache.h',
'runtime/RegExpConstructor.cpp',
'runtime/RegExpConstructor.h',
+ 'runtime/RegExpKey.h',
'runtime/RegExpMatchesArray.h',
'runtime/RegExpObject.cpp',
'runtime/RegExpObject.h',
diff --git a/JavaScriptCore/JavaScriptCore.pri b/JavaScriptCore/JavaScriptCore.pri
index 09dba2f..8ef9b30 100644
--- a/JavaScriptCore/JavaScriptCore.pri
+++ b/JavaScriptCore/JavaScriptCore.pri
@@ -1,14 +1,17 @@
# JavaScriptCore - Qt4 build info
+
+include(../common.pri)
+
VPATH += $$PWD
-!CONFIG(release, debug|release) {
- # Output in JavaScriptCore/<config>
- JAVASCRIPTCORE_DESTDIR = debug
- # Use a config-specific target to prevent parallel builds file clashes on Mac
- JAVASCRIPTCORE_TARGET = jscored
-} else {
- JAVASCRIPTCORE_DESTDIR = release
- JAVASCRIPTCORE_TARGET = jscore
-}
+
+# Use a config-specific target to prevent parallel builds file clashes on Mac
+mac: CONFIG(debug, debug|release): JAVASCRIPTCORE_TARGET = jscored
+else: JAVASCRIPTCORE_TARGET = jscore
+
+# Output in JavaScriptCore/<config>
+CONFIG(debug, debug|release) : JAVASCRIPTCORE_DESTDIR = debug
+else: JAVASCRIPTCORE_DESTDIR = release
+
CONFIG(standalone_package) {
isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/generated
} else {
@@ -51,9 +54,6 @@ win32-*: DEFINES += _HAS_TR1=0
DEFINES += BUILDING_QT__ BUILDING_JavaScriptCore BUILDING_WTF
-contains(JAVASCRIPTCORE_JIT,yes): DEFINES+=ENABLE_JIT=1
-contains(JAVASCRIPTCORE_JIT,no): DEFINES+=ENABLE_JIT=0
-
wince* {
INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/ce-compat
DEFINES += WINCEBASIC
diff --git a/JavaScriptCore/JavaScriptCore.pro b/JavaScriptCore/JavaScriptCore.pro
index a3d8358..8ee4f09 100644
--- a/JavaScriptCore/JavaScriptCore.pro
+++ b/JavaScriptCore/JavaScriptCore.pro
@@ -43,7 +43,7 @@ CONFIG(QTDIR_build) {
}
# Pick up 3rdparty libraries from INCLUDE/LIB just like with MSVC
-win32-g++ {
+win32-g++* {
TMPPATH = $$quote($$(INCLUDE))
QMAKE_INCDIR_POST += $$split(TMPPATH,";")
TMPPATH = $$quote($$(LIB))
@@ -109,6 +109,7 @@ SOURCES += \
jit/JITPropertyAccess32_64.cpp \
jit/JITStubs.cpp \
jit/ThunkGenerators.cpp \
+ parser/JSParser.cpp \
parser/Lexer.cpp \
parser/Nodes.cpp \
parser/ParserArena.cpp \
@@ -191,6 +192,7 @@ SOURCES += \
runtime/RegExp.cpp \
runtime/RegExpObject.cpp \
runtime/RegExpPrototype.cpp \
+ runtime/RegExpCache.cpp \
runtime/RopeImpl.cpp \
runtime/ScopeChain.cpp \
runtime/SmallStrings.cpp \
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make
index 806894a..4c47ac6 100644
--- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make
+++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make
@@ -31,3 +31,5 @@ install:
xcopy "$(OBJROOT)\include\*" "$(DSTROOT)\AppleInternal\include\" /e/v/i/h/y
xcopy "$(OBJROOT)\lib\*" "$(DSTROOT)\AppleInternal\lib\" /e/v/i/h/y
xcopy "$(OBJROOT)\bin\JavaScriptCore.resources\*" "$(DSTROOT)\AppleInternal\bin\JavaScriptCore.resources" /e/v/i/h/y
+ -mkdir "$(DSTROOT)\AppleInternal\Sources\JavaScriptCore"
+ xcopy "$(OBJROOT)\obj\JavaScriptCore\DerivedSources\*" "$(DSTROOT)\AppleInternal\Sources\WebCore" /e/v/i/h/y
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
index effce51..8117f78 100644
--- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
+++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
@@ -1089,6 +1089,14 @@
>
</File>
<File
+ RelativePath="..\..\runtime\RegExpCache.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\runtime\RegExpCache.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\RegExpConstructor.cpp"
>
</File>
@@ -1097,6 +1105,10 @@
>
</File>
<File
+ RelativePath="..\..\runtime\RegExpKey.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\RegExpMatchesArray.h"
>
</File>
@@ -1789,6 +1801,18 @@
Name="parser"
>
<File
+ RelativePath="..\..\parser\ASTBuilder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\parser\JSParser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\parser\JSParser.h"
+ >
+ </File>
+ <File
RelativePath="..\..\parser\Lexer.cpp"
>
</File>
@@ -1840,6 +1864,10 @@
RelativePath="..\..\parser\SourceProvider.h"
>
</File>
+ <File
+ RelativePath="..\..\parser\SyntaxChecker.h"
+ >
+ </File>
</Filter>
<Filter
Name="Derived Sources"
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 3b448c5..bc58f5d 100644
--- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -293,6 +293,9 @@
969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07950ED1D3AE00F1F681 /* Opcode.h */; settings = {ATTRIBUTES = (Private, ); }; };
96DD73790F9DA3100027FBCC /* VMTags.h in Headers */ = {isa = PBXBuildFile; fileRef = 96DD73780F9DA3100027FBCC /* VMTags.h */; settings = {ATTRIBUTES = (Private, ); }; };
971EDEA61169E0D3005E4262 /* Terminator.h in Headers */ = {isa = PBXBuildFile; fileRef = 97F6903A1169DF7F00A6BB46 /* Terminator.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1712B3A11C7B212007A5315 /* RegExpCache.cpp */; };
+ A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B3E11C7B228007A5315 /* RegExpCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B4011C7B235007A5315 /* RegExpKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
A71236E51195F33C00BD2174 /* JITOpcodes32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */; };
A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72700780DAC605600E548D7 /* JSNotAnObject.cpp */; };
A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; };
@@ -313,6 +316,10 @@
A782F1A50EEC9FA20036273F /* ExecutableAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A782F1A40EEC9FA20036273F /* ExecutableAllocatorPosix.cpp */; };
A783A0D111A36DCA00563D20 /* JSObjectWithGlobalObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A783A0D011A36DCA00563D20 /* JSObjectWithGlobalObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
A783A2AB11A5BE8400563D20 /* JSObjectWithGlobalObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A783A2AA11A5BE8400563D20 /* JSObjectWithGlobalObject.cpp */; };
+ A784A26111D16622005776AC /* ASTBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */; };
+ A784A26211D16622005776AC /* JSParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A7EE7511B98B8D0065A14F /* JSParser.cpp */; };
+ A784A26311D16622005776AC /* JSParser.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7611B98B8D0065A14F /* JSParser.h */; };
+ A784A26411D16622005776AC /* SyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */; };
A791EF280F11E07900AE1F68 /* JSByteArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A791EF260F11E07900AE1F68 /* JSByteArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
A791EF290F11E07900AE1F68 /* JSByteArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A791EF270F11E07900AE1F68 /* JSByteArray.cpp */; };
A7A1F7AC0F252B3C00E184E2 /* ByteArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */; };
@@ -888,6 +895,9 @@
969A09220ED1E09C00F1F681 /* Completion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Completion.cpp; sourceTree = "<group>"; };
96DD73780F9DA3100027FBCC /* VMTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMTags.h; sourceTree = "<group>"; };
97F6903A1169DF7F00A6BB46 /* Terminator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Terminator.h; sourceTree = "<group>"; };
+ A1712B3A11C7B212007A5315 /* RegExpCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpCache.cpp; sourceTree = "<group>"; };
+ A1712B3E11C7B228007A5315 /* RegExpCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCache.h; sourceTree = "<group>"; };
+ A1712B4011C7B235007A5315 /* RegExpKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpKey.h; sourceTree = "<group>"; };
A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITOpcodes32_64.cpp; sourceTree = "<group>"; };
A718F61A11754A21002465A7 /* RegExpJitTables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpJitTables.h; sourceTree = "<group>"; };
A718F8211178EB4B002465A7 /* create_regex_tables */ = {isa = PBXFileReference; explicitFileType = text.script.python; fileEncoding = 4; path = create_regex_tables; sourceTree = "<group>"; };
@@ -915,6 +925,10 @@
A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectRefPrivate.h; sourceTree = "<group>"; };
A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ByteArray.cpp; sourceTree = "<group>"; };
A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByteArray.h; sourceTree = "<group>"; };
+ A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTBuilder.h; sourceTree = "<group>"; };
+ A7A7EE7511B98B8D0065A14F /* JSParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSParser.cpp; sourceTree = "<group>"; };
+ A7A7EE7611B98B8D0065A14F /* JSParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSParser.h; sourceTree = "<group>"; };
+ A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyntaxChecker.h; sourceTree = "<group>"; };
A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableAllocator.h; sourceTree = "<group>"; };
A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocator.cpp; sourceTree = "<group>"; };
A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITPropertyAccess32_64.cpp; sourceTree = "<group>"; };
@@ -1516,7 +1530,10 @@
7E39D8370EC3A388003AF11A /* parser */ = {
isa = PBXGroup;
children = (
+ A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */,
933A3499038AE7C6008635CE /* Grammar.y */,
+ A7A7EE7511B98B8D0065A14F /* JSParser.cpp */,
+ A7A7EE7611B98B8D0065A14F /* JSParser.h */,
93F1981A08245AAE001E9ABC /* Keywords.table */,
F692A8650255597D01FF60F7 /* Lexer.cpp */,
F692A8660255597D01FF60F7 /* Lexer.h */,
@@ -1531,6 +1548,7 @@
869EBCB60E8C6D4A008722CC /* ResultType.h */,
65E866EE0DD59AFA00A2B2A1 /* SourceCode.h */,
65E866ED0DD59AFA00A2B2A1 /* SourceProvider.h */,
+ A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */,
);
path = parser;
sourceTree = "<group>";
@@ -1538,6 +1556,9 @@
7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = {
isa = PBXGroup;
children = (
+ A1712B4011C7B235007A5315 /* RegExpKey.h */,
+ A1712B3E11C7B228007A5315 /* RegExpCache.h */,
+ A1712B3A11C7B212007A5315 /* RegExpCache.cpp */,
BCF605110E203EF800B9A64D /* ArgList.cpp */,
BCF605120E203EF800B9A64D /* ArgList.h */,
BC257DE50E1F51C50016B6C9 /* Arguments.cpp */,
@@ -2166,6 +2187,11 @@
86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */,
A783A0D111A36DCA00563D20 /* JSObjectWithGlobalObject.h in Headers */,
BC01D4F211A8F1FF00A54B2A /* JSZombie.h in Headers */,
+ A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */,
+ A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */,
+ A784A26111D16622005776AC /* ASTBuilder.h in Headers */,
+ A784A26311D16622005776AC /* JSParser.h in Headers */,
+ A784A26411D16622005776AC /* SyntaxChecker.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2605,6 +2631,8 @@
146FE51211A710430087AE66 /* JITCall32_64.cpp in Sources */,
A783A2AB11A5BE8400563D20 /* JSObjectWithGlobalObject.cpp in Sources */,
BC01D4F111A8F1FF00A54B2A /* JSZombie.cpp in Sources */,
+ A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */,
+ A784A26211D16622005776AC /* JSParser.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/JavaScriptCore/assembler/AssemblerBuffer.h b/JavaScriptCore/assembler/AssemblerBuffer.h
index e2fb8a1..11e0df0 100644
--- a/JavaScriptCore/assembler/AssemblerBuffer.h
+++ b/JavaScriptCore/assembler/AssemblerBuffer.h
@@ -37,13 +37,14 @@
namespace JSC {
class AssemblerBuffer {
- static const int inlineCapacity = 256;
+ static const int inlineCapacity = 128 - sizeof(char*) - 2 * sizeof(int);
public:
AssemblerBuffer()
: m_buffer(m_inlineBuffer)
, m_capacity(inlineCapacity)
, m_size(0)
{
+ COMPILE_ASSERT(sizeof(AssemblerBuffer) == 128, AssemblerBuffer_should_be_128_bytes);
}
~AssemblerBuffer()
diff --git a/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h b/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h
index b1c537e..599be14 100644
--- a/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h
+++ b/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h
@@ -190,6 +190,8 @@ public:
void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false)
{
+ if (!m_numConsts)
+ m_maxDistance = maxPoolSize;
flushIfNoSpaceFor(4, 4);
m_loadOffsets.append(AssemblerBuffer::size());
@@ -279,7 +281,6 @@ private:
m_loadOffsets.clear();
m_numConsts = 0;
- m_maxDistance = maxPoolSize;
}
void flushIfNoSpaceFor(int nextInsnSize)
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index df3ca7b..30d101c 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1519,11 +1519,12 @@ void CodeBlock::markAggregate(MarkStack& markStack)
m_functionDecls[i]->markAggregate(markStack);
}
-void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
+bool CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
{
if (m_exceptionInfo)
- return;
+ return true;
+ ASSERT(!m_rareData || !m_rareData->m_exceptionHandlers.size());
ScopeChainNode* scopeChain = callFrame->scopeChain();
if (m_needsFullScopeChain) {
ScopeChain sc(scopeChain);
@@ -1538,6 +1539,7 @@ void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
}
m_exceptionInfo.set(m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this));
+ return m_exceptionInfo;
}
HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
@@ -1562,11 +1564,8 @@ int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned byteco
{
ASSERT(bytecodeOffset < m_instructionCount);
- reparseForExceptionInfoIfNecessary(callFrame);
- ASSERT(m_exceptionInfo);
-
- if (!m_exceptionInfo->m_lineInfo.size())
- return m_ownerExecutable->source().firstLine(); // Empty function
+ if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_lineInfo.size())
+ return m_ownerExecutable->source().firstLine(); // Empty function or unable to reparse
int low = 0;
int high = m_exceptionInfo->m_lineInfo.size();
@@ -1587,11 +1586,9 @@ int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned b
{
ASSERT(bytecodeOffset < m_instructionCount);
- reparseForExceptionInfoIfNecessary(callFrame);
- ASSERT(m_exceptionInfo);
-
- if (!m_exceptionInfo->m_expressionInfo.size()) {
+ if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_expressionInfo.size()) {
// We didn't think anything could throw. Apparently we were wrong.
+ // Alternatively something went wrong when trying to reparse
startOffset = 0;
endOffset = 0;
divot = 0;
@@ -1626,10 +1623,7 @@ bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsi
{
ASSERT(bytecodeOffset < m_instructionCount);
- reparseForExceptionInfoIfNecessary(callFrame);
- ASSERT(m_exceptionInfo);
-
- if (!m_exceptionInfo->m_getByIdExceptionInfo.size())
+ if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_getByIdExceptionInfo.size())
return false;
int low = 0;
diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h
index 27e56c6..590fe2e 100644
--- a/JavaScriptCore/bytecode/CodeBlock.h
+++ b/JavaScriptCore/bytecode/CodeBlock.h
@@ -351,7 +351,8 @@ namespace JSC {
unsigned bytecodeOffset(CallFrame* callFrame, ReturnAddressPtr returnAddress)
{
- reparseForExceptionInfoIfNecessary(callFrame);
+ if (!reparseForExceptionInfoIfNecessary(callFrame))
+ return 1;
return binaryChop<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callReturnIndexVector().begin(), callReturnIndexVector().size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset;
}
@@ -521,7 +522,7 @@ namespace JSC {
void printPutByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
#endif
- void reparseForExceptionInfoIfNecessary(CallFrame*);
+ bool reparseForExceptionInfoIfNecessary(CallFrame*) WARN_UNUSED_RETURN;
void createRareDataIfNecessary()
{
@@ -655,7 +656,7 @@ namespace JSC {
// symbol table, so we just pass as a raw pointer with a ref count of 1. We then manually deref
// in the destructor.
FunctionCodeBlock(FunctionExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, bool isConstructor)
- : CodeBlock(ownerExecutable, codeType, sourceProvider, sourceOffset, new SharedSymbolTable, isConstructor)
+ : CodeBlock(ownerExecutable, codeType, sourceProvider, sourceOffset, SharedSymbolTable::create().releaseRef(), isConstructor)
{
}
~FunctionCodeBlock()
diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h
index 81fff99..f845a34 100644
--- a/JavaScriptCore/bytecode/Opcode.h
+++ b/JavaScriptCore/bytecode/Opcode.h
@@ -211,7 +211,7 @@ namespace JSC {
#undef VERIFY_OPCODE_ID
#if HAVE(COMPUTED_GOTO)
-#if COMPILER(RVCT)
+#if COMPILER(RVCT) || COMPILER(INTEL)
typedef void* Opcode;
#else
typedef const void* Opcode;
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 777e1e6..16ef357 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -156,7 +156,7 @@ void BytecodeGenerator::generate()
m_codeBlock->setIsNumericCompareFunction(instructions() == m_globalData->numericCompareFunction(m_scopeChain->globalObject()->globalExec()));
#if !ENABLE(OPCODE_SAMPLING)
- if (!m_regeneratingForExceptionInfo && (m_codeType == FunctionCode || m_codeType == EvalCode))
+ if (!m_regeneratingForExceptionInfo && !m_usesExceptions && (m_codeType == FunctionCode || m_codeType == EvalCode))
m_codeBlock->clearExceptionInfo();
#endif
@@ -219,6 +219,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
, m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
, m_lastOpcodeID(op_end)
, m_emitNodeDepth(0)
+ , m_usesExceptions(false)
, m_regeneratingForExceptionInfo(false)
, m_codeBlockBeingRegeneratedFrom(0)
{
@@ -304,6 +305,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
, m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
, m_lastOpcodeID(op_end)
, m_emitNodeDepth(0)
+ , m_usesExceptions(false)
, m_regeneratingForExceptionInfo(false)
, m_codeBlockBeingRegeneratedFrom(0)
{
@@ -405,6 +407,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
, m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
, m_lastOpcodeID(op_end)
, m_emitNodeDepth(0)
+ , m_usesExceptions(false)
, m_regeneratingForExceptionInfo(false)
, m_codeBlockBeingRegeneratedFrom(0)
{
@@ -1842,6 +1845,7 @@ RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID*
RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
{
+ m_usesExceptions = true;
#if ENABLE(JIT)
HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
#else
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 8f0ce34..8b6ab77 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -363,7 +363,12 @@ namespace JSC {
RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
- void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); }
+ void emitThrow(RegisterID* exc)
+ {
+ m_usesExceptions = true;
+ emitUnaryNoDstOp(op_throw, exc);
+ }
+
RegisterID* emitNewError(RegisterID* dst, bool isReferenceError, JSValue message);
void emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value);
@@ -552,6 +557,7 @@ namespace JSC {
unsigned m_emitNodeDepth;
+ bool m_usesExceptions;
bool m_regeneratingForExceptionInfo;
CodeBlock* m_codeBlockBeingRegeneratedFrom;
diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index 765230e..cdf3e49 100644
--- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -39,6 +39,7 @@
#include "Operations.h"
#include "Parser.h"
#include "PropertyNameArray.h"
+#include "RegExpCache.h"
#include "RegExpObject.h"
#include "SamplingTool.h"
#include <wtf/Assertions.h>
@@ -144,7 +145,7 @@ RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d
RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring());
+ RefPtr<RegExp> regExp = generator.globalData()->regExpCache()->lookupOrCreate(m_pattern.ustring(), m_flags.ustring());
if (!regExp->isValid())
return emitThrowError(generator, false, "Invalid regular expression: %s", regExp->errorMessage());
if (dst == generator.ignoredResult())
diff --git a/JavaScriptCore/create_jit_stubs b/JavaScriptCore/create_jit_stubs
index 4d510ea..9bb9ee5 100644
--- a/JavaScriptCore/create_jit_stubs
+++ b/JavaScriptCore/create_jit_stubs
@@ -42,6 +42,7 @@ $file = $ARGV[0];
die "$usage\n" unless ($prefix and $file);
my $stub_template = "";
+my $output_end = "";
my $stub = "";
my $rtype = "";
@@ -51,9 +52,17 @@ print STDERR "Creating JIT stubs for $file \n";
open(IN, $file) or die "No such file $file";
while ( $_ = <IN> ) {
+ if ( /^$prefix\_BEGIN\((.*)\)/ ) {
+ $stub = $1;
+ $stub =~ s/$offset_template/$offset/g;
+ print $stub . "\n";
+ }
if ( /^$prefix\((.*)\)/ ) {
$stub_template .= $1 . "\n";
}
+ if ( /^$prefix\_END\((.*)\)/ ) {
+ $output_end .= $1 . "\n";
+ }
if ( /^DEFINE_STUB_FUNCTION\((.*), (.*)\)/ ) {
$stub = $stub_template;
$rtype = quotemeta($1);
@@ -66,4 +75,6 @@ while ( $_ = <IN> ) {
}
}
+print $output_end;
+
close(IN);
diff --git a/JavaScriptCore/interpreter/CallFrame.cpp b/JavaScriptCore/interpreter/CallFrame.cpp
index f53e6f4..ff061db 100644
--- a/JavaScriptCore/interpreter/CallFrame.cpp
+++ b/JavaScriptCore/interpreter/CallFrame.cpp
@@ -42,6 +42,12 @@ void CallFrame::dumpCaller()
interpreter()->retrieveLastCaller(this, signedLineNumber, sourceID, urlString, function);
printf("Callpoint => %s:%d\n", urlString.ascii(), signedLineNumber);
}
+
+RegisterFile* CallFrame::registerFile()
+{
+ return &interpreter()->registerFile();
+}
+
#endif
}
diff --git a/JavaScriptCore/interpreter/CallFrame.h b/JavaScriptCore/interpreter/CallFrame.h
index 723d4ae..7ea59fb 100644
--- a/JavaScriptCore/interpreter/CallFrame.h
+++ b/JavaScriptCore/interpreter/CallFrame.h
@@ -117,6 +117,7 @@ namespace JSC {
CallFrame* callerFrame, int argc, JSObject* callee)
{
ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller.
+ ASSERT(callerFrame == noCaller() || callerFrame->removeHostCallFrameFlag()->registerFile()->end() >= this);
setCodeBlock(codeBlock);
setScopeChain(scopeChain);
@@ -155,7 +156,9 @@ namespace JSC {
private:
static const intptr_t HostCallFrameFlag = 1;
-
+#ifndef NDEBUG
+ RegisterFile* registerFile();
+#endif
ExecState();
~ExecState();
};
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 91f5c0a..7c5bc6f 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -456,7 +456,6 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
printf("[ScopeChain] | %10p | %p \n", it, (*it).scopeChain()); ++it;
printf("[CallerRegisters] | %10p | %d \n", it, (*it).i()); ++it;
printf("[ReturnPC] | %10p | %p \n", it, (*it).vPC()); ++it;
- ++it;
printf("[ArgumentCount] | %10p | %d \n", it, (*it).i()); ++it;
printf("[Callee] | %10p | %p \n", it, (*it).function()); ++it;
printf("-----------------------------------------------------------------------------\n");
@@ -643,6 +642,10 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
}
CodeBlock* codeBlock = &program->bytecode(callFrame, scopeChain);
+ if (!codeBlock) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
Register* oldEnd = m_registerFile.end();
Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
@@ -722,9 +725,12 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
if (callType == CallTypeJS) {
ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
- CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);
+ CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);
- newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
+ if (newCodeBlock)
+ newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
+ else
+ newCallFrame = 0;
if (UNLIKELY(!newCallFrame)) {
*exception = createStackOverflowError(callFrame);
m_registerFile.shrink(oldEnd);
@@ -811,9 +817,12 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
if (constructType == ConstructTypeJS) {
ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain;
- CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecodeForConstruct(callFrame, constructDataScopeChain);
+ CodeBlock* newCodeBlock = constructData.js.functionExecutable->bytecodeForConstruct(callFrame, constructDataScopeChain);
+ if (newCodeBlock)
+ newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
+ else
+ newCallFrame = 0;
- newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
if (UNLIKELY(!newCallFrame)) {
*exception = createStackOverflowError(callFrame);
m_registerFile.shrink(oldEnd);
@@ -902,8 +911,11 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE
for (int i = 0; i < argc; ++i)
newCallFrame->r(++dst) = jsUndefined();
- CodeBlock* codeBlock = &FunctionExecutable->bytecodeForCall(callFrame, scopeChain);
- newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
+ CodeBlock* codeBlock = FunctionExecutable->bytecodeForCall(callFrame, scopeChain);
+ if (codeBlock)
+ newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
+ else
+ newCallFrame = 0;
if (UNLIKELY(!newCallFrame)) {
*exception = createStackOverflowError(callFrame);
m_registerFile.shrink(oldEnd);
@@ -968,6 +980,10 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain);
+ if (!codeBlock) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
JSVariableObject* variableObject;
for (ScopeChainNode* node = scopeChain; ; node = node->next) {
@@ -3619,11 +3635,13 @@ skip_id_custom_self:
if (callType == CallTypeJS) {
ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
- CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);
+ CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);
CallFrame* previousCallFrame = callFrame;
-
- callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
+ if (newCodeBlock)
+ callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
+ else
+ callFrame = 0;
if (UNLIKELY(!callFrame)) {
callFrame = previousCallFrame;
exceptionValue = createStackOverflowError(callFrame);
@@ -3645,6 +3663,11 @@ skip_id_custom_self:
if (callType == CallTypeHost) {
ScopeChainNode* scopeChain = callFrame->scopeChain();
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+ if (!registerFile->grow(newCallFrame->registers())) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+
newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scopeChain, callFrame, argCount, asObject(v));
JSValue returnValue;
@@ -3766,11 +3789,13 @@ skip_id_custom_self:
if (callType == CallTypeJS) {
ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
- CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);
+ CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);
CallFrame* previousCallFrame = callFrame;
-
- callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
+ if (newCodeBlock)
+ callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
+ else
+ callFrame = 0;
if (UNLIKELY(!callFrame)) {
callFrame = previousCallFrame;
exceptionValue = createStackOverflowError(callFrame);
@@ -3792,6 +3817,10 @@ skip_id_custom_self:
if (callType == CallTypeHost) {
ScopeChainNode* scopeChain = callFrame->scopeChain();
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+ if (!registerFile->grow(newCallFrame->registers())) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_varargs), scopeChain, callFrame, argCount, asObject(v));
JSValue returnValue;
@@ -4085,11 +4114,15 @@ skip_id_custom_self:
if (constructType == ConstructTypeJS) {
ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
- CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecodeForConstruct(callFrame, callDataScopeChain);
+ CodeBlock* newCodeBlock = constructData.js.functionExecutable->bytecodeForConstruct(callFrame, callDataScopeChain);
CallFrame* previousCallFrame = callFrame;
- callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
+ if (newCodeBlock)
+ callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
+ else
+ callFrame = 0;
+
if (UNLIKELY(!callFrame)) {
callFrame = previousCallFrame;
exceptionValue = createStackOverflowError(callFrame);
@@ -4110,6 +4143,10 @@ skip_id_custom_self:
if (constructType == ConstructTypeHost) {
ScopeChainNode* scopeChain = callFrame->scopeChain();
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+ if (!registerFile->grow(newCallFrame->registers())) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
newCallFrame->init(0, vPC + OPCODE_LENGTH(op_construct), scopeChain, callFrame, argCount, asObject(v));
JSValue returnValue;
diff --git a/JavaScriptCore/jit/ExecutableAllocator.h b/JavaScriptCore/jit/ExecutableAllocator.h
index 610b788..703f63f 100644
--- a/JavaScriptCore/jit/ExecutableAllocator.h
+++ b/JavaScriptCore/jit/ExecutableAllocator.h
@@ -25,7 +25,6 @@
#ifndef ExecutableAllocator_h
#define ExecutableAllocator_h
-
#include <stddef.h> // for ptrdiff_t
#include <limits>
#include <wtf/Assertions.h>
@@ -80,7 +79,7 @@ inline size_t roundUpAllocationSize(size_t request, size_t granularity)
}
-#if ENABLE(ASSEMBLER)
+#if ENABLE(JIT) && ENABLE(ASSEMBLER)
namespace JSC {
@@ -316,6 +315,6 @@ inline void* ExecutablePool::poolAllocate(size_t n)
}
-#endif // ENABLE(ASSEMBLER)
+#endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
#endif // !defined(ExecutableAllocator)
diff --git a/JavaScriptCore/jit/JITInlineMethods.h b/JavaScriptCore/jit/JITInlineMethods.h
index cba290b..04f7158 100644
--- a/JavaScriptCore/jit/JITInlineMethods.h
+++ b/JavaScriptCore/jit/JITInlineMethods.h
@@ -645,7 +645,7 @@ ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from)
{
storePtr(from, Address(callFrameRegister, dst * sizeof(Register)));
- m_lastResultBytecodeRegister = (from == cachedResultRegister) ? dst : std::numeric_limits<int>::max();
+ m_lastResultBytecodeRegister = (from == cachedResultRegister) ? static_cast<int>(dst) : std::numeric_limits<int>::max();
}
ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp
index 0848348..9a34931 100644
--- a/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/JavaScriptCore/jit/JITOpcodes.cpp
@@ -73,12 +73,14 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
// VirtualCallLink Trampoline
// regT0 holds callee, regT1 holds argCount. regT2 will hold the FunctionExecutable.
+ JumpList callLazyLinkFailures;
Label virtualCallLinkBegin = align();
compileOpCallInitializeCallFrame();
preserveReturnAddressAfterCall(regT3);
emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
restoreArgumentReference();
Call callLazyLinkCall = call();
+ callLazyLinkFailures.append(branchTestPtr(Zero, regT0));
restoreReturnAddressBeforeReturn(regT3);
emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
jump(regT0);
@@ -91,10 +93,24 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
restoreArgumentReference();
Call callLazyLinkConstruct = call();
+ callLazyLinkFailures.append(branchTestPtr(Zero, regT0));
restoreReturnAddressBeforeReturn(regT3);
emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
jump(regT0);
+ // If the parser fails we want to be able to be able to keep going,
+ // So we handle this as a parse failure.
+ callLazyLinkFailures.link(this);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+ restoreReturnAddressBeforeReturn(regT1);
+ move(ImmPtr(&globalData->exceptionLocation), regT2);
+ storePtr(regT1, regT2);
+ poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+ poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()));
+ ret();
+
+
// VirtualCall Trampoline
// regT0 holds callee, regT1 holds argCount. regT2 will hold the FunctionExecutable.
Label virtualCallBegin = align();
@@ -181,6 +197,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
Label nativeCallThunk = align();
+#if CPU(X86_64)
// Load caller frame's scope chain into this callframe so that whatever we call can
// get to its global data.
emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0);
@@ -190,7 +207,6 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
peek(regT1);
emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC);
-#if CPU(X86_64)
// Calling convention: f(edi, esi, edx, ecx, ...);
// Host function signature: f(ExecState*);
move(callFrameRegister, X86Registers::edi);
@@ -204,6 +220,27 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
addPtr(Imm32(16 - sizeof(void*)), stackPointerRegister);
+#elif CPU(ARM)
+ // Load caller frame's scope chain into this callframe so that whatever we call can
+ // get to its global data.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+ emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+ preserveReturnAddressAfterCall(regT3); // Callee preserved
+ emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+
+ // Calling convention: f(r0 == regT0, r1 == regT1, ...);
+ // Host function signature: f(ExecState*);
+ move(callFrameRegister, ARMRegisters::r0);
+
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, ARMRegisters::r1);
+ move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+ loadPtr(Address(ARMRegisters::r1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+ call(Address(regT2, executableOffsetToFunction));
+
+ restoreReturnAddressBeforeReturn(regT3);
+
#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
#else
@@ -220,12 +257,18 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
// Handle an exception
exceptionHandler.link(this);
+
// Grab the return address.
- peek(regT1);
+ preserveReturnAddressAfterCall(regT1);
+
move(ImmPtr(&globalData->exceptionLocation), regT2);
storePtr(regT1, regT2);
- poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
- poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()));
+ poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+
+ // Set the return address.
+ move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
+ restoreReturnAddressBeforeReturn(regT1);
+
ret();
return nativeCallThunk;
diff --git a/JavaScriptCore/jit/JITOpcodes32_64.cpp b/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 239751f..a44a8a1 100644
--- a/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -66,8 +66,8 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
#endif
// (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
-
#if ENABLE(JIT_OPTIMIZE_CALL)
+ JumpList callLazyLinkFailures;
// VirtualCallLink Trampoline
// regT0 holds callee, regT1 holds argCount. regT2 will hold the FunctionExecutable.
Label virtualCallLinkBegin = align();
@@ -76,6 +76,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
restoreArgumentReference();
Call callLazyLinkCall = call();
+ callLazyLinkFailures.append(branchTestPtr(Zero, regT0));
restoreReturnAddressBeforeReturn(regT3);
emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
jump(regT0);
@@ -89,8 +90,22 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
restoreArgumentReference();
Call callLazyLinkConstruct = call();
restoreReturnAddressBeforeReturn(regT3);
+ callLazyLinkFailures.append(branchTestPtr(Zero, regT0));
emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
jump(regT0);
+
+ // If the parser fails we want to be able to be able to keep going,
+ // So we handle this as a parse failure.
+ callLazyLinkFailures.link(this);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+ restoreReturnAddressBeforeReturn(regT1);
+ move(ImmPtr(&globalData->exceptionLocation), regT2);
+ storePtr(regT1, regT2);
+ poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+ poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()));
+ ret();
+
#endif // ENABLE(JIT_OPTIMIZE_CALL)
// VirtualCall Trampoline
@@ -181,6 +196,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
Label nativeCallThunk = align();
+#if CPU(X86)
// Load caller frame's scope chain into this callframe so that whatever we call can
// get to its global data.
emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0);
@@ -190,7 +206,6 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
peek(regT1);
emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC);
-#if CPU(X86)
// Calling convention: f(ecx, edx, ...);
// Host function signature: f(ExecState*);
move(callFrameRegister, X86Registers::ecx);
@@ -205,6 +220,28 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
addPtr(Imm32(16 - sizeof(void*)), stackPointerRegister);
+#elif CPU(ARM)
+ // Load caller frame's scope chain into this callframe so that whatever we call can
+ // get to its global data.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+ emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+ preserveReturnAddressAfterCall(regT3); // Callee preserved
+ emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+
+ // Calling convention: f(r0 == regT0, r1 == regT1, ...);
+ // Host function signature: f(ExecState*);
+ move(callFrameRegister, ARMRegisters::r0);
+
+ // call the function
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, ARMRegisters::r1);
+ move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+ loadPtr(Address(ARMRegisters::r1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+ call(Address(regT2, executableOffsetToFunction));
+
+ restoreReturnAddressBeforeReturn(regT3);
+
#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
#else
@@ -220,11 +257,18 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
// Handle an exception
sawException.link(this);
- peek(regT1);
+
+ // Grab the return address.
+ preserveReturnAddressAfterCall(regT1);
+
move(ImmPtr(&globalData->exceptionLocation), regT2);
storePtr(regT1, regT2);
- poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
- poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()));
+ poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+
+ // Set the return address.
+ move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
+ restoreReturnAddressBeforeReturn(regT1);
+
ret();
return nativeCallThunk;
@@ -258,6 +302,29 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa
addPtr(Imm32(16 - sizeof(void*)), stackPointerRegister);
+#elif CPU(ARM)
+ // Load caller frame's scope chain into this callframe so that whatever we call can
+ // get to its global data.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+ emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+ preserveReturnAddressAfterCall(regT3); // Callee preserved
+ emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+
+ // Calling convention: f(r0 == regT0, r1 == regT1, ...);
+ // Host function signature: f(ExecState*);
+ move(callFrameRegister, ARMRegisters::r0);
+
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, ARMRegisters::r1);
+ move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+ loadPtr(Address(ARMRegisters::r1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+
+ // call the function
+ nativeCall = call();
+
+ restoreReturnAddressBeforeReturn(regT3);
+
#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
#else
@@ -272,11 +339,18 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa
// Handle an exception
sawException.link(this);
- peek(regT1);
+
+ // Grab the return address.
+ preserveReturnAddressAfterCall(regT1);
+
move(ImmPtr(&globalData->exceptionLocation), regT2);
storePtr(regT1, regT2);
- poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
- poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()));
+ poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+
+ // Set the return address.
+ move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
+ restoreReturnAddressBeforeReturn(regT1);
+
ret();
// All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
@@ -607,8 +681,8 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
// Load property.
loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_externalStorage)), regT2);
load32(offsetAddr, regT3);
- load32(BaseIndex(regT2, regT3, TimesEight), regT0); // payload
- load32(BaseIndex(regT2, regT3, TimesEight, 4), regT1); // tag
+ load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
+ load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
emitStore(dst, regT1, regT0);
map(m_bytecodeOffset + dynamic ? OPCODE_LENGTH(op_resolve_global_dynamic) : OPCODE_LENGTH(op_resolve_global), dst, regT1, regT0);
}
diff --git a/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
index 6b8af7c..16cf84a 100644
--- a/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
+++ b/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
@@ -314,8 +314,8 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3);
addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength))));
- load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), regT1); // tag
- load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); // payload
+ load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
+ load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
addSlowCase(branch32(Equal, regT1, Imm32(JSValue::EmptyValueTag)));
emitStore(dst, regT1, regT0);
@@ -366,12 +366,12 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3);
- Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), Imm32(JSValue::EmptyValueTag));
+ Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::EmptyValueTag));
Label storeResult(this);
emitLoad(value, regT1, regT0);
- store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); // payload
- store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4)); // tag
+ store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); // payload
+ store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); // tag
Jump end = jump();
empty.link(this);
@@ -571,8 +571,8 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, Register
void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
{
if (base->isUsingInlineStorage()) {
- load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]), resultPayload);
- load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + 4, resultTag);
+ load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload), resultPayload);
+ load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag), resultTag);
return;
}
@@ -580,8 +580,8 @@ void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID res
PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
loadPtr(static_cast<void*>(protoPropertyStorage), temp);
- load32(Address(temp, offset), resultPayload);
- load32(Address(temp, offset + 4), resultTag);
+ load32(Address(temp, offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
+ load32(Address(temp, offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
}
void JIT::testPrototype(Structure* structure, JumpList& failureCases)
@@ -628,8 +628,8 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount()));
storePtr(ImmPtr(newStructure), Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)));
- load32(Address(stackPointerRegister, offsetof(struct JITStackFrame, args[2]) + sizeof(void*)), regT3);
- load32(Address(stackPointerRegister, offsetof(struct JITStackFrame, args[2]) + sizeof(void*) + 4), regT2);
+ load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT3);
+ load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT2);
// Write the value
compilePutDirectOffset(regT0, regT2, regT3, newStructure, cachedOffset);
@@ -673,8 +673,8 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St
// Patch the offset into the propoerty map to load from, then patch the Structure to look for.
repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure);
- repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset1), offset); // payload
- repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + 4); // tag
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
}
void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
@@ -714,8 +714,8 @@ void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo,
// Patch the offset into the propoerty map to load from, then patch the Structure to look for.
repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure);
- repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset1), offset); // payload
- repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset2), offset + 4); // tag
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
}
void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
@@ -1122,8 +1122,8 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, Register
ASSERT(sizeof(JSValue) == 8);
Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
- loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
- loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
+ loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
+ loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
Jump finishedLoad = jump();
notUsingInlineStorage.link(this);
loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index ff0dc3f..c4a6507 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -1967,7 +1967,11 @@ DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
codePtr = executable->generatedJITCodeForCall().addressForCall();
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- codeBlock = &functionExecutable->bytecodeForCall(stackFrame.callFrame, callee->scope().node());
+ codeBlock = functionExecutable->bytecodeForCall(stackFrame.callFrame, callee->scope().node());
+ if (!codeBlock) {
+ stackFrame.callFrame->globalData().exception = createStackOverflowError(callFrame);
+ return 0;
+ }
functionExecutable->jitCodeForCall(callFrame, callee->scope().node());
if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
codePtr = functionExecutable->generatedJITCodeForCall().addressForCall();
@@ -1997,7 +2001,11 @@ DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
codePtr = executable->generatedJITCodeForConstruct().addressForCall();
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- codeBlock = &functionExecutable->bytecodeForConstruct(stackFrame.callFrame, callee->scope().node());
+ codeBlock = functionExecutable->bytecodeForConstruct(stackFrame.callFrame, callee->scope().node());
+ if (!codeBlock) {
+ throwStackOverflowError(callFrame, stackFrame.globalData, ReturnAddressPtr(callFrame->returnPC()), STUB_RETURN_ADDRESS);
+ VM_THROW_EXCEPTION();
+ }
functionExecutable->jitCodeForConstruct(callFrame, callee->scope().node());
if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
codePtr = functionExecutable->generatedJITCodeForConstruct().addressForCall();
@@ -2040,7 +2048,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
int argCount = stackFrame.args[2].int32();
CallFrame* previousCallFrame = stackFrame.callFrame;
CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
-
+ if (!stackFrame.registerFile->grow(callFrame->registers())) {
+ throwStackOverflowError(previousCallFrame, stackFrame.globalData, callFrame->returnPC(), STUB_RETURN_ADDRESS);
+ VM_THROW_EXCEPTION();
+ }
callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(funcVal));
stackFrame.callFrame = callFrame;
@@ -2175,6 +2186,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
int argCount = stackFrame.args[2].int32();
CallFrame* previousCallFrame = stackFrame.callFrame;
CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
+ if (!stackFrame.registerFile->grow(callFrame->registers())) {
+ throwStackOverflowError(previousCallFrame, stackFrame.globalData, callFrame->returnPC(), STUB_RETURN_ADDRESS);
+ VM_THROW_EXCEPTION();
+ }
callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(constrVal));
stackFrame.callFrame = callFrame;
diff --git a/JavaScriptCore/jsc/CMakeLists.txt b/JavaScriptCore/jsc/CMakeLists.txt
index cc39e14..970c20f 100644
--- a/JavaScriptCore/jsc/CMakeLists.txt
+++ b/JavaScriptCore/jsc/CMakeLists.txt
@@ -9,11 +9,8 @@ SET(JSC_LIBRARIES
${JavaScriptCore_LIBRARY_NAME}
)
-
-SET(JSC_PORT_FLAGS )
INCLUDE_IF_EXISTS(${JAVASCRIPTCORE_DIR}/jsc/CMakeLists${PORT}.txt)
-
WEBKIT_WRAP_SOURCELIST(${JSC_SOURCES})
INCLUDE_DIRECTORIES(./ ${JavaScriptCore_INCLUDE_DIRECTORIES})
ADD_EXECUTABLE(${JSC_EXECUTABLE_NAME} ${JSC_HEADERS} ${JSC_SOURCES})
diff --git a/JavaScriptCore/parser/ASTBuilder.h b/JavaScriptCore/parser/ASTBuilder.h
new file mode 100644
index 0000000..7dcdff0
--- /dev/null
+++ b/JavaScriptCore/parser/ASTBuilder.h
@@ -0,0 +1,925 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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 ASTBuilder_h
+#define ASTBuilder_h
+
+#include "NodeConstructors.h"
+#include "SyntaxChecker.h"
+#include <utility>
+
+namespace JSC {
+
+class ASTBuilder {
+ struct BinaryOpInfo {
+ BinaryOpInfo() {}
+ BinaryOpInfo(int s, int d, int e, bool r)
+ : start(s)
+ , divot(d)
+ , end(e)
+ , hasAssignment(r)
+ {
+ }
+ BinaryOpInfo(const BinaryOpInfo& lhs, const BinaryOpInfo& rhs)
+ : start(lhs.start)
+ , divot(rhs.start)
+ , end(rhs.end)
+ , hasAssignment(lhs.hasAssignment || rhs.hasAssignment)
+ {
+ }
+ int start;
+ int divot;
+ int end;
+ bool hasAssignment;
+ };
+
+
+ struct AssignmentInfo {
+ AssignmentInfo() {}
+ AssignmentInfo(ExpressionNode* node, int start, int divot, int initAssignments, Operator op)
+ : m_node(node)
+ , m_start(start)
+ , m_divot(divot)
+ , m_initAssignments(initAssignments)
+ , m_op(op)
+ {
+ }
+ ExpressionNode* m_node;
+ int m_start;
+ int m_divot;
+ int m_initAssignments;
+ Operator m_op;
+ };
+public:
+ ASTBuilder(JSGlobalData* globalData, Lexer* lexer)
+ : m_globalData(globalData)
+ , m_lexer(lexer)
+ , m_evalCount(0)
+ {
+ m_scopes.append(Scope(globalData));
+ }
+
+ typedef SyntaxChecker FunctionBodyBuilder;
+
+ typedef ExpressionNode* Expression;
+ typedef JSC::SourceElements* SourceElements;
+ typedef ArgumentsNode* Arguments;
+ typedef CommaNode* Comma;
+ typedef PropertyNode* Property;
+ typedef PropertyListNode* PropertyList;
+ typedef ElementNode* ElementList;
+ typedef ArgumentListNode* ArgumentsList;
+ typedef ParameterNode* FormalParameterList;
+ typedef FunctionBodyNode* FunctionBody;
+ typedef StatementNode* Statement;
+ typedef ClauseListNode* ClauseList;
+ typedef CaseClauseNode* Clause;
+ typedef ConstDeclNode* ConstDeclList;
+ typedef std::pair<ExpressionNode*, BinaryOpInfo> BinaryOperand;
+
+ static const bool CreatesAST = true;
+
+ ExpressionNode* makeBinaryNode(int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>);
+ ExpressionNode* makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end);
+
+ JSC::SourceElements* createSourceElements() { return new (m_globalData) JSC::SourceElements(m_globalData); }
+
+ ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scopes.last().m_varDeclarations; }
+ ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scopes.last().m_funcDeclarations; }
+ int features() const { return m_scopes.last().m_features; }
+ int numConstants() const { return m_scopes.last().m_numConstants; }
+
+ void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); }
+
+ CommaNode* createCommaExpr(ExpressionNode* lhs, ExpressionNode* rhs) { return new (m_globalData) CommaNode(m_globalData, lhs, rhs); }
+
+ ExpressionNode* makeAssignNode(ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end);
+ ExpressionNode* makePrefixNode(ExpressionNode*, Operator, int start, int divot, int end);
+ ExpressionNode* makePostfixNode(ExpressionNode*, Operator, int start, int divot, int end);
+ ExpressionNode* makeTypeOfNode(ExpressionNode*);
+ ExpressionNode* makeDeleteNode(ExpressionNode*, int start, int divot, int end);
+ ExpressionNode* makeNegateNode(ExpressionNode*);
+ ExpressionNode* makeBitwiseNotNode(ExpressionNode*);
+ ExpressionNode* makeMultNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+ ExpressionNode* makeDivNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+ ExpressionNode* makeAddNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+ ExpressionNode* makeSubNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+ ExpressionNode* makeLeftShiftNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+ ExpressionNode* makeRightShiftNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+
+ ExpressionNode* createLogicalNot(ExpressionNode* expr) { return new (m_globalData) LogicalNotNode(m_globalData, expr); }
+ ExpressionNode* createUnaryPlus(ExpressionNode* expr) { return new (m_globalData) UnaryPlusNode(m_globalData, expr); }
+ ExpressionNode* createVoid(ExpressionNode* expr)
+ {
+ incConstants();
+ return new (m_globalData) VoidNode(m_globalData, expr);
+ }
+ ExpressionNode* thisExpr()
+ {
+ usesThis();
+ return new (m_globalData) ThisNode(m_globalData);
+ }
+ ExpressionNode* createResolve(const Identifier* ident, int start)
+ {
+ if (m_globalData->propertyNames->arguments == *ident)
+ usesArguments();
+ return new (m_globalData) ResolveNode(m_globalData, *ident, start);
+ }
+ ExpressionNode* createObjectLiteral() { return new (m_globalData) ObjectLiteralNode(m_globalData); }
+ ExpressionNode* createObjectLiteral(PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(m_globalData, properties); }
+
+ ExpressionNode* createArray(int elisions)
+ {
+ if (elisions)
+ incConstants();
+ return new (m_globalData) ArrayNode(m_globalData, elisions);
+ }
+
+ ExpressionNode* createArray(ElementNode* elems) { return new (m_globalData) ArrayNode(m_globalData, elems); }
+ ExpressionNode* createArray(int elisions, ElementNode* elems)
+ {
+ if (elisions)
+ incConstants();
+ return new (m_globalData) ArrayNode(m_globalData, elisions, elems);
+ }
+ ExpressionNode* createNumberExpr(double d)
+ {
+ incConstants();
+ return new (m_globalData) NumberNode(m_globalData, d);
+ }
+
+ ExpressionNode* createString(const Identifier* string)
+ {
+ incConstants();
+ return new (m_globalData) StringNode(m_globalData, *string);
+ }
+
+ ExpressionNode* createBoolean(bool b)
+ {
+ incConstants();
+ return new (m_globalData) BooleanNode(m_globalData, b);
+ }
+
+ ExpressionNode* createNull()
+ {
+ incConstants();
+ return new (m_globalData) NullNode(m_globalData);
+ }
+
+ ExpressionNode* createBracketAccess(ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, int start, int divot, int end)
+ {
+ BracketAccessorNode* node = new (m_globalData) BracketAccessorNode(m_globalData, base, property, propertyHasAssignments);
+ setExceptionLocation(node, start, divot, end);
+ return node;
+ }
+
+ ExpressionNode* createDotAccess(ExpressionNode* base, const Identifier& property, int start, int divot, int end)
+ {
+ DotAccessorNode* node = new (m_globalData) DotAccessorNode(m_globalData, base, property);
+ setExceptionLocation(node, start, divot, end);
+ return node;
+ }
+
+ ExpressionNode* createRegex(const Identifier& pattern, const Identifier& flags, int start)
+ {
+ RegExpNode* node = new (m_globalData) RegExpNode(m_globalData, pattern, flags);
+ int size = pattern.size() + 2; // + 2 for the two /'s
+ setExceptionLocation(node, start, start + size, start + size);
+ return node;
+ }
+
+ ExpressionNode* createNewExpr(ExpressionNode* expr, ArgumentsNode* arguments, int start, int divot, int end)
+ {
+ NewExprNode* node = new (m_globalData) NewExprNode(m_globalData, expr, arguments);
+ setExceptionLocation(node, start, divot, end);
+ return node;
+ }
+
+ ExpressionNode* createNewExpr(ExpressionNode* expr, int start, int end)
+ {
+ NewExprNode* node = new (m_globalData) NewExprNode(m_globalData, expr);
+ setExceptionLocation(node, start, end, end);
+ return node;
+ }
+
+ ExpressionNode* createConditionalExpr(ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs)
+ {
+ return new (m_globalData) ConditionalNode(m_globalData, condition, lhs, rhs);
+ }
+
+ ExpressionNode* createAssignResolve(const Identifier& ident, ExpressionNode* rhs, bool rhsHasAssignment, int start, int divot, int end)
+ {
+ AssignResolveNode* node = new (m_globalData) AssignResolveNode(m_globalData, ident, rhs, rhsHasAssignment);
+ setExceptionLocation(node, start, divot, end);
+ return node;
+ }
+
+ ExpressionNode* createFunctionExpr(const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+ {
+ FuncExprNode* result = new (m_globalData) FuncExprNode(m_globalData, *name, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), parameters);
+ body->setLoc(bodyStartLine, bodyEndLine);
+ return result;
+ }
+
+ FunctionBodyNode* createFunctionBody()
+ {
+ usesClosures();
+ return FunctionBodyNode::create(m_globalData);
+ }
+
+ PropertyNode* createGetterOrSetterProperty(const Identifier* getOrSet, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+ {
+ ASSERT(name);
+ PropertyNode::Type type;
+ if (*getOrSet == "get")
+ type = PropertyNode::Getter;
+ else if (*getOrSet == "set")
+ type = PropertyNode::Setter;
+ else
+ return 0;
+ body->setLoc(bodyStartLine, bodyEndLine);
+ return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(m_globalData, m_globalData->propertyNames->nullIdentifier, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), params), type);
+ }
+
+
+ ArgumentsNode* createArguments() { return new (m_globalData) ArgumentsNode(m_globalData); }
+ ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_globalData) ArgumentsNode(m_globalData, args); }
+ ArgumentListNode* createArgumentsList(ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, arg); }
+ ArgumentListNode* createArgumentsList(ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, args, arg); }
+
+ PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); }
+ PropertyNode* createProperty(double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); }
+ PropertyListNode* createPropertyList(PropertyNode* property) { return new (m_globalData) PropertyListNode(m_globalData, property); }
+ PropertyListNode* createPropertyList(PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(m_globalData, property, tail); }
+
+ ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(m_globalData, elisions, expr); }
+ ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(m_globalData, elems, elisions, expr); }
+
+ ParameterNode* createFormalParameterList(const Identifier& ident) { return new (m_globalData) ParameterNode(m_globalData, ident); }
+ ParameterNode* createFormalParameterList(ParameterNode* list, const Identifier& ident) { return new (m_globalData) ParameterNode(m_globalData, list, ident); }
+
+ CaseClauseNode* createClause(ExpressionNode* expr, JSC::SourceElements* statements) { return new (m_globalData) CaseClauseNode(m_globalData, expr, statements); }
+ ClauseListNode* createClauseList(CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(m_globalData, clause); }
+ ClauseListNode* createClauseList(ClauseListNode* tail, CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(m_globalData, tail, clause); }
+
+ void setUsesArguments(FunctionBodyNode* node) { node->setUsesArguments(); }
+
+ StatementNode* createFuncDeclStatement(const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+ {
+ FuncDeclNode* decl = new (m_globalData) FuncDeclNode(m_globalData, *name, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), parameters);
+ if (*name == m_globalData->propertyNames->arguments)
+ usesArguments();
+ m_scopes.last().m_funcDeclarations->data.append(decl->body());
+ body->setLoc(bodyStartLine, bodyEndLine);
+ return decl;
+ }
+
+ StatementNode* createBlockStatement(JSC::SourceElements* elements, int startLine, int endLine)
+ {
+ BlockNode* block = new (m_globalData) BlockNode(m_globalData, elements);
+ block->setLoc(startLine, endLine);
+ return block;
+ }
+
+ StatementNode* createExprStatement(ExpressionNode* expr, int start, int end)
+ {
+ ExprStatementNode* result = new (m_globalData) ExprStatementNode(m_globalData, expr);
+ result->setLoc(start, end);
+ return result;
+ }
+
+ StatementNode* createIfStatement(ExpressionNode* condition, StatementNode* trueBlock, int start, int end)
+ {
+ IfNode* result = new (m_globalData) IfNode(m_globalData, condition, trueBlock);
+ result->setLoc(start, end);
+ return result;
+ }
+
+ StatementNode* createIfStatement(ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end)
+ {
+ IfNode* result = new (m_globalData) IfElseNode(m_globalData, condition, trueBlock, falseBlock);
+ result->setLoc(start, end);
+ return result;
+ }
+
+ StatementNode* createForLoop(ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, bool b, int start, int end)
+ {
+ ForNode* result = new (m_globalData) ForNode(m_globalData, initializer, condition, iter, statements, b);
+ result->setLoc(start, end);
+ return result;
+ }
+
+ StatementNode* createForInLoop(const Identifier* ident, ExpressionNode* initializer, ExpressionNode* iter, StatementNode* statements, int start, int divot, int end, int initStart, int initEnd, int startLine, int endLine)
+ {
+ ForInNode* result = new (m_globalData) ForInNode(m_globalData, *ident, initializer, iter, statements, initStart, initStart - start, initEnd - initStart);
+ result->setLoc(startLine, endLine);
+ setExceptionLocation(result, start, divot + 1, end);
+ return result;
+ }
+
+ StatementNode* createForInLoop(ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, int eStart, int eDivot, int eEnd, int start, int end)
+ {
+ ForInNode* result = new (m_globalData) ForInNode(m_globalData, lhs, iter, statements);
+ result->setLoc(start, end);
+ setExceptionLocation(result, eStart, eDivot, eEnd);
+ return result;
+ }
+
+ StatementNode* createEmptyStatement() { return new (m_globalData) EmptyStatementNode(m_globalData); }
+
+ StatementNode* createVarStatement(ExpressionNode* expr, int start, int end)
+ {
+ StatementNode* result;
+ if (!expr)
+ result = new (m_globalData) EmptyStatementNode(m_globalData);
+ else
+ result = new (m_globalData) VarStatementNode(m_globalData, expr);
+ result->setLoc(start, end);
+ return result;
+ }
+
+ StatementNode* createReturnStatement(ExpressionNode* expression, int eStart, int eEnd, int startLine, int endLine)
+ {
+ ReturnNode* result = new (m_globalData) ReturnNode(m_globalData, expression);
+ setExceptionLocation(result, eStart, eEnd, eEnd);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createBreakStatement(int eStart, int eEnd, int startLine, int endLine)
+ {
+ BreakNode* result = new (m_globalData) BreakNode(m_globalData);
+ setExceptionLocation(result, eStart, eEnd, eEnd);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createBreakStatement(const Identifier* ident, int eStart, int eEnd, int startLine, int endLine)
+ {
+ BreakNode* result = new (m_globalData) BreakNode(m_globalData, *ident);
+ setExceptionLocation(result, eStart, eEnd, eEnd);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createContinueStatement(int eStart, int eEnd, int startLine, int endLine)
+ {
+ ContinueNode* result = new (m_globalData) ContinueNode(m_globalData);
+ setExceptionLocation(result, eStart, eEnd, eEnd);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createContinueStatement(const Identifier* ident, int eStart, int eEnd, int startLine, int endLine)
+ {
+ ContinueNode* result = new (m_globalData) ContinueNode(m_globalData, *ident);
+ setExceptionLocation(result, eStart, eEnd, eEnd);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createTryStatement(StatementNode* tryBlock, const Identifier* ident, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
+ {
+ TryNode* result = new (m_globalData) TryNode(m_globalData, tryBlock, *ident, catchHasEval, catchBlock, finallyBlock);
+ if (catchBlock)
+ usesCatch();
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createSwitchStatement(ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine)
+ {
+ CaseBlockNode* cases = new (m_globalData) CaseBlockNode(m_globalData, firstClauses, defaultClause, secondClauses);
+ SwitchNode* result = new (m_globalData) SwitchNode(m_globalData, expr, cases);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createWhileStatement(ExpressionNode* expr, StatementNode* statement, int startLine, int endLine)
+ {
+ WhileNode* result = new (m_globalData) WhileNode(m_globalData, expr, statement);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createDoWhileStatement(StatementNode* statement, ExpressionNode* expr, int startLine, int endLine)
+ {
+ DoWhileNode* result = new (m_globalData) DoWhileNode(m_globalData, statement, expr);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createLabelStatement(const Identifier* ident, StatementNode* statement, int start, int end)
+ {
+ LabelNode* result = new (m_globalData) LabelNode(m_globalData, *ident, statement);
+ setExceptionLocation(result, start, end, end);
+ return result;
+ }
+
+ StatementNode* createWithStatement(ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine)
+ {
+ usesWith();
+ WithNode* result = new (m_globalData) WithNode(m_globalData, expr, statement, end, end - start);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createThrowStatement(ExpressionNode* expr, int start, int end, int startLine, int endLine)
+ {
+ ThrowNode* result = new (m_globalData) ThrowNode(m_globalData, expr);
+ result->setLoc(startLine, endLine);
+ setExceptionLocation(result, start, end, end);
+ return result;
+ }
+
+ StatementNode* createDebugger(int startLine, int endLine)
+ {
+ DebuggerStatementNode* result = new (m_globalData) DebuggerStatementNode(m_globalData);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ StatementNode* createConstStatement(ConstDeclNode* decls, int startLine, int endLine)
+ {
+ ConstStatementNode* result = new (m_globalData) ConstStatementNode(m_globalData, decls);
+ result->setLoc(startLine, endLine);
+ return result;
+ }
+
+ ConstDeclNode* appendConstDecl(ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer)
+ {
+ ConstDeclNode* result = new (m_globalData) ConstDeclNode(m_globalData, *name, initializer);
+ if (tail)
+ tail->m_next = result;
+ return result;
+ }
+
+ void appendStatement(JSC::SourceElements* elements, JSC::StatementNode* statement)
+ {
+ elements->append(statement);
+ }
+
+ void addVar(const Identifier* ident, int attrs)
+ {
+ if (m_globalData->propertyNames->arguments == *ident)
+ usesArguments();
+ m_scopes.last().m_varDeclarations->data.append(std::make_pair(ident, attrs));
+ }
+
+ ExpressionNode* combineCommaNodes(ExpressionNode* list, ExpressionNode* init)
+ {
+ if (!list)
+ return init;
+ if (list->isCommaNode()) {
+ static_cast<CommaNode*>(list)->append(init);
+ return list;
+ }
+ return new (m_globalData) CommaNode(m_globalData, list, init);
+ }
+
+ int evalCount() const { return m_evalCount; }
+
+ void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, int exprStart, int lhs, int rhs, bool hasAssignments)
+ {
+ operandStackDepth++;
+ m_binaryOperandStack.append(std::make_pair(current, BinaryOpInfo(exprStart, lhs, rhs, hasAssignments)));
+ }
+
+ // Logic to handle datastructures used during parsing of binary expressions
+ void operatorStackPop(int& operatorStackDepth)
+ {
+ operatorStackDepth--;
+ m_binaryOperatorStack.removeLast();
+ }
+ bool operatorStackHasHigherPrecedence(int&, int precedence)
+ {
+ return precedence <= m_binaryOperatorStack.last().second;
+ }
+ const BinaryOperand& getFromOperandStack(int i) { return m_binaryOperandStack[m_binaryOperandStack.size() + i]; }
+ void shrinkOperandStackBy(int& operandStackDepth, int amount)
+ {
+ operandStackDepth -= amount;
+ ASSERT(operandStackDepth >= 0);
+ m_binaryOperandStack.resize(m_binaryOperandStack.size() - amount);
+ }
+ void appendBinaryOperation(int& operandStackDepth, int&, const BinaryOperand& lhs, const BinaryOperand& rhs)
+ {
+ operandStackDepth++;
+ m_binaryOperandStack.append(std::make_pair(makeBinaryNode(m_binaryOperatorStack.last().first, lhs, rhs), BinaryOpInfo(lhs.second, rhs.second)));
+ }
+ void operatorStackAppend(int& operatorStackDepth, int op, int precedence)
+ {
+ operatorStackDepth++;
+ m_binaryOperatorStack.append(std::make_pair(op, precedence));
+ }
+ ExpressionNode* popOperandStack(int&)
+ {
+ ExpressionNode* result = m_binaryOperandStack.last().first;
+ m_binaryOperandStack.removeLast();
+ return result;
+ }
+
+ void appendUnaryToken(int& tokenStackDepth, int type, int start)
+ {
+ tokenStackDepth++;
+ m_unaryTokenStack.append(std::make_pair(type, start));
+ }
+
+ int unaryTokenStackLastType(int&)
+ {
+ return m_unaryTokenStack.last().first;
+ }
+
+ int unaryTokenStackLastStart(int&)
+ {
+ return m_unaryTokenStack.last().second;
+ }
+
+ void unaryTokenStackRemoveLast(int& tokenStackDepth)
+ {
+ tokenStackDepth--;
+ m_unaryTokenStack.removeLast();
+ }
+
+ void assignmentStackAppend(int& assignmentStackDepth, ExpressionNode* node, int start, int divot, int assignmentCount, Operator op)
+ {
+ assignmentStackDepth++;
+ m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, assignmentCount, op));
+ }
+
+ ExpressionNode* createAssignment(int& assignmentStackDepth, ExpressionNode* rhs, int initialAssignmentCount, int currentAssignmentCount, int lastTokenEnd)
+ {
+ ExpressionNode* result = makeAssignNode(m_assignmentInfoStack.last().m_node, m_assignmentInfoStack.last().m_op, rhs, m_assignmentInfoStack.last().m_initAssignments != initialAssignmentCount, m_assignmentInfoStack.last().m_initAssignments != currentAssignmentCount, m_assignmentInfoStack.last().m_start, m_assignmentInfoStack.last().m_divot + 1, lastTokenEnd);
+ m_assignmentInfoStack.removeLast();
+ assignmentStackDepth--;
+ return result;
+ }
+
+private:
+ struct Scope {
+ Scope(JSGlobalData* globalData)
+ : m_varDeclarations(new (globalData) ParserArenaData<DeclarationStacks::VarStack>)
+ , m_funcDeclarations(new (globalData) ParserArenaData<DeclarationStacks::FunctionStack>)
+ , m_features(0)
+ , m_numConstants(0)
+ {
+ }
+ ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
+ ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
+ int m_features;
+ int m_numConstants;
+ };
+
+ static void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end)
+ {
+ node->setExceptionSourceCode(divot, divot - start, end - divot);
+ }
+
+ void incConstants() { m_scopes.last().m_numConstants++; }
+ void usesThis() { m_scopes.last().m_features |= ThisFeature; }
+ void usesCatch() { m_scopes.last().m_features |= CatchFeature; }
+ void usesClosures() { m_scopes.last().m_features |= ClosureFeature; }
+ void usesArguments() { m_scopes.last().m_features |= ArgumentsFeature; }
+ void usesAssignment() { m_scopes.last().m_features |= AssignFeature; }
+ void usesWith() { m_scopes.last().m_features |= WithFeature; }
+ void usesEval()
+ {
+ m_evalCount++;
+ m_scopes.last().m_features |= EvalFeature;
+ }
+ ExpressionNode* createNumber(double d)
+ {
+ return new (m_globalData) NumberNode(m_globalData, d);
+ }
+
+ JSGlobalData* m_globalData;
+ Lexer* m_lexer;
+ Vector<Scope> m_scopes;
+ Vector<BinaryOperand, 10> m_binaryOperandStack;
+ Vector<AssignmentInfo, 10> m_assignmentInfoStack;
+ Vector<pair<int, int>, 10> m_binaryOperatorStack;
+ Vector<pair<int, int>, 10> m_unaryTokenStack;
+ int m_evalCount;
+};
+
+ExpressionNode* ASTBuilder::makeTypeOfNode(ExpressionNode* expr)
+{
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new (m_globalData) TypeOfResolveNode(m_globalData, resolve->identifier());
+ }
+ return new (m_globalData) TypeOfValueNode(m_globalData, expr);
+}
+
+ExpressionNode* ASTBuilder::makeDeleteNode(ExpressionNode* expr, int start, int divot, int end)
+{
+ if (!expr->isLocation())
+ return new (m_globalData) DeleteValueNode(m_globalData, expr);
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new (m_globalData) DeleteResolveNode(m_globalData, resolve->identifier(), divot, divot - start, end - divot);
+ }
+ if (expr->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+ return new (m_globalData) DeleteBracketNode(m_globalData, bracket->base(), bracket->subscript(), divot, divot - start, end - divot);
+ }
+ ASSERT(expr->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+ return new (m_globalData) DeleteDotNode(m_globalData, dot->base(), dot->identifier(), divot, divot - start, end - divot);
+}
+
+ExpressionNode* ASTBuilder::makeNegateNode(ExpressionNode* n)
+{
+ if (n->isNumber()) {
+ NumberNode* numberNode = static_cast<NumberNode*>(n);
+ numberNode->setValue(-numberNode->value());
+ return numberNode;
+ }
+
+ return new (m_globalData) NegateNode(m_globalData, n);
+}
+
+ExpressionNode* ASTBuilder::makeBitwiseNotNode(ExpressionNode* expr)
+{
+ if (expr->isNumber())
+ return createNumber(~toInt32(static_cast<NumberNode*>(expr)->value()));
+ return new (m_globalData) BitwiseNotNode(m_globalData, expr);
+}
+
+ExpressionNode* ASTBuilder::makeMultNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ expr1 = expr1->stripUnaryPlus();
+ expr2 = expr2->stripUnaryPlus();
+
+ if (expr1->isNumber() && expr2->isNumber())
+ return createNumber(static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
+
+ if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
+ return new (m_globalData) UnaryPlusNode(m_globalData, expr2);
+
+ if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
+ return new (m_globalData) UnaryPlusNode(m_globalData, expr1);
+
+ return new (m_globalData) MultNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeDivNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ expr1 = expr1->stripUnaryPlus();
+ expr2 = expr2->stripUnaryPlus();
+
+ if (expr1->isNumber() && expr2->isNumber())
+ return createNumber(static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value());
+ return new (m_globalData) DivNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeAddNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ if (expr1->isNumber() && expr2->isNumber())
+ return createNumber(static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value());
+ return new (m_globalData) AddNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeSubNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ expr1 = expr1->stripUnaryPlus();
+ expr2 = expr2->stripUnaryPlus();
+
+ if (expr1->isNumber() && expr2->isNumber())
+ return createNumber(static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value());
+ return new (m_globalData) SubNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeLeftShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ if (expr1->isNumber() && expr2->isNumber())
+ return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+ return new (m_globalData) LeftShiftNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeRightShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ if (expr1->isNumber() && expr2->isNumber())
+ return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+ return new (m_globalData) RightShiftNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end)
+{
+ if (!func->isLocation())
+ return new (m_globalData) FunctionCallValueNode(m_globalData, func, args, divot, divot - start, end - divot);
+ if (func->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(func);
+ const Identifier& identifier = resolve->identifier();
+ if (identifier == m_globalData->propertyNames->eval) {
+ usesEval();
+ return new (m_globalData) EvalFunctionCallNode(m_globalData, args, divot, divot - start, end - divot);
+ }
+ return new (m_globalData) FunctionCallResolveNode(m_globalData, identifier, args, divot, divot - start, end - divot);
+ }
+ if (func->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func);
+ FunctionCallBracketNode* node = new (m_globalData) FunctionCallBracketNode(m_globalData, bracket->base(), bracket->subscript(), args, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+ return node;
+ }
+ ASSERT(func->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(func);
+ FunctionCallDotNode* node;
+ if (dot->identifier() == m_globalData->propertyNames->call)
+ node = new (m_globalData) CallFunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
+ else if (dot->identifier() == m_globalData->propertyNames->apply)
+ node = new (m_globalData) ApplyFunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
+ else
+ node = new (m_globalData) FunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+ return node;
+}
+
+ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, BinaryOpInfo> lhs, pair<ExpressionNode*, BinaryOpInfo> rhs)
+{
+ switch (token) {
+ case OR:
+ return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalOr);
+
+ case AND:
+ return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalAnd);
+
+ case '|':
+ return new (m_globalData) BitOrNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case '^':
+ return new (m_globalData) BitXOrNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case '&':
+ return new (m_globalData) BitAndNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case EQEQ:
+ return new (m_globalData) EqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case NE:
+ return new (m_globalData) NotEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case STREQ:
+ return new (m_globalData) StrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case STRNEQ:
+ return new (m_globalData) NotStrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case '<':
+ return new (m_globalData) LessNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case '>':
+ return new (m_globalData) GreaterNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case LE:
+ return new (m_globalData) LessEqNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case GE:
+ return new (m_globalData) GreaterEqNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case INSTANCEOF: {
+ InstanceOfNode* node = new (m_globalData) InstanceOfNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+ setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end);
+ return node;
+ }
+
+ case INTOKEN: {
+ InNode* node = new (m_globalData) InNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+ setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end);
+ return node;
+ }
+
+ case LSHIFT:
+ return makeLeftShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case RSHIFT:
+ return makeRightShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case URSHIFT:
+ return new (m_globalData) UnsignedRightShiftNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case '+':
+ return makeAddNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case '-':
+ return makeSubNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case '*':
+ return makeMultNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case '/':
+ return makeDivNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case '%':
+ return new (m_globalData) ModNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+ }
+ CRASH();
+ return 0;
+}
+
+ExpressionNode* ASTBuilder::makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
+{
+ usesAssignment();
+ if (!loc->isLocation())
+ return new (m_globalData) AssignErrorNode(m_globalData, loc, op, expr, divot, divot - start, end - divot);
+
+ if (loc->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(loc);
+ if (op == OpEqual) {
+ AssignResolveNode* node = new (m_globalData) AssignResolveNode(m_globalData, resolve->identifier(), expr, exprHasAssignments);
+ setExceptionLocation(node, start, divot, end);
+ return node;
+ }
+ return new (m_globalData) ReadModifyResolveNode(m_globalData, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+ }
+ if (loc->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
+ if (op == OpEqual)
+ return new (m_globalData) AssignBracketNode(m_globalData, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot());
+ ReadModifyBracketNode* node = new (m_globalData) ReadModifyBracketNode(m_globalData, 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 (m_globalData) AssignDotNode(m_globalData, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
+
+ ReadModifyDotNode* node = new (m_globalData) ReadModifyDotNode(m_globalData, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+ return node;
+}
+
+ExpressionNode* ASTBuilder::makePrefixNode(ExpressionNode* expr, Operator op, int start, int divot, int end)
+{
+ usesAssignment();
+ if (!expr->isLocation())
+ return new (m_globalData) PrefixErrorNode(m_globalData, expr, op, divot, divot - start, end - divot);
+
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new (m_globalData) PrefixResolveNode(m_globalData, resolve->identifier(), op, divot, divot - start, end - divot);
+ }
+ if (expr->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+ PrefixBracketNode* node = new (m_globalData) PrefixBracketNode(m_globalData, 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 (m_globalData) PrefixDotNode(m_globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->startOffset());
+ return node;
+}
+
+ExpressionNode* ASTBuilder::makePostfixNode(ExpressionNode* expr, Operator op, int start, int divot, int end)
+{
+ usesAssignment();
+ if (!expr->isLocation())
+ return new (m_globalData) PostfixErrorNode(m_globalData, expr, op, divot, divot - start, end - divot);
+
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new (m_globalData) PostfixResolveNode(m_globalData, resolve->identifier(), op, divot, divot - start, end - divot);
+ }
+ if (expr->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+ PostfixBracketNode* node = new (m_globalData) PostfixBracketNode(m_globalData, 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 (m_globalData) PostfixDotNode(m_globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+ return node;
+}
+
+}
+
+#endif
diff --git a/JavaScriptCore/parser/JSParser.cpp b/JavaScriptCore/parser/JSParser.cpp
new file mode 100644
index 0000000..1934c0c
--- /dev/null
+++ b/JavaScriptCore/parser/JSParser.cpp
@@ -0,0 +1,1504 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(RECURSIVE_PARSE)
+#include "JSParser.h"
+
+using namespace JSC;
+
+#include "JSGlobalData.h"
+#include "NodeInfo.h"
+#include "Grammar.h"
+#include "ASTBuilder.h"
+#include <utility>
+
+using namespace std;
+
+namespace JSC {
+#define fail() do { m_error = true; return 0; } while (0)
+#define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
+#define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
+#define consumeOrFail(tokenType) do { if (!consume(tokenType)) fail(); } while (0)
+#define matchOrFail(tokenType) do { if (!match(tokenType)) fail(); } while (0)
+#define failIfStackOverflow() do { failIfFalse(canRecurse()); } while (0)
+
+// Macros to make the more common TreeBuilder types a little less verbose
+#define TreeStatement typename TreeBuilder::Statement
+#define TreeExpression typename TreeBuilder::Expression
+#define TreeFormalParameterList typename TreeBuilder::FormalParameterList
+#define TreeSourceElements typename TreeBuilder::SourceElements
+#define TreeClause typename TreeBuilder::Clause
+#define TreeClauseList typename TreeBuilder::ClauseList
+#define TreeConstDeclList typename TreeBuilder::ConstDeclList
+#define TreeArguments typename TreeBuilder::Arguments
+#define TreeArgumentsList typename TreeBuilder::ArgumentsList
+#define TreeFunctionBody typename TreeBuilder::FunctionBody
+#define TreeProperty typename TreeBuilder::Property
+#define TreePropertyList typename TreeBuilder::PropertyList
+
+// This matches v8
+static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024;
+
+class JSParser {
+public:
+ JSParser(Lexer*, JSGlobalData*);
+ bool parseProgram();
+private:
+ struct AllowInOverride {
+ AllowInOverride(JSParser* parser)
+ : m_parser(parser)
+ , m_oldAllowsIn(parser->m_allowsIn)
+ {
+ parser->m_allowsIn = true;
+ }
+ ~AllowInOverride()
+ {
+ m_parser->m_allowsIn = m_oldAllowsIn;
+ }
+ JSParser* m_parser;
+ bool m_oldAllowsIn;
+ };
+
+ const JSToken& token() { return m_token; }
+ void next()
+ {
+ m_lastLine = token().m_info.last_line;
+ m_lastTokenEnd = token().m_info.last_column;
+ m_lexer->setLastLineNumber(m_lastLine);
+ m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info);
+ m_tokenCount++;
+ }
+
+ bool consume(int expected)
+ {
+ bool result = m_token.m_type == expected;
+ failIfFalse(result);
+ next();
+ return result;
+ }
+
+ bool match(int expected)
+ {
+ return m_token.m_type == expected;
+ }
+
+ int tokenStart()
+ {
+ return token().m_info.first_column;
+ }
+
+ int tokenLine()
+ {
+ return token().m_info.first_line;
+ }
+
+ int tokenEnd()
+ {
+ return token().m_info.last_column;
+ }
+
+ template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseBreakStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseContinueStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseReturnStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseThrowStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseWithStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseSwitchStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeClauseList parseSwitchClauses(TreeBuilder&);
+ template <class TreeBuilder> TreeClause parseSwitchDefaultClause(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseTryStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseDebuggerStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeStatement parseBlockStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&);
+ template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseBinaryExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseUnaryExpression(TreeBuilder&);
+ template <class TreeBuilder> TreeExpression parseMemberExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&, bool& usesArguments);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd);
+ template <class TreeBuilder> ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context);
+ enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
+ template <FunctionRequirements, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine);
+ int isBinaryOperator(int token);
+ bool allowAutomaticSemicolon();
+
+ bool autoSemiColon()
+ {
+ if (token().m_type == ';') {
+ next();
+ return true;
+ }
+ return allowAutomaticSemicolon();
+ }
+
+ bool canRecurse()
+ {
+ char sample = 0;
+ ASSERT(m_endAddress);
+ return &sample > m_endAddress;
+ }
+
+ int lastTokenEnd() const
+ {
+ return m_lastTokenEnd;
+ }
+
+ ParserArena m_arena;
+ Lexer* m_lexer;
+ char* m_endAddress;
+ bool m_error;
+ JSGlobalData* m_globalData;
+ JSToken m_token;
+ bool m_allowsIn;
+ int m_tokenCount;
+ int m_lastLine;
+ int m_lastTokenEnd;
+ int m_assignmentCount;
+ int m_nonLHSCount;
+};
+
+int jsParse(JSGlobalData* globalData)
+{
+ JSParser parser(globalData->lexer, globalData);
+ return parser.parseProgram();
+}
+
+JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData)
+ : m_lexer(lexer)
+ , m_endAddress(0)
+ , m_error(false)
+ , m_globalData(globalData)
+ , m_allowsIn(true)
+ , m_tokenCount(0)
+ , m_lastLine(0)
+ , m_lastTokenEnd(0)
+ , m_assignmentCount(0)
+ , m_nonLHSCount(0)
+{
+ m_endAddress = *(globalData->stackGuards);
+ if (!m_endAddress) {
+ char sample = 0;
+ m_endAddress = &sample - kMaxParserStackUsage;
+ *(globalData->stackGuards) = m_endAddress;
+ }
+ next();
+ m_lexer->setLastLineNumber(tokenLine());
+}
+
+bool JSParser::parseProgram()
+{
+ ASTBuilder context(m_globalData, m_lexer);
+ SourceElements* sourceElements = parseSourceElements<ASTBuilder>(context);
+ if (!sourceElements || !consume(0))
+ return true;
+ m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features(),
+ m_lastLine, context.numConstants());
+ return false;
+}
+
+bool JSParser::allowAutomaticSemicolon()
+{
+ return match(CLOSEBRACE) || match(0) || m_lexer->prevTerminator();
+}
+
+template <class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context)
+{
+ TreeSourceElements sourceElements = context.createSourceElements();
+ while (TreeStatement statement = parseStatement(context))
+ context.appendStatement(sourceElements, statement);
+
+ if (m_error)
+ fail();
+ return sourceElements;
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseVarDeclaration(TreeBuilder& context)
+{
+ ASSERT(match(VAR));
+ int start = tokenLine();
+ int end = 0;
+ int scratch;
+ const Identifier* scratch1 = 0;
+ TreeExpression scratch2 = 0;
+ int scratch3 = 0;
+ TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3);
+ failIfTrue(m_error);
+ failIfFalse(autoSemiColon());
+
+ return context.createVarStatement(varDecls, start, end);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseConstDeclaration(TreeBuilder& context)
+{
+ ASSERT(match(CONSTTOKEN));
+ int start = tokenLine();
+ int end = 0;
+ TreeConstDeclList constDecls = parseConstDeclarationList(context);
+ failIfTrue(m_error);
+ failIfFalse(autoSemiColon());
+
+ return context.createConstStatement(constDecls, start, end);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseDoWhileStatement(TreeBuilder& context)
+{
+ ASSERT(match(DO));
+ int startLine = tokenLine();
+ next();
+ TreeStatement statement = parseStatement(context);
+ failIfFalse(statement);
+ int endLine = tokenLine();
+ consumeOrFail(WHILE);
+ consumeOrFail('(');
+ TreeExpression expr = parseExpression(context);
+ failIfFalse(expr);
+ consumeOrFail(')');
+ if (match(';'))
+ next(); // Always performs automatic semicolon insertion.
+ return context.createDoWhileStatement(statement, expr, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseWhileStatement(TreeBuilder& context)
+{
+ ASSERT(match(WHILE));
+ int startLine = tokenLine();
+ next();
+ consumeOrFail('(');
+ TreeExpression expr = parseExpression(context);
+ failIfFalse(expr);
+ int endLine = tokenLine();
+ consumeOrFail(')');
+ TreeStatement statement = parseStatement(context);
+ failIfFalse(statement);
+ return context.createWhileStatement(expr, statement, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(TreeBuilder& context, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd)
+{
+ TreeExpression varDecls = 0;
+ do {
+ declarations++;
+ next();
+ matchOrFail(IDENT);
+
+ int varStart = tokenStart();
+ identStart = varStart;
+ const Identifier* name = token().m_data.ident;
+ lastIdent = name;
+ next();
+ bool hasInitializer = match('=');
+ context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
+ if (hasInitializer) {
+ int varDivot = tokenStart() + 1;
+ initStart = tokenStart();
+ next(); // consume '='
+ int initialAssignments = m_assignmentCount;
+ TreeExpression initializer = parseAssignmentExpression(context);
+ initEnd = lastTokenEnd();
+ lastInitializer = initializer;
+ failIfFalse(initializer);
+
+ TreeExpression node = context.createAssignResolve(*name, initializer, initialAssignments != m_assignmentCount, varStart, varDivot, lastTokenEnd());
+ if (!varDecls)
+ varDecls = node;
+ else
+ varDecls = context.combineCommaNodes(varDecls, node);
+ }
+ } while (match(','));
+ return varDecls;
+}
+
+template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationList(TreeBuilder& context)
+{
+ TreeConstDeclList constDecls = 0;
+ TreeConstDeclList tail = 0;
+ do {
+ next();
+ matchOrFail(IDENT);
+ const Identifier* name = token().m_data.ident;
+ next();
+ bool hasInitializer = match('=');
+ context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
+ TreeExpression initializer = 0;
+ if (hasInitializer) {
+ next(); // consume '='
+ initializer = parseAssignmentExpression(context);
+ }
+ tail = context.appendConstDecl(tail, name, initializer);
+ if (!constDecls)
+ constDecls = tail;
+ } while (match(','));
+ return constDecls;
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuilder& context)
+{
+ ASSERT(match(FOR));
+ int startLine = tokenLine();
+ next();
+ consumeOrFail('(');
+ int nonLHSCount = m_nonLHSCount;
+ int declarations = 0;
+ int declsStart = 0;
+ int declsEnd = 0;
+ TreeExpression decls = 0;
+ bool hasDeclaration = false;
+ if (match(VAR)) {
+ /*
+ for (var IDENT in expression) statement
+ for (var IDENT = expression in expression) statement
+ for (var varDeclarationList; expressionOpt; expressionOpt)
+ */
+ hasDeclaration = true;
+ const Identifier* forInTarget = 0;
+ TreeExpression forInInitializer = 0;
+ m_allowsIn = false;
+ int initStart = 0;
+ int initEnd = 0;
+ decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd);
+ m_allowsIn = true;
+ if (m_error)
+ fail();
+
+ // Remainder of a standard for loop is handled identically
+ if (declarations > 1 || match(';'))
+ goto standardForLoop;
+
+ // Handle for-in with var declaration
+ int inLocation = tokenStart();
+ if (!consume(INTOKEN))
+ fail();
+
+ TreeExpression expr = parseExpression(context);
+ failIfFalse(expr);
+ int exprEnd = lastTokenEnd();
+
+ int endLine = tokenLine();
+ consumeOrFail(')');
+
+ TreeStatement statement = parseStatement(context);
+ failIfFalse(statement);
+
+ return context.createForInLoop(forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine);
+ }
+
+ if (!match(';')) {
+ m_allowsIn = false;
+ declsStart = tokenStart();
+ decls = parseExpression(context);
+ declsEnd = lastTokenEnd();
+ m_allowsIn = true;
+ failIfFalse(decls);
+ }
+
+ if (match(';')) {
+ standardForLoop:
+ // Standard for loop
+ next();
+ TreeExpression condition = 0;
+
+ if (!match(';')) {
+ condition = parseExpression(context);
+ failIfFalse(condition);
+ }
+ consumeOrFail(';');
+
+ TreeExpression increment = 0;
+ if (!match(')')) {
+ increment = parseExpression(context);
+ failIfFalse(increment);
+ }
+ int endLine = tokenLine();
+ consumeOrFail(')');
+ TreeStatement statement = parseStatement(context);
+ failIfFalse(statement);
+ return context.createForLoop(decls, condition, increment, statement, hasDeclaration, startLine, endLine);
+ }
+
+ // For-in loop
+ failIfFalse(nonLHSCount == m_nonLHSCount);
+ consumeOrFail(INTOKEN);
+ TreeExpression expr = parseExpression(context);
+ failIfFalse(expr);
+ int exprEnd = lastTokenEnd();
+ int endLine = tokenLine();
+ consumeOrFail(')');
+ TreeStatement statement = parseStatement(context);
+ failIfFalse(statement);
+
+ return context.createForInLoop(decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseBreakStatement(TreeBuilder& context)
+{
+ ASSERT(match(BREAK));
+ int startCol = tokenStart();
+ int endCol = tokenEnd();
+ int startLine = tokenLine();
+ int endLine = tokenLine();
+ next();
+
+ if (autoSemiColon())
+ return context.createBreakStatement(startCol, endCol, startLine, endLine);
+ matchOrFail(IDENT);
+ const Identifier* ident = token().m_data.ident;
+ endCol = tokenEnd();
+ endLine = tokenLine();
+ next();
+ failIfFalse(autoSemiColon());
+ return context.createBreakStatement(ident, startCol, endCol, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseContinueStatement(TreeBuilder& context)
+{
+ ASSERT(match(CONTINUE));
+ int startCol = tokenStart();
+ int endCol = tokenEnd();
+ int startLine = tokenLine();
+ int endLine = tokenLine();
+ next();
+
+ if (autoSemiColon())
+ return context.createContinueStatement(startCol, endCol, startLine, endLine);
+ matchOrFail(IDENT);
+ const Identifier* ident = token().m_data.ident;
+ endCol = tokenEnd();
+ endLine = tokenLine();
+ next();
+ failIfFalse(autoSemiColon());
+ return context.createContinueStatement(ident, startCol, endCol, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBuilder& context)
+{
+ ASSERT(match(RETURN));
+ int startLine = tokenLine();
+ int endLine = startLine;
+ int start = tokenStart();
+ int end = tokenEnd();
+ next();
+ // We do the auto semicolon check before attempting to parse an expression
+ // as we need to ensure the a line break after the return correctly terminates
+ // the statement
+ if (match(';'))
+ endLine = tokenLine();
+ if (autoSemiColon())
+ return context.createReturnStatement(0, start, end, startLine, endLine);
+ TreeExpression expr = parseExpression(context);
+ failIfFalse(expr);
+ end = lastTokenEnd();
+ if (match(';'))
+ endLine = tokenLine();
+ failIfFalse(autoSemiColon());
+ return context.createReturnStatement(expr, start, end, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseThrowStatement(TreeBuilder& context)
+{
+ ASSERT(match(THROW));
+ int eStart = tokenStart();
+ int startLine = tokenLine();
+ next();
+
+ TreeExpression expr = parseExpression(context);
+ failIfFalse(expr);
+ int eEnd = lastTokenEnd();
+ int endLine = tokenLine();
+ failIfFalse(autoSemiColon());
+
+ return context.createThrowStatement(expr, eStart, eEnd, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuilder& context)
+{
+ ASSERT(match(WITH));
+ int startLine = tokenLine();
+ next();
+ consumeOrFail('(');
+ int start = tokenStart();
+ TreeExpression expr = parseExpression(context);
+ failIfFalse(expr);
+ int end = lastTokenEnd();
+
+ int endLine = tokenLine();
+ consumeOrFail(')');
+
+ TreeStatement statement = parseStatement(context);
+ failIfFalse(statement);
+
+ return context.createWithStatement(expr, statement, start, end, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseSwitchStatement(TreeBuilder& context)
+{
+ ASSERT(match(SWITCH));
+ int startLine = tokenLine();
+ next();
+ consumeOrFail('(');
+ TreeExpression expr = parseExpression(context);
+ failIfFalse(expr);
+ int endLine = tokenLine();
+ consumeOrFail(')');
+ consumeOrFail(OPENBRACE);
+
+ TreeClauseList firstClauses = parseSwitchClauses(context);
+ failIfTrue(m_error);
+
+ TreeClause defaultClause = parseSwitchDefaultClause(context);
+ failIfTrue(m_error);
+
+ TreeClauseList secondClauses = parseSwitchClauses(context);
+ failIfTrue(m_error);
+ consumeOrFail(CLOSEBRACE);
+
+ return context.createSwitchStatement(expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
+
+}
+
+template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBuilder& context)
+{
+ if (!match(CASE))
+ return 0;
+ next();
+ TreeExpression condition = parseExpression(context);
+ failIfFalse(condition);
+ consumeOrFail(':');
+ TreeSourceElements statements = parseSourceElements(context);
+ failIfFalse(statements);
+ TreeClause clause = context.createClause(condition, statements);
+ TreeClauseList clauseList = context.createClauseList(clause);
+ TreeClauseList tail = clauseList;
+
+ while (match(CASE)) {
+ next();
+ TreeExpression condition = parseExpression(context);
+ failIfFalse(condition);
+ consumeOrFail(':');
+ TreeSourceElements statements = parseSourceElements(context);
+ failIfFalse(statements);
+ clause = context.createClause(condition, statements);
+ tail = context.createClauseList(tail, clause);
+ }
+ return clauseList;
+}
+
+template <class TreeBuilder> TreeClause JSParser::parseSwitchDefaultClause(TreeBuilder& context)
+{
+ if (!match(DEFAULT))
+ return 0;
+ next();
+ consumeOrFail(':');
+ TreeSourceElements statements = parseSourceElements(context);
+ failIfFalse(statements);
+ return context.createClause(0, statements);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuilder& context)
+{
+ ASSERT(match(TRY));
+ TreeStatement tryBlock = 0;
+ const Identifier* ident = &m_globalData->propertyNames->nullIdentifier;
+ bool catchHasEval = false;
+ TreeStatement catchBlock = 0;
+ TreeStatement finallyBlock = 0;
+ int firstLine = tokenLine();
+ next();
+ matchOrFail(OPENBRACE);
+
+ tryBlock = parseBlockStatement(context);
+ failIfFalse(tryBlock);
+ int lastLine = m_lastLine;
+
+ if (match(CATCH)) {
+ next();
+ consumeOrFail('(');
+ matchOrFail(IDENT);
+ ident = token().m_data.ident;
+ next();
+ consumeOrFail(')');
+ matchOrFail(OPENBRACE);
+ int initialEvalCount = context.evalCount();
+ catchBlock = parseBlockStatement(context);
+ failIfFalse(catchBlock);
+ catchHasEval = initialEvalCount != context.evalCount();
+ }
+
+ if (match(FINALLY)) {
+ next();
+ matchOrFail(OPENBRACE);
+ finallyBlock = parseBlockStatement(context);
+ failIfFalse(finallyBlock);
+ }
+ failIfFalse(catchBlock || finallyBlock);
+ return context.createTryStatement(tryBlock, ident, catchHasEval, catchBlock, finallyBlock, firstLine, lastLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseDebuggerStatement(TreeBuilder& context)
+{
+ ASSERT(match(DEBUGGER));
+ int startLine = tokenLine();
+ int endLine = startLine;
+ next();
+ if (match(';'))
+ startLine = tokenLine();
+ failIfFalse(autoSemiColon());
+ return context.createDebugger(startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseBlockStatement(TreeBuilder& context)
+{
+ ASSERT(match(OPENBRACE));
+ int start = tokenLine();
+ next();
+ if (match(CLOSEBRACE)) {
+ next();
+ return context.createBlockStatement(0, start, m_lastLine);
+ }
+ TreeSourceElements subtree = parseSourceElements(context);
+ failIfFalse(subtree);
+ matchOrFail(CLOSEBRACE);
+ next();
+ return context.createBlockStatement(subtree, start, m_lastLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& context)
+{
+ failIfStackOverflow();
+ switch (token().m_type) {
+ case OPENBRACE:
+ return parseBlockStatement(context);
+ case VAR:
+ return parseVarDeclaration(context);
+ case CONSTTOKEN:
+ return parseConstDeclaration(context);
+ case FUNCTION:
+ return parseFunctionDeclaration(context);
+ case ';':
+ next();
+ return context.createEmptyStatement();
+ case IF:
+ return parseIfStatement(context);
+ case DO:
+ return parseDoWhileStatement(context);
+ case WHILE:
+ return parseWhileStatement(context);
+ case FOR:
+ return parseForStatement(context);
+ case CONTINUE:
+ return parseContinueStatement(context);
+ case BREAK:
+ return parseBreakStatement(context);
+ case RETURN:
+ return parseReturnStatement(context);
+ case WITH:
+ return parseWithStatement(context);
+ case SWITCH:
+ return parseSwitchStatement(context);
+ case THROW:
+ return parseThrowStatement(context);
+ case TRY:
+ return parseTryStatement(context);
+ case DEBUGGER:
+ return parseDebuggerStatement(context);
+ case 0:
+ case CASE:
+ case CLOSEBRACE:
+ case DEFAULT:
+ // These tokens imply the end of a set of source elements
+ return 0;
+ case IDENT:
+ return parseExpressionOrLabelStatement(context);
+ default:
+ return parseExpressionStatement(context);
+ }
+}
+
+template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParameters(TreeBuilder& context, bool& usesArguments)
+{
+ matchOrFail(IDENT);
+ usesArguments = m_globalData->propertyNames->arguments == *token().m_data.ident;
+ TreeFormalParameterList list = context.createFormalParameterList(*token().m_data.ident);
+ TreeFormalParameterList tail = list;
+ next();
+ while (match(',')) {
+ next();
+ matchOrFail(IDENT);
+ const Identifier* ident = token().m_data.ident;
+ next();
+ usesArguments = usesArguments || m_globalData->propertyNames->arguments == *ident;
+ tail = context.createFormalParameterList(tail, *ident);
+ }
+ return list;
+}
+
+template <class TreeBuilder> TreeFunctionBody JSParser::parseFunctionBody(TreeBuilder& context)
+{
+ if (match(CLOSEBRACE))
+ return context.createFunctionBody();
+ typename TreeBuilder::FunctionBodyBuilder bodyBuilder(m_globalData, m_lexer);
+ failIfFalse(parseSourceElements(bodyBuilder));
+ return context.createFunctionBody();
+}
+
+template <JSParser::FunctionRequirements requirements, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine)
+{
+ if (match(IDENT)) {
+ name = token().m_data.ident;
+ next();
+ } else if (requirements == FunctionNeedsName)
+ return false;
+ consumeOrFail('(');
+ bool usesArguments = false;
+ if (!match(')')) {
+ parameters = parseFormalParameters(context, usesArguments);
+ failIfFalse(parameters);
+ }
+ consumeOrFail(')');
+ matchOrFail(OPENBRACE);
+
+ openBracePos = token().m_data.intValue;
+ bodyStartLine = tokenLine();
+ next();
+
+ body = parseFunctionBody(context);
+ failIfFalse(body);
+ if (usesArguments)
+ context.setUsesArguments(body);
+
+ matchOrFail(CLOSEBRACE);
+ closeBracePos = token().m_data.intValue;
+ next();
+ return true;
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseFunctionDeclaration(TreeBuilder& context)
+{
+ ASSERT(match(FUNCTION));
+ next();
+ const Identifier* name = 0;
+ TreeFormalParameterList parameters = 0;
+ TreeFunctionBody body = 0;
+ int openBracePos = 0;
+ int closeBracePos = 0;
+ int bodyStartLine = 0;
+ failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine));
+ failIfFalse(name);
+ return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseExpressionOrLabelStatement(TreeBuilder& context)
+{
+
+ /* Expression and Label statements are ambiguous at LL(1), to avoid
+ * the cost of having a token buffer to support LL(2) we simply assume
+ * we have an expression statement, and then only look for a label if that
+ * parse fails.
+ */
+ int start = tokenStart();
+ int startLine = tokenLine();
+ const Identifier* ident = token().m_data.ident;
+ int currentToken = m_tokenCount;
+ TreeExpression expression = parseExpression(context);
+ failIfFalse(expression);
+ if (autoSemiColon())
+ return context.createExprStatement(expression, startLine, m_lastLine);
+ failIfFalse(currentToken + 1 == m_tokenCount);
+ int end = tokenEnd();
+ consumeOrFail(':');
+ TreeStatement statement = parseStatement(context);
+ failIfFalse(statement);
+ return context.createLabelStatement(ident, statement, start, end);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseExpressionStatement(TreeBuilder& context)
+{
+ int startLine = tokenLine();
+ TreeExpression expression = parseExpression(context);
+ failIfFalse(expression);
+ failIfFalse(autoSemiColon());
+ return context.createExprStatement(expression, startLine, m_lastLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilder& context)
+{
+ ASSERT(match(IF));
+
+ int start = tokenLine();
+ next();
+
+ consumeOrFail('(');
+
+ TreeExpression condition = parseExpression(context);
+ failIfFalse(condition);
+ int end = tokenLine();
+ consumeOrFail(')');
+
+ TreeStatement trueBlock = parseStatement(context);
+ failIfFalse(trueBlock);
+
+ if (!match(ELSE))
+ return context.createIfStatement(condition, trueBlock, start, end);
+
+ Vector<TreeExpression> exprStack;
+ Vector<pair<int, int> > posStack;
+ Vector<TreeStatement> statementStack;
+ bool trailingElse = false;
+ do {
+ next();
+ if (!match(IF)) {
+ TreeStatement block = parseStatement(context);
+ failIfFalse(block);
+ statementStack.append(block);
+ trailingElse = true;
+ break;
+ }
+ int innerStart = tokenLine();
+ next();
+
+ consumeOrFail('(');
+
+ TreeExpression innerCondition = parseExpression(context);
+ failIfFalse(innerCondition);
+ int innerEnd = tokenLine();
+ consumeOrFail(')');
+
+ TreeStatement innerTrueBlock = parseStatement(context);
+ failIfFalse(innerTrueBlock);
+ exprStack.append(innerCondition);
+ posStack.append(make_pair(innerStart, innerEnd));
+ statementStack.append(innerTrueBlock);
+ } while (match(ELSE));
+
+ if (!trailingElse) {
+ TreeExpression condition = exprStack.last();
+ exprStack.removeLast();
+ TreeStatement trueBlock = statementStack.last();
+ statementStack.removeLast();
+ pair<int, int> pos = posStack.last();
+ posStack.removeLast();
+ statementStack.append(context.createIfStatement(condition, trueBlock, pos.first, pos.second));
+ }
+
+ while (!exprStack.isEmpty()) {
+ TreeExpression condition = exprStack.last();
+ exprStack.removeLast();
+ TreeStatement falseBlock = statementStack.last();
+ statementStack.removeLast();
+ TreeStatement trueBlock = statementStack.last();
+ statementStack.removeLast();
+ pair<int, int> pos = posStack.last();
+ posStack.removeLast();
+ statementStack.append(context.createIfStatement(condition, trueBlock, falseBlock, pos.first, pos.second));
+ }
+
+ return context.createIfStatement(condition, trueBlock, statementStack.last(), start, end);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseExpression(TreeBuilder& context)
+{
+ failIfStackOverflow();
+ TreeExpression node = parseAssignmentExpression(context);
+ failIfFalse(node);
+ if (!match(','))
+ return node;
+ next();
+ m_nonLHSCount++;
+ TreeExpression right = parseAssignmentExpression(context);
+ failIfFalse(right);
+ typename TreeBuilder::Comma commaNode = context.createCommaExpr(node, right);
+ while (match(',')) {
+ next();
+ right = parseAssignmentExpression(context);
+ failIfFalse(right);
+ context.appendToComma(commaNode, right);
+ }
+ return commaNode;
+}
+
+
+template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpression(TreeBuilder& context)
+{
+ failIfStackOverflow();
+ int start = tokenStart();
+ int initialAssignmentCount = m_assignmentCount;
+ int initialNonLHSCount = m_nonLHSCount;
+ TreeExpression lhs = parseConditionalExpression(context);
+ failIfFalse(lhs);
+ if (initialNonLHSCount != m_nonLHSCount)
+ return lhs;
+
+ int assignmentStack = 0;
+ Operator op;
+ bool hadAssignment = false;
+ while (true) {
+ switch (token().m_type) {
+ case '=': op = OpEqual; break;
+ case PLUSEQUAL: op = OpPlusEq; break;
+ case MINUSEQUAL: op = OpMinusEq; break;
+ case MULTEQUAL: op = OpMultEq; break;
+ case DIVEQUAL: op = OpDivEq; break;
+ case LSHIFTEQUAL: op = OpLShift; break;
+ case RSHIFTEQUAL: op = OpRShift; break;
+ case URSHIFTEQUAL: op = OpURShift; break;
+ case ANDEQUAL: op = OpAndEq; break;
+ case XOREQUAL: op = OpXOrEq; break;
+ case OREQUAL: op = OpOrEq; break;
+ case MODEQUAL: op = OpModEq; break;
+ default:
+ goto end;
+ }
+ hadAssignment = true;
+ context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), m_assignmentCount, op);
+ start = tokenStart();
+ m_assignmentCount++;
+ next();
+ lhs = parseConditionalExpression(context);
+ failIfFalse(lhs);
+ if (initialNonLHSCount != m_nonLHSCount)
+ break;
+ }
+end:
+ if (hadAssignment)
+ m_nonLHSCount++;
+
+ if (!ASTBuilder::CreatesAST)
+ return lhs;
+
+ while (assignmentStack)
+ lhs = context.createAssignment(assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd());
+
+ return lhs;
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseConditionalExpression(TreeBuilder& context)
+{
+ TreeExpression cond = parseBinaryExpression(context);
+ failIfFalse(cond);
+ if (!match('?'))
+ return cond;
+ m_nonLHSCount++;
+ next();
+ TreeExpression lhs = parseAssignmentExpression(context);
+ consumeOrFail(':');
+
+ TreeExpression rhs = parseAssignmentExpression(context);
+ failIfFalse(rhs);
+ return context.createConditionalExpr(cond, lhs, rhs);
+}
+
+static bool isUnaryOp(int token)
+{
+ switch (token) {
+ case '!':
+ case '~':
+ case '-':
+ case '+':
+ case PLUSPLUS:
+ case AUTOPLUSPLUS:
+ case MINUSMINUS:
+ case AUTOMINUSMINUS:
+ case TYPEOF:
+ case VOIDTOKEN:
+ case DELETETOKEN:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int JSParser::isBinaryOperator(int token)
+{
+ switch (token) {
+ case OR:
+ return 1;
+
+ case AND:
+ return 2;
+
+ case '|':
+ return 3;
+
+ case '^':
+ return 4;
+
+ case '&':
+ return 5;
+
+ case EQEQ:
+ case NE:
+ case STREQ:
+ case STRNEQ:
+ return 6;
+
+ case '<':
+ case '>':
+ case LE:
+ case GE:
+ case INSTANCEOF:
+ return 7;
+
+ case INTOKEN:
+ // same precedence as the above but needs a validity check
+ if (m_allowsIn)
+ return 7;
+ return 0;
+
+ case LSHIFT:
+ case RSHIFT:
+ case URSHIFT:
+ return 8;
+
+ case '+':
+ case '-':
+ return 9;
+
+ case '*':
+ case '/':
+ case '%':
+ return 10;
+
+ default:
+ return 0;
+ }
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(TreeBuilder& context)
+{
+
+ int operandStackDepth = 0;
+ int operatorStackDepth = 0;
+ while (true) {
+ int exprStart = tokenStart();
+ int initialAssignments = m_assignmentCount;
+ TreeExpression current = parseUnaryExpression(context);
+ failIfFalse(current);
+
+ context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), initialAssignments != m_assignmentCount);
+ int precedence = isBinaryOperator(token().m_type);
+ if (!precedence)
+ break;
+ m_nonLHSCount++;
+ int operatorToken = token().m_type;
+ next();
+
+ while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
+ ASSERT(operandStackDepth > 1);
+
+ typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
+ typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
+ context.shrinkOperandStackBy(operandStackDepth, 2);
+ context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
+ context.operatorStackPop(operatorStackDepth);
+ }
+ context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
+ }
+
+ while (operatorStackDepth) {
+ ASSERT(operandStackDepth > 1);
+
+ typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
+ typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
+ context.shrinkOperandStackBy(operandStackDepth, 2);
+ context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
+ context.operatorStackPop(operatorStackDepth);
+ }
+ return context.popOperandStack(operandStackDepth);
+}
+
+
+template <class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& context)
+{
+ bool wasIdent = false;
+ switch (token().m_type) {
+ case IDENT:
+ wasIdent = true;
+ case STRING: {
+ const Identifier* ident = token().m_data.ident;
+ next();
+ if (match(':')) {
+ next();
+ TreeExpression node = parseAssignmentExpression(context);
+ failIfFalse(node);
+ return context.createProperty(ident, node, PropertyNode::Constant);
+ }
+ failIfFalse(wasIdent);
+ matchOrFail(IDENT);
+ const Identifier* accessorName = 0;
+ TreeFormalParameterList parameters = 0;
+ TreeFunctionBody body = 0;
+ int openBracePos = 0;
+ int closeBracePos = 0;
+ int bodyStartLine = 0;
+ failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine));
+ return context.createGetterOrSetterProperty(ident, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
+ }
+ case NUMBER: {
+ double propertyName = token().m_data.doubleValue;
+ next();
+ consumeOrFail(':');
+ TreeExpression node = parseAssignmentExpression(context);
+ failIfFalse(node);
+ return context.createProperty(propertyName, node, PropertyNode::Constant);
+ }
+ }
+ fail();
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBuilder& context)
+{
+ consumeOrFail(OPENBRACE);
+
+ if (match(CLOSEBRACE)) {
+ next();
+ return context.createObjectLiteral();
+ }
+
+ TreeProperty property = parseProperty(context);
+ failIfFalse(property);
+
+ TreePropertyList propertyList = context.createPropertyList(property);
+ TreePropertyList tail = propertyList;
+
+ while (match(',')) {
+ next();
+ // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
+ if (match(CLOSEBRACE))
+ break;
+ property = parseProperty(context);
+ failIfFalse(property);
+
+ tail = context.createPropertyList(property, tail);
+ }
+
+ consumeOrFail(CLOSEBRACE);
+
+ return context.createObjectLiteral(propertyList);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuilder& context)
+{
+ consumeOrFail('[');
+
+ int elisions = 0;
+ while (match(',')) {
+ next();
+ elisions++;
+ }
+ if (match(']')) {
+ next();
+ return context.createArray(elisions);
+ }
+
+ TreeExpression elem = parseAssignmentExpression(context);
+ failIfFalse(elem);
+ typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
+ typename TreeBuilder::ElementList tail = elementList;
+ elisions = 0;
+ while (match(',')) {
+ next();
+ elisions = 0;
+
+ while (match(',')) {
+ next();
+ elisions++;
+ }
+
+ if (match(']')) {
+ next();
+ return context.createArray(elisions, elementList);
+ }
+ TreeExpression elem = parseAssignmentExpression(context);
+ failIfFalse(elem);
+ tail = context.createElementList(tail, elisions, elem);
+ }
+
+ consumeOrFail(']');
+
+ return context.createArray(elementList);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(TreeBuilder& context)
+{
+ switch (token().m_type) {
+ case OPENBRACE:
+ return parseObjectLiteral(context);
+ case '[':
+ return parseArrayLiteral(context);
+ case '(': {
+ next();
+ int oldNonLHSCount = m_nonLHSCount;
+ TreeExpression result = parseExpression(context);
+ m_nonLHSCount = oldNonLHSCount;
+ consumeOrFail(')');
+
+ return result;
+ }
+ case THISTOKEN: {
+ next();
+ return context.thisExpr();
+ }
+ case IDENT: {
+ int start = tokenStart();
+ const Identifier* ident = token().m_data.ident;
+ next();
+ return context.createResolve(ident, start);
+ }
+ case STRING: {
+ const Identifier* ident = token().m_data.ident;
+ next();
+ return context.createString(ident);
+ }
+ case NUMBER: {
+ double d = token().m_data.doubleValue;
+ next();
+ return context.createNumberExpr(d);
+ }
+ case NULLTOKEN: {
+ next();
+ return context.createNull();
+ }
+ case TRUETOKEN: {
+ next();
+ return context.createBoolean(true);
+ }
+ case FALSETOKEN: {
+ next();
+ return context.createBoolean(false);
+ }
+ case DIVEQUAL:
+ case '/': {
+ /* regexp */
+ const Identifier* pattern;
+ const Identifier* flags;
+ if (match(DIVEQUAL))
+ failIfFalse(m_lexer->scanRegExp(pattern, flags, '='));
+ else
+ failIfFalse(m_lexer->scanRegExp(pattern, flags));
+
+ int start = tokenStart();
+ next();
+ return context.createRegex(*pattern, *flags, start);
+ }
+ }
+ fail();
+}
+
+template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder& context)
+{
+ consumeOrFail('(');
+ if (match(')')) {
+ next();
+ return context.createArguments();
+ }
+ TreeExpression firstArg = parseAssignmentExpression(context);
+ failIfFalse(firstArg);
+
+ TreeArgumentsList argList = context.createArgumentsList(firstArg);
+ TreeArgumentsList tail = argList;
+ while (match(',')) {
+ next();
+ TreeExpression arg = parseAssignmentExpression(context);
+ failIfFalse(arg);
+ tail = context.createArgumentsList(tail, arg);
+ }
+ consumeOrFail(')');
+ return context.createArguments(argList);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(TreeBuilder& context)
+{
+ TreeExpression base = 0;
+ int start = tokenStart();
+ int expressionStart = start;
+ int newCount = 0;
+ while (match(NEW)) {
+ next();
+ newCount++;
+ }
+ if (match(FUNCTION)) {
+ const Identifier* name = &m_globalData->propertyNames->nullIdentifier;
+ TreeFormalParameterList parameters = 0;
+ TreeFunctionBody body = 0;
+ int openBracePos = 0;
+ int closeBracePos = 0;
+ int bodyStartLine = 0;
+ next();
+ failIfFalse(parseFunctionInfo<FunctionNoRequirements>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine));
+ base = context.createFunctionExpr(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
+ } else
+ base = parsePrimaryExpression(context);
+
+ failIfFalse(base);
+ while (true) {
+ switch (token().m_type) {
+ case '[': {
+ int expressionEnd = lastTokenEnd();
+ next();
+ int nonLHSCount = m_nonLHSCount;
+ int initialAssignments = m_assignmentCount;
+ TreeExpression property = parseExpression(context);
+ failIfFalse(property);
+ base = context.createBracketAccess(base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd());
+ if (!consume(']'))
+ fail();
+ m_nonLHSCount = nonLHSCount;
+ break;
+ }
+ case '(': {
+ if (newCount) {
+ newCount--;
+ if (match('(')) {
+ int exprEnd = lastTokenEnd();
+ TreeArguments arguments = parseArguments(context);
+ failIfFalse(arguments);
+ base = context.createNewExpr(base, arguments, start, exprEnd, lastTokenEnd());
+ } else
+ base = context.createNewExpr(base, start, lastTokenEnd());
+ } else {
+ int nonLHSCount = m_nonLHSCount;
+ int expressionEnd = lastTokenEnd();
+ TreeArguments arguments = parseArguments(context);
+ failIfFalse(arguments);
+ base = context.makeFunctionCallNode(base, arguments, expressionStart, expressionEnd, lastTokenEnd());
+ m_nonLHSCount = nonLHSCount;
+ }
+ break;
+ }
+ case '.': {
+ int expressionEnd = lastTokenEnd();
+ next();
+ matchOrFail(IDENT);
+ base = context.createDotAccess(base, *token().m_data.ident, expressionStart, expressionEnd, tokenEnd());
+ next();
+ break;
+ }
+ default:
+ goto endMemberExpression;
+ }
+ }
+endMemberExpression:
+ while (newCount--)
+ base = context.createNewExpr(base, start, lastTokenEnd());
+ return base;
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeBuilder& context)
+{
+ AllowInOverride allowInOverride(this);
+ int tokenStackDepth = 0;
+ while (isUnaryOp(token().m_type)) {
+ m_nonLHSCount++;
+ context.appendUnaryToken(tokenStackDepth, token().m_type, tokenStart());
+ next();
+ }
+ int subExprStart = tokenStart();
+ TreeExpression expr = parseMemberExpression(context);
+ failIfFalse(expr);
+ switch (token().m_type) {
+ case PLUSPLUS:
+ m_nonLHSCount++;
+ expr = context.makePostfixNode(expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd());
+ m_assignmentCount++;
+ next();
+ break;
+ case MINUSMINUS:
+ m_nonLHSCount++;
+ expr = context.makePostfixNode(expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd());
+ m_assignmentCount++;
+ next();
+ break;
+ }
+
+ int end = lastTokenEnd();
+
+ if (!TreeBuilder::CreatesAST)
+ return expr;
+
+ while (tokenStackDepth) {
+ switch (context.unaryTokenStackLastType(tokenStackDepth)) {
+ case '!':
+ expr = context.createLogicalNot(expr);
+ break;
+ case '~':
+ expr = context.makeBitwiseNotNode(expr);
+ break;
+ case '-':
+ expr = context.makeNegateNode(expr);
+ break;
+ case '+':
+ expr = context.createUnaryPlus(expr);
+ break;
+ case PLUSPLUS:
+ case AUTOPLUSPLUS:
+ expr = context.makePrefixNode(expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
+ m_assignmentCount++;
+ break;
+ case MINUSMINUS:
+ case AUTOMINUSMINUS:
+ expr = context.makePrefixNode(expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
+ m_assignmentCount++;
+ break;
+ case TYPEOF:
+ expr = context.makeTypeOfNode(expr);
+ break;
+ case VOIDTOKEN:
+ expr = context.createVoid(expr);
+ break;
+ case DELETETOKEN:
+ expr = context.makeDeleteNode(expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
+ break;
+ default:
+ // If we get here something has gone horribly horribly wrong
+ CRASH();
+ }
+ subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
+ context.unaryTokenStackRemoveLast(tokenStackDepth);
+ }
+ return expr;
+}
+
+}
+
+#endif
+
diff --git a/JavaScriptCore/parser/JSParser.h b/JavaScriptCore/parser/JSParser.h
new file mode 100644
index 0000000..e212b2a
--- /dev/null
+++ b/JavaScriptCore/parser/JSParser.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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 JSParser_h
+#define JSParser_h
+#if ENABLE(RECURSIVE_PARSE)
+
+namespace JSC {
+
+class Identifier;
+class JSGlobalData;
+
+enum JSTokenType {
+ NULLTOKEN = 258,
+ TRUETOKEN = 259,
+ FALSETOKEN = 260,
+ BREAK = 261,
+ CASE = 262,
+ DEFAULT = 263,
+ FOR = 264,
+ NEW = 265,
+ VAR = 266,
+ CONSTTOKEN = 267,
+ CONTINUE = 268,
+ FUNCTION = 269,
+ RETURN = 270,
+ VOIDTOKEN = 271,
+ DELETETOKEN = 272,
+ IF = 273,
+ THISTOKEN = 274,
+ DO = 275,
+ WHILE = 276,
+ INTOKEN = 277,
+ INSTANCEOF = 278,
+ TYPEOF = 279,
+ SWITCH = 280,
+ WITH = 281,
+ RESERVED = 282,
+ THROW = 283,
+ TRY = 284,
+ CATCH = 285,
+ FINALLY = 286,
+ DEBUGGER = 287,
+ IF_WITHOUT_ELSE = 288,
+ ELSE = 289,
+ EQEQ = 290,
+ NE = 291,
+ STREQ = 292,
+ STRNEQ = 293,
+ LE = 294,
+ GE = 295,
+ OR = 296,
+ AND = 297,
+ PLUSPLUS = 298,
+ MINUSMINUS = 299,
+ LSHIFT = 300,
+ RSHIFT = 301,
+ URSHIFT = 302,
+ PLUSEQUAL = 303,
+ MINUSEQUAL = 304,
+ MULTEQUAL = 305,
+ DIVEQUAL = 306,
+ LSHIFTEQUAL = 307,
+ RSHIFTEQUAL = 308,
+ URSHIFTEQUAL = 309,
+ ANDEQUAL = 310,
+ MODEQUAL = 311,
+ XOREQUAL = 312,
+ OREQUAL = 313,
+ OPENBRACE = 314,
+ CLOSEBRACE = 315,
+ NUMBER = 316,
+ IDENT = 317,
+ STRING = 318,
+ AUTOPLUSPLUS = 319,
+ AUTOMINUSMINUS = 320
+};
+
+union JSTokenData {
+ int intValue;
+ double doubleValue;
+ const Identifier* ident;
+};
+typedef JSTokenData YYSTYPE;
+
+struct JSTokenInfo {
+ JSTokenInfo() : last_line(0) {}
+ int first_line;
+ int last_line;
+ int first_column;
+ int last_column;
+};
+typedef JSTokenInfo YYLTYPE;
+struct JSToken {
+ int m_type;
+ JSTokenData m_data;
+ JSTokenInfo m_info;
+};
+
+int jsParse(JSGlobalData*);
+}
+#endif
+#endif // JSParser_h
diff --git a/JavaScriptCore/parser/Lexer.cpp b/JavaScriptCore/parser/Lexer.cpp
index 1af2d75..3a38273 100644
--- a/JavaScriptCore/parser/Lexer.cpp
+++ b/JavaScriptCore/parser/Lexer.cpp
@@ -24,7 +24,9 @@
#include "Lexer.h"
#include "JSFunction.h"
+
#include "JSGlobalObjectFunctions.h"
+#include "Identifier.h"
#include "NodeInfo.h"
#include "Nodes.h"
#include "dtoa.h"
@@ -36,10 +38,13 @@
using namespace WTF;
using namespace Unicode;
-// We can't specify the namespace in yacc's C output, so do it here instead.
+#if ENABLE(RECURSIVE_PARSE)
+#include "JSParser.h"
+#else
using namespace JSC;
-
#include "Grammar.h"
+#endif
+
#include "Lookup.h"
#include "Lexer.lut.h"
@@ -872,7 +877,7 @@ doneIdentifierOrKeyword: {
m_delimited = false;
m_buffer16.resize(0);
const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident);
- token = entry ? entry->lexerValue() : IDENT;
+ token = entry ? entry->lexerValue() : static_cast<int>(IDENT);
goto returnToken;
}
@@ -893,7 +898,6 @@ returnToken: {
llocp->last_line = lineNumber;
llocp->first_column = startOffset;
llocp->last_column = currentOffset();
-
m_lastToken = token;
return token;
}
@@ -1024,20 +1028,23 @@ SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine)
return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine);
const UChar* data = m_source->provider()->data();
-
+
ASSERT(openBrace < closeBrace);
-
- int numBOMsBeforeOpenBrace = 0;
- int numBOMsBetweenBraces = 0;
-
int i;
- for (i = m_source->startOffset(); i < openBrace; ++i)
- numBOMsBeforeOpenBrace += data[i] == byteOrderMark;
- for (; i < closeBrace; ++i)
- numBOMsBetweenBraces += data[i] == byteOrderMark;
+ for (i = m_source->startOffset(); i < openBrace; ++i) {
+ if (data[i] == byteOrderMark) {
+ openBrace++;
+ closeBrace++;
+ }
+ }
+ for (; i < closeBrace; ++i) {
+ if (data[i] == byteOrderMark)
+ closeBrace++;
+ }
+
+ ASSERT(openBrace < closeBrace);
- return SourceCode(m_source->provider(), openBrace + numBOMsBeforeOpenBrace,
- closeBrace + numBOMsBeforeOpenBrace + numBOMsBetweenBraces + 1, firstLine);
+ return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine);
}
} // namespace JSC
diff --git a/JavaScriptCore/parser/Lexer.h b/JavaScriptCore/parser/Lexer.h
index c76696c..f197093 100644
--- a/JavaScriptCore/parser/Lexer.h
+++ b/JavaScriptCore/parser/Lexer.h
@@ -49,6 +49,8 @@ namespace JSC {
// Functions for the parser itself.
int lex(void* lvalp, void* llocp);
int lineNumber() const { return m_lineNumber; }
+ void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
+ int lastLineNumber() const { return m_lastLineNumber; }
bool prevTerminator() const { return m_terminator; }
SourceCode sourceCode(int openBrace, int closeBrace, int firstLine);
bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0);
@@ -84,8 +86,9 @@ namespace JSC {
bool lastTokenWasRestrKeyword() const;
static const size_t initialReadBufferCapacity = 32;
-
+
int m_lineNumber;
+ int m_lastLineNumber;
Vector<char> m_buffer8;
Vector<UChar> m_buffer16;
diff --git a/JavaScriptCore/parser/NodeConstructors.h b/JavaScriptCore/parser/NodeConstructors.h
index dd3b981..8b64e0f 100644
--- a/JavaScriptCore/parser/NodeConstructors.h
+++ b/JavaScriptCore/parser/NodeConstructors.h
@@ -43,7 +43,11 @@ namespace JSC {
}
inline Node::Node(JSGlobalData* globalData)
+#if ENABLE(RECURSIVE_PARSE)
+ : m_line(globalData->lexer->lastLineNumber())
+#else
: m_line(globalData->lexer->lineNumber())
+#endif
{
}
diff --git a/JavaScriptCore/parser/Parser.cpp b/JavaScriptCore/parser/Parser.cpp
index 48627df..fe92b40 100644
--- a/JavaScriptCore/parser/Parser.cpp
+++ b/JavaScriptCore/parser/Parser.cpp
@@ -24,6 +24,7 @@
#include "Parser.h"
#include "Debugger.h"
+#include "JSParser.h"
#include "Lexer.h"
#include <wtf/HashSet.h>
#include <wtf/Vector.h>
@@ -58,10 +59,14 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
Lexer& lexer = *globalData->lexer;
lexer.setCode(*m_source, m_arena);
-
+
+#if ENABLE(RECURSIVE_PARSE)
+ int parseError = jsParse(globalData);
+#else
int parseError = jscyyparse(globalData);
- bool lexError = lexer.sawError();
+#endif
int lineNumber = lexer.lineNumber();
+ bool lexError = lexer.sawError();
lexer.clear();
if (parseError || lexError) {
diff --git a/JavaScriptCore/parser/SyntaxChecker.h b/JavaScriptCore/parser/SyntaxChecker.h
new file mode 100644
index 0000000..cad89f6
--- /dev/null
+++ b/JavaScriptCore/parser/SyntaxChecker.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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 SyntaxChecker_h
+#define SyntaxChecker_h
+
+namespace JSC {
+class SyntaxChecker {
+public:
+ SyntaxChecker(JSGlobalData*, Lexer*)
+ {
+ }
+
+ typedef SyntaxChecker FunctionBodyBuilder;
+
+ typedef int Expression;
+ typedef int SourceElements;
+ typedef int Arguments;
+ typedef int Comma;
+ typedef int Property;
+ typedef int PropertyList;
+ typedef int ElementList;
+ typedef int ArgumentsList;
+ typedef int FormalParameterList;
+ typedef int FunctionBody;
+ typedef int Statement;
+ typedef int ClauseList;
+ typedef int Clause;
+ typedef int ConstDeclList;
+ typedef int BinaryOperand;
+
+ static const bool CreatesAST = false;
+
+ int createSourceElements() { return 1; }
+ int makeFunctionCallNode(int, int, int, int, int) { return 1; }
+ void appendToComma(int, int) { }
+ int createCommaExpr(int, int) { return 1; }
+ int makeAssignNode(int, Operator, int, bool, bool, int, int, int) { return 1; }
+ int makePrefixNode(int, Operator, int, int, int) { return 1; }
+ int makePostfixNode(int, Operator, int, int, int) { return 1; }
+ int makeTypeOfNode(int) { return 1; }
+ int makeDeleteNode(int, int, int, int) { return 1; }
+ int makeNegateNode(int) { return 1; }
+ int makeBitwiseNotNode(int) { return 1; }
+ int createLogicalNot(int) { return 1; }
+ int createUnaryPlus(int) { return 1; }
+ int createVoid(int) { return 1; }
+ int thisExpr() { return 1; }
+ int createResolve(const Identifier*, int) { return 1; }
+ int createObjectLiteral() { return 1; }
+ int createObjectLiteral(int) { return 1; }
+ int createArray(int) { return 1; }
+ int createArray(int, int) { return 1; }
+ int createNumberExpr(double) { return 1; }
+ int createString(const Identifier*) { return 1; }
+ int createBoolean(bool) { return 1; }
+ int createNull() { return 1; }
+ int createBracketAccess(int, int, bool, int, int, int) { return 1; }
+ int createDotAccess(int, const Identifier&, int, int, int) { return 1; }
+ int createRegex(const Identifier&, const Identifier&, int) { return 1; }
+ int createNewExpr(int, int, int, int, int) { return 1; }
+ int createNewExpr(int, int, int) { return 1; }
+ int createConditionalExpr(int, int, int) { return 1; }
+ int createAssignResolve(const Identifier&, int, bool, int, int, int) { return 1; }
+ int createFunctionExpr(const Identifier*, int, int, int, int, int, int) { return 1; }
+ int createFunctionBody() { return 1; }
+ int createArguments() { return 1; }
+ int createArguments(int) { return 1; }
+ int createArgumentsList(int) { return 1; }
+ int createArgumentsList(int, int) { return 1; }
+ int createProperty(const Identifier*, int, PropertyNode::Type) { return 1; }
+ int createProperty(double, int, PropertyNode::Type) { return 1; }
+ int createPropertyList(int) { return 1; }
+ int createPropertyList(int, int) { return 1; }
+ int createElementList(int, int) { return 1; }
+ int createElementList(int, int, int) { return 1; }
+ int createFormalParameterList(const Identifier&) { return 1; }
+ int createFormalParameterList(int, const Identifier&) { return 1; }
+ int createClause(int, int) { return 1; }
+ int createClauseList(int) { return 1; }
+ int createClauseList(int, int) { return 1; }
+ void setUsesArguments(int) { }
+ int createFuncDeclStatement(const Identifier*, int, int, int, int, int, int) { return 1; }
+ int createBlockStatement(int, int, int) { return 1; }
+ int createExprStatement(int, int, int) { return 1; }
+ int createIfStatement(int, int, int, int) { return 1; }
+ int createIfStatement(int, int, int, int, int) { return 1; }
+ int createForLoop(int, int, int, int, bool, int, int) { return 1; }
+ int createForInLoop(const Identifier*, int, int, int, int, int, int, int, int, int, int) { return 1; }
+ int createForInLoop(int, int, int, int, int, int, int, int) { return 1; }
+ int createEmptyStatement() { return 1; }
+ int createVarStatement(int, int, int) { return 1; }
+ int createReturnStatement(int, int, int, int, int) { return 1; }
+ int createBreakStatement(int, int, int, int) { return 1; }
+ int createBreakStatement(const Identifier*, int, int, int, int) { return 1; }
+ int createContinueStatement(int, int, int, int) { return 1; }
+ int createContinueStatement(const Identifier*, int, int, int, int) { return 1; }
+ int createTryStatement(int, const Identifier*, bool, int, int, int, int) { return 1; }
+ int createSwitchStatement(int, int, int, int, int, int) { return 1; }
+ int createWhileStatement(int, int, int, int) { return 1; }
+ int createWithStatement(int, int, int, int, int, int) { return 1; }
+ int createDoWhileStatement(int, int, int, int) { return 1; }
+ int createLabelStatement(const Identifier*, int, int, int) { return 1; }
+ int createThrowStatement(int, int, int, int, int) { return 1; }
+ int createDebugger(int, int) { return 1; }
+ int createConstStatement(int, int, int) { return 1; }
+ int appendConstDecl(int, const Identifier*, int) { return 1; }
+ int createGetterOrSetterProperty(const Identifier*, const Identifier*, int, int, int, int, int, int) { return 1; }
+
+ void appendStatement(int, int) { }
+ void addVar(const Identifier*, bool) { }
+ int combineCommaNodes(int, int) { return 1; }
+ int evalCount() const { return 0; }
+ void appendBinaryExpressionInfo(int& operandStackDepth, int, int, int, int, bool) { operandStackDepth++; }
+
+ // Logic to handle datastructures used during parsing of binary expressions
+ void operatorStackPop(int& operatorStackDepth) { operatorStackDepth--; }
+ bool operatorStackHasHigherPrecedence(int&, int) { return true; }
+ BinaryOperand getFromOperandStack(int) { return 1; }
+ void shrinkOperandStackBy(int& operandStackDepth, int amount) { operandStackDepth -= amount; }
+ void appendBinaryOperation(int& operandStackDepth, int&, BinaryOperand, BinaryOperand) { operandStackDepth++; }
+ void operatorStackAppend(int& operatorStackDepth, int, int) { operatorStackDepth++; }
+ int popOperandStack(int&) { return 1; }
+
+ void appendUnaryToken(int&, int, int) { }
+ int unaryTokenStackLastType(int&) { ASSERT_NOT_REACHED(); return 1; }
+ int unaryTokenStackLastStart(int&) { ASSERT_NOT_REACHED(); return 1; }
+ void unaryTokenStackRemoveLast(int&) { }
+
+ void assignmentStackAppend(int, int, int, int, int, Operator) { }
+ int createAssignment(int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; }
+};
+
+}
+
+#endif
diff --git a/JavaScriptCore/qt/api/qscriptengine_p.cpp b/JavaScriptCore/qt/api/qscriptengine_p.cpp
index a6cf4a4..fd7978b 100644
--- a/JavaScriptCore/qt/api/qscriptengine_p.cpp
+++ b/JavaScriptCore/qt/api/qscriptengine_p.cpp
@@ -85,5 +85,5 @@ QScriptValuePrivate* QScriptEnginePrivate::newObject() const
QScriptValuePrivate* QScriptEnginePrivate::globalObject() const
{
JSObjectRef globalObject = JSContextGetGlobalObject(m_context);
- return new QScriptValuePrivate(this, globalObject, globalObject);
+ return new QScriptValuePrivate(this, globalObject);
}
diff --git a/JavaScriptCore/qt/api/qscriptvalue.cpp b/JavaScriptCore/qt/api/qscriptvalue.cpp
index 22ff8be..8ad76a5 100644
--- a/JavaScriptCore/qt/api/qscriptvalue.cpp
+++ b/JavaScriptCore/qt/api/qscriptvalue.cpp
@@ -518,6 +518,34 @@ QScriptEngine* QScriptValue::engine() const
}
/*!
+ If this QScriptValue is an object, returns the internal prototype
+ (\c{__proto__} property) of this object; otherwise returns an
+ invalid QScriptValue.
+
+ \sa setPrototype(), isObject()
+*/
+QScriptValue QScriptValue::prototype() const
+{
+ return QScriptValuePrivate::get(d_ptr->prototype());
+}
+
+/*!
+ If this QScriptValue is an object, sets the internal prototype
+ (\c{__proto__} property) of this object to be \a prototype;
+ otherwise does nothing.
+
+ The internal prototype should not be confused with the public
+ property with name "prototype"; the public prototype is usually
+ only set on functions that act as constructors.
+
+ \sa prototype(), isObject()
+*/
+void QScriptValue::setPrototype(const QScriptValue& prototype)
+{
+ d_ptr->setPrototype(QScriptValuePrivate::get(prototype));
+}
+
+/*!
Assigns the \a other value to this QScriptValue.
Note that if \a other is an object (isObject() returns true),
diff --git a/JavaScriptCore/qt/api/qscriptvalue.h b/JavaScriptCore/qt/api/qscriptvalue.h
index 6c42429..c82ef55 100644
--- a/JavaScriptCore/qt/api/qscriptvalue.h
+++ b/JavaScriptCore/qt/api/qscriptvalue.h
@@ -59,6 +59,10 @@ public:
~QScriptValue();
QScriptValue& operator=(const QScriptValue& other);
+
+ QScriptValue prototype() const;
+ void setPrototype(const QScriptValue& prototype);
+
bool equals(const QScriptValue& other) const;
bool strictlyEquals(const QScriptValue& other) const;
bool instanceOf(const QScriptValue& other) const;
diff --git a/JavaScriptCore/qt/api/qscriptvalue_p.h b/JavaScriptCore/qt/api/qscriptvalue_p.h
index 1bb8a77..f8a1e7a 100644
--- a/JavaScriptCore/qt/api/qscriptvalue_p.h
+++ b/JavaScriptCore/qt/api/qscriptvalue_p.h
@@ -25,6 +25,7 @@
#include "qscriptvalue.h"
#include <JavaScriptCore/JavaScript.h>
#include <JavaScriptCore/JSRetainPtr.h>
+#include <JSObjectRefPrivate.h>
#include <QtCore/qmath.h>
#include <QtCore/qnumeric.h>
#include <QtCore/qshareddata.h>
@@ -49,7 +50,7 @@ class QScriptValue;
CNumber -> QSVP is created from int, uint, double... and no JSC engine has been bind yet. Current
value is kept in m_number
CBool -> QSVP is created from bool and no JSC engine has been associated yet. Current value is kept
- in m_number
+ in m_bool
CNull -> QSVP is null, but a JSC engine hasn't been associated yet.
CUndefined -> QSVP is undefined, but a JSC engine hasn't been associated yet.
JSValue -> QSVP is associated with engine, but there is no information about real type, the state
@@ -89,7 +90,7 @@ public:
inline QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value);
inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value);
- inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object);
+ inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSObjectRef object);
inline bool isValid() const;
inline bool isBool();
@@ -108,8 +109,11 @@ public:
inline qint32 toInt32() const;
inline quint32 toUInt32() const;
inline quint16 toUInt16() const;
+
inline QScriptValuePrivate* toObject(QScriptEnginePrivate* engine);
inline QScriptValuePrivate* toObject();
+ inline QScriptValuePrivate* prototype();
+ inline void setPrototype(QScriptValuePrivate* prototype);
inline bool equals(QScriptValuePrivate* other);
inline bool strictlyEquals(QScriptValuePrivate* other);
@@ -137,12 +141,23 @@ private:
JSObject
} m_state;
QScriptEnginePtr m_engine;
- QString m_string;
- qsreal m_number;
- JSValueRef m_value;
- JSObjectRef m_object;
-
- inline void setValue(JSValueRef);
+ union Value
+ {
+ bool m_bool;
+ qsreal m_number;
+ JSValueRef m_value;
+ JSObjectRef m_object;
+ QString* m_string;
+
+ Value() : m_number(0) {}
+ Value(bool value) : m_bool(value) {}
+ Value(int number) : m_number(number) {}
+ Value(uint number) : m_number(number) {}
+ Value(qsreal number) : m_number(number) {}
+ Value(JSValueRef value) : m_value(value) {}
+ Value(JSObjectRef object) : m_object(object) {}
+ Value(QString* string) : m_string(string) {}
+ } u;
inline bool inherits(const char*);
inline State refinedJSValue();
@@ -166,131 +181,124 @@ QScriptValue QScriptValuePrivate::get(QScriptValuePrivate* d)
QScriptValuePrivate::~QScriptValuePrivate()
{
- if (m_value)
- JSValueUnprotect(*m_engine, m_value);
+ if (isJSBased())
+ JSValueUnprotect(*m_engine, u.m_value);
+ else if (isStringBased())
+ delete u.m_string;
}
QScriptValuePrivate::QScriptValuePrivate()
: m_state(Invalid)
- , m_value(0)
{
}
QScriptValuePrivate::QScriptValuePrivate(const QString& string)
: m_state(CString)
- , m_string(string)
- , m_value(0)
+ , u(new QString(string))
{
}
QScriptValuePrivate::QScriptValuePrivate(bool value)
: m_state(CBool)
- , m_number(value)
- , m_value(0)
+ , u(value)
{
}
QScriptValuePrivate::QScriptValuePrivate(int number)
: m_state(CNumber)
- , m_number(number)
- , m_value(0)
+ , u(number)
{
}
QScriptValuePrivate::QScriptValuePrivate(uint number)
: m_state(CNumber)
- , m_number(number)
- , m_value(0)
+ , u(number)
{
}
QScriptValuePrivate::QScriptValuePrivate(qsreal number)
: m_state(CNumber)
- , m_number(number)
- , m_value(0)
+ , u(number)
{
}
QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value)
: m_state(value == QScriptValue::NullValue ? CNull : CUndefined)
- , m_value(0)
{
}
QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, bool value)
: m_state(JSPrimitive)
, m_engine(const_cast<QScriptEnginePrivate*>(engine))
- , m_value(engine->makeJSValue(value))
+ , u(engine->makeJSValue(value))
{
Q_ASSERT(engine);
- JSValueProtect(*m_engine, m_value);
+ JSValueProtect(*m_engine, u.m_value);
}
QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, int value)
: m_state(JSPrimitive)
, m_engine(const_cast<QScriptEnginePrivate*>(engine))
- , m_value(m_engine->makeJSValue(value))
+ , u(m_engine->makeJSValue(value))
{
Q_ASSERT(engine);
- JSValueProtect(*m_engine, m_value);
+ JSValueProtect(*m_engine, u.m_value);
}
QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, uint value)
: m_state(JSPrimitive)
, m_engine(const_cast<QScriptEnginePrivate*>(engine))
- , m_value(m_engine->makeJSValue(value))
+ , u(m_engine->makeJSValue(value))
{
Q_ASSERT(engine);
- JSValueProtect(*m_engine, m_value);
+ JSValueProtect(*m_engine, u.m_value);
}
QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, qsreal value)
: m_state(JSPrimitive)
, m_engine(const_cast<QScriptEnginePrivate*>(engine))
- , m_value(m_engine->makeJSValue(value))
+ , u(m_engine->makeJSValue(value))
{
Q_ASSERT(engine);
- JSValueProtect(*m_engine, m_value);
+ JSValueProtect(*m_engine, u.m_value);
}
QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, const QString& value)
: m_state(JSPrimitive)
, m_engine(const_cast<QScriptEnginePrivate*>(engine))
- , m_value(m_engine->makeJSValue(value))
+ , u(m_engine->makeJSValue(value))
{
Q_ASSERT(engine);
- JSValueProtect(*m_engine, m_value);
+ JSValueProtect(*m_engine, u.m_value);
}
QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value)
: m_state(JSPrimitive)
, m_engine(const_cast<QScriptEnginePrivate*>(engine))
- , m_value(m_engine->makeJSValue(value))
+ , u(m_engine->makeJSValue(value))
{
Q_ASSERT(engine);
- JSValueProtect(*m_engine, m_value);
+ JSValueProtect(*m_engine, u.m_value);
}
QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value)
: m_state(JSValue)
, m_engine(const_cast<QScriptEnginePrivate*>(engine))
- , m_value(value)
+ , u(value)
{
Q_ASSERT(engine);
Q_ASSERT(value);
- JSValueProtect(*m_engine, m_value);
+ JSValueProtect(*m_engine, u.m_value);
}
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object)
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSObjectRef object)
: m_state(JSObject)
, m_engine(const_cast<QScriptEnginePrivate*>(engine))
- , m_value(value)
- , m_object(object)
+ , u(object)
{
Q_ASSERT(engine);
- Q_ASSERT(value);
Q_ASSERT(object);
- JSValueProtect(*m_engine, m_value);
+ JSValueProtect(*m_engine, object);
}
bool QScriptValuePrivate::isValid() const { return m_state != Invalid; }
@@ -422,11 +430,11 @@ QString QScriptValuePrivate::toString() const
case Invalid:
return QString();
case CBool:
- return m_number ? QString::fromLatin1("true") : QString::fromLatin1("false");
+ return u.m_bool ? QString::fromLatin1("true") : QString::fromLatin1("false");
case CString:
- return m_string;
+ return *u.m_string;
case CNumber:
- return QScriptConverter::toString(m_number);
+ return QScriptConverter::toString(u.m_number);
case CNull:
return QString::fromLatin1("null");
case CUndefined:
@@ -450,9 +458,9 @@ qsreal QScriptValuePrivate::toNumber() const
case JSObject:
return JSValueToNumber(*m_engine, *this, /* exception */ 0);
case CNumber:
- return m_number;
+ return u.m_number;
case CBool:
- return m_number ? 1 : 0;
+ return u.m_bool ? 1 : 0;
case CNull:
case Invalid:
return 0;
@@ -460,15 +468,15 @@ qsreal QScriptValuePrivate::toNumber() const
return qQNaN();
case CString:
bool ok;
- qsreal result = m_string.toDouble(&ok);
+ qsreal result = u.m_string->toDouble(&ok);
if (ok)
return result;
- result = m_string.toInt(&ok, 0); // Try other bases.
+ result = u.m_string->toInt(&ok, 0); // Try other bases.
if (ok)
return result;
- if (m_string == "Infinity" || m_string == "-Infinity")
+ if (*u.m_string == "Infinity" || *u.m_string == "-Infinity")
return qInf();
- return m_string.length() ? qQNaN() : 0;
+ return u.m_string->length() ? qQNaN() : 0;
}
Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement.");
@@ -484,15 +492,15 @@ bool QScriptValuePrivate::toBool() const
case JSObject:
return true;
case CNumber:
- return !(qIsNaN(m_number) || !m_number);
+ return !(qIsNaN(u.m_number) || !u.m_number);
case CBool:
- return m_number;
+ return u.m_bool;
case Invalid:
case CNull:
case CUndefined:
return false;
case CString:
- return m_string.length();
+ return u.m_string->length();
}
Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement.");
@@ -551,23 +559,23 @@ QScriptValuePrivate* QScriptValuePrivate::toObject(QScriptEnginePrivate* engine)
case CString:
{
// Exception can't occur here.
- JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(m_string), /* exception */ 0);
+ JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(*u.m_string), /* exception */ 0);
Q_ASSERT(object);
- return new QScriptValuePrivate(engine, object, object);
+ return new QScriptValuePrivate(engine, object);
}
case CNumber:
{
// Exception can't occur here.
- JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(m_number), /* exception */ 0);
+ JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(u.m_number), /* exception */ 0);
Q_ASSERT(object);
- return new QScriptValuePrivate(engine, object, object);
+ return new QScriptValuePrivate(engine, object);
}
case CBool:
{
// Exception can't occure here.
- JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(static_cast<bool>(m_number)), /* exception */ 0);
+ JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(u.m_bool), /* exception */ 0);
Q_ASSERT(object);
- return new QScriptValuePrivate(engine, object, object);
+ return new QScriptValuePrivate(engine, object);
}
case JSValue:
if (refinedJSValue() != JSPrimitive)
@@ -605,6 +613,35 @@ QScriptValuePrivate* QScriptValuePrivate::toObject()
return new QScriptValuePrivate;
}
+inline QScriptValuePrivate* QScriptValuePrivate::prototype()
+{
+ if (isObject()) {
+ JSValueRef prototype = JSObjectGetPrototype(*m_engine, *this);
+ if (JSValueIsNull(*m_engine, prototype))
+ return new QScriptValuePrivate(engine(), prototype);
+ // The prototype could be either a null or a JSObject, so it is safe to cast the prototype
+ // to the JSObjectRef here.
+ return new QScriptValuePrivate(engine(), prototype, const_cast<JSObjectRef>(prototype));
+ }
+ return new QScriptValuePrivate;
+}
+
+inline void QScriptValuePrivate::setPrototype(QScriptValuePrivate* prototype)
+{
+ if (isObject() && prototype->isValid() && (prototype->isObject() || prototype->isNull())) {
+ if (engine() != prototype->engine()) {
+ qWarning("QScriptValue::setPrototype() failed: cannot set a prototype created in a different engine");
+ return;
+ }
+ // FIXME: This could be replaced by a new, faster API
+ // look at https://bugs.webkit.org/show_bug.cgi?id=40060
+ JSObjectSetPrototype(*m_engine, *this, *prototype);
+ JSValueRef proto = JSObjectGetPrototype(*m_engine, *this);
+ if (!JSValueIsStrictEqual(*m_engine, proto, *prototype))
+ qWarning("QScriptValue::setPrototype() failed: cyclic prototype value");
+ }
+}
+
bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
{
if (!isValid())
@@ -615,9 +652,9 @@ bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
if ((m_state == other->m_state) && !isJSBased()) {
if (isNumberBased())
- return m_number == other->m_number;
+ return u.m_number == other->u.m_number;
Q_ASSERT(isStringBased());
- return m_string == other->m_string;
+ return *u.m_string == *(other->u.m_string);
}
if (!isJSBased() && !other->isJSBased())
@@ -655,7 +692,7 @@ bool QScriptValuePrivate::strictlyEquals(QScriptValuePrivate* other)
}
if (isStringBased()) {
if (other->isStringBased())
- return m_string == other->m_string;
+ return *u.m_string == *(other->u.m_string);
if (other->isJSBased()) {
assignEngine(other->engine());
return JSValueIsStrictEqual(*m_engine, *this, *other);
@@ -663,7 +700,7 @@ bool QScriptValuePrivate::strictlyEquals(QScriptValuePrivate* other)
}
if (isNumberBased()) {
if (other->isNumberBased())
- return m_number == other->m_number;
+ return u.m_number == other->u.m_number;
if (other->isJSBased()) {
assignEngine(other->engine());
return JSValueIsStrictEqual(*m_engine, *this, *other);
@@ -690,13 +727,14 @@ bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
JSValueRef value;
switch (m_state) {
case CBool:
- value = engine->makeJSValue(static_cast<bool>(m_number));
+ value = engine->makeJSValue(u.m_bool);
break;
case CString:
- value = engine->makeJSValue(m_string);
+ value = engine->makeJSValue(*u.m_string);
+ delete u.m_string;
break;
case CNumber:
- value = engine->makeJSValue(m_number);
+ value = engine->makeJSValue(u.m_number);
break;
case CNull:
value = engine->makeJSValue(QScriptValue::NullValue);
@@ -713,7 +751,8 @@ bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
}
m_engine = engine;
m_state = JSPrimitive;
- setValue(value);
+ u.m_value = value;
+ JSValueProtect(*m_engine, value);
return true;
}
@@ -763,22 +802,15 @@ QScriptEnginePrivate* QScriptValuePrivate::engine() const
QScriptValuePrivate::operator JSValueRef() const
{
Q_ASSERT(isJSBased());
- return m_value;
+ Q_ASSERT(u.m_value);
+ return u.m_value;
}
QScriptValuePrivate::operator JSObjectRef() const
{
Q_ASSERT(m_state == JSObject);
- return m_object;
-}
-
-void QScriptValuePrivate::setValue(JSValueRef value)
-{
- if (m_value)
- JSValueUnprotect(*m_engine, m_value);
- if (value)
- JSValueProtect(*m_engine, value);
- m_value = value;
+ Q_ASSERT(u.m_object);
+ return u.m_object;
}
/*!
@@ -806,10 +838,9 @@ QScriptValuePrivate::State QScriptValuePrivate::refinedJSValue()
if (!JSValueIsObject(*m_engine, *this)) {
m_state = JSPrimitive;
} else {
+ // Difference between JSValueRef and JSObjectRef is only in their type, binarywise it is the same.
+ // As m_value and m_object are stored in the u union, it is enough to change the m_state only.
m_state = JSObject;
- // We are sure that value is an JSObject, so we can const_cast safely without
- // calling JSC C API (JSValueToObject(*m_engine, *this, /* exceptions */ 0)).
- m_object = const_cast<JSObjectRef>(m_value);
}
return m_state;
}
diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp
index 90730c3..27d6df2 100644
--- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp
+++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp
@@ -431,6 +431,46 @@ void tst_QScriptValue::call()
QVERIFY(incr.call().isValid()); // Exception.
}
+void tst_QScriptValue::getSetPrototype()
+{
+ QScriptEngine engine;
+ QScriptValue object = engine.evaluate("new Object()");
+ QScriptValue object2 = engine.evaluate("new Object()");
+ object2.setPrototype(object);
+ QCOMPARE(object2.prototype().strictlyEquals(object), true);
+
+ QScriptValue inv;
+ inv.setPrototype(object);
+ QCOMPARE(inv.prototype().isValid(), false);
+
+ QScriptEngine otherEngine;
+ QScriptValue object3 = otherEngine.evaluate("new Object()");
+ QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cannot set a prototype created in a different engine");
+ object2.setPrototype(object3);
+ QCOMPARE(object2.prototype().strictlyEquals(object), true);
+
+ // cyclic prototypes
+ {
+ QScriptValue ret = engine.evaluate("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
+ QCOMPARE(ret.isError(), true);
+ QCOMPARE(ret.toString(), QLatin1String("Error: cyclic __proto__ value"));
+ }
+ {
+ QScriptValue ret = engine.evaluate("p.__proto__ = { }");
+ QCOMPARE(ret.isError(), false);
+ }
+
+ QScriptValue old = object.prototype();
+ QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cyclic prototype value");
+ object.setPrototype(object);
+ QCOMPARE(object.prototype().strictlyEquals(old), true);
+
+ object2.setPrototype(object);
+ QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cyclic prototype value");
+ object.setPrototype(object2);
+ QCOMPARE(object.prototype().strictlyEquals(old), true);
+}
+
void tst_QScriptValue::toObjectSimple()
{
QScriptEngine eng;
diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h
index 0565b6f..f9fcedb 100644
--- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h
+++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h
@@ -47,6 +47,7 @@ private slots:
void dataSharing();
void constructors_data();
void constructors();
+ void getSetPrototype();
void call();
void ctor();
void toObjectSimple();
diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp
index 699fbe6..9407be7 100644
--- a/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -77,12 +77,14 @@ static inline bool isNumericCompareFunction(ExecState* exec, CallType callType,
// If the JIT is enabled then we need to preserve the invariant that every
// function with a CodeBlock also has JIT code.
callData.js.functionExecutable->jitCodeForCall(exec, callData.js.scopeChain);
- CodeBlock& codeBlock = callData.js.functionExecutable->generatedBytecodeForCall();
+ CodeBlock* codeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
#else
- CodeBlock& codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain);
+ CodeBlock* codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain);
#endif
+ if (!codeBlock)
+ return false;
- return codeBlock.isNumericCompareFunction();
+ return codeBlock->isNumericCompareFunction();
}
// ------------------------------ ArrayPrototype ----------------------------
diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp
index a18e80c..f33f3b4 100644
--- a/JavaScriptCore/runtime/Executable.cpp
+++ b/JavaScriptCore/runtime/Executable.cpp
@@ -119,10 +119,12 @@ JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChain
return 0;
}
-void FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNode)
+bool FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNode)
{
JSGlobalData* globalData = scopeChainNode->globalData;
RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+ if (!body)
+ return false;
if (m_forceUsesArguments)
body->setUsesArguments();
body->finishParsing(m_parameters, m_name);
@@ -141,12 +143,15 @@ void FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNo
m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
body->destroyData();
+ return true;
}
-void FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeChainNode)
+bool FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeChainNode)
{
JSGlobalData* globalData = scopeChainNode->globalData;
RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+ if (!body)
+ return false;
if (m_forceUsesArguments)
body->setUsesArguments();
body->finishParsing(m_parameters, m_name);
@@ -165,6 +170,7 @@ void FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeCh
m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
body->destroyData();
+ return true;
}
#if ENABLE(JIT)
@@ -193,7 +199,7 @@ void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeCh
void FunctionExecutable::generateJITCodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
{
- CodeBlock* codeBlock = &bytecodeForCall(exec, scopeChainNode);
+ CodeBlock* codeBlock = bytecodeForCall(exec, scopeChainNode);
m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForCallWithArityCheck);
#if !ENABLE(OPCODE_SAMPLING)
@@ -204,7 +210,7 @@ void FunctionExecutable::generateJITCodeForCall(ExecState* exec, ScopeChainNode*
void FunctionExecutable::generateJITCodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
{
- CodeBlock* codeBlock = &bytecodeForConstruct(exec, scopeChainNode);
+ CodeBlock* codeBlock = bytecodeForConstruct(exec, scopeChainNode);
m_jitCodeForConstruct = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForConstructWithArityCheck);
#if !ENABLE(OPCODE_SAMPLING)
@@ -226,6 +232,8 @@ void FunctionExecutable::markAggregate(MarkStack& markStack)
ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
{
RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+ if (!newFunctionBody)
+ return 0;
if (m_forceUsesArguments)
newFunctionBody->setUsesArguments();
newFunctionBody->finishParsing(m_parameters, m_name);
@@ -255,6 +263,8 @@ ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData
ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
{
RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source);
+ if (!newEvalBody)
+ return 0;
ScopeChain scopeChain(scopeChainNode);
JSGlobalObject* globalObject = scopeChain.globalObject();
diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h
index 39ddf49..3320fe1 100644
--- a/JavaScriptCore/runtime/Executable.h
+++ b/JavaScriptCore/runtime/Executable.h
@@ -305,12 +305,12 @@ namespace JSC {
return *m_codeBlockForConstruct;
}
- FunctionCodeBlock& bytecodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
+ FunctionCodeBlock* bytecodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
{
ASSERT(scopeChainNode);
if (!m_codeBlockForCall)
compileForCall(exec, scopeChainNode);
- return *m_codeBlockForCall;
+ return m_codeBlockForCall;
}
bool isGeneratedForCall() const
@@ -324,12 +324,12 @@ namespace JSC {
return *m_codeBlockForCall;
}
- FunctionCodeBlock& bytecodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
+ FunctionCodeBlock* bytecodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
{
ASSERT(scopeChainNode);
if (!m_codeBlockForConstruct)
compileForConstruct(exec, scopeChainNode);
- return *m_codeBlockForConstruct;
+ return m_codeBlockForConstruct;
}
bool isGeneratedForConstruct() const
@@ -383,8 +383,8 @@ namespace JSC {
m_lastLine = lastLine;
}
- void compileForCall(ExecState*, ScopeChainNode*);
- void compileForConstruct(ExecState*, ScopeChainNode*);
+ bool compileForCall(ExecState*, ScopeChainNode*);
+ bool compileForConstruct(ExecState*, ScopeChainNode*);
unsigned m_numVariables : 31;
bool m_forceUsesArguments : 1;
diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp
index 3f24ea4..30a5ef9 100644
--- a/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -49,6 +49,7 @@
#include "Lookup.h"
#include "Nodes.h"
#include "Parser.h"
+#include "RegExpCache.h"
#include <wtf/WTFThreadData.h>
#if ENABLE(JSC_MULTIPLE_THREADS)
@@ -147,6 +148,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, cachedUTCOffset(NaN)
, weakRandom(static_cast<int>(currentTime()))
, maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
+ , m_regExpCache(new RegExpCache(this))
#ifndef NDEBUG
, exclusiveThread(0)
#endif
@@ -196,6 +198,7 @@ JSGlobalData::~JSGlobalData()
deleteIdentifierTable(identifierTable);
delete clientData;
+ delete m_regExpCache;
}
PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type)
@@ -246,7 +249,7 @@ const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
initializingLazyNumericCompareFunction = true;
RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare"), exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
- lazyNumericCompareFunction = function->bytecodeForCall(exec, exec->scopeChain()).instructions();
+ lazyNumericCompareFunction = function->bytecodeForCall(exec, exec->scopeChain())->instructions();
initializingLazyNumericCompareFunction = false;
}
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
index f48aec8..f99c8d6 100644
--- a/JavaScriptCore/runtime/JSGlobalData.h
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -44,6 +44,7 @@
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
+#include <wtf/ThreadSpecific.h>
struct OpaqueJSClass;
struct OpaqueJSClassContextData;
@@ -58,6 +59,7 @@ namespace JSC {
class JSObject;
class Lexer;
class Parser;
+ class RegExpCache;
class Stringifier;
class Structure;
class UString;
@@ -211,17 +213,22 @@ namespace JSC {
WeakRandom weakRandom;
int maxReentryDepth;
+
+ RegExpCache* m_regExpCache;
+
#ifndef NDEBUG
ThreadIdentifier exclusiveThread;
#endif
CachedTranscendentalFunction<sin> cachedSin;
+ WTF::ThreadSpecific<char*> stackGuards;
void resetDateCache();
void startSampling();
void stopSampling();
void dumpSampleData(ExecState* exec);
+ RegExpCache* regExpCache() { return m_regExpCache; }
private:
JSGlobalData(GlobalDataType, ThreadStackType);
static JSGlobalData*& sharedInstanceInternal();
diff --git a/JavaScriptCore/runtime/JSImmediate.h b/JavaScriptCore/runtime/JSImmediate.h
index 9127b6a..f33d9fe 100644
--- a/JavaScriptCore/runtime/JSImmediate.h
+++ b/JavaScriptCore/runtime/JSImmediate.h
@@ -44,6 +44,8 @@ namespace JSC {
class JSObject;
class UString;
+ extern const size_t CELL_MASK;
+
#if USE(JSVALUE64)
inline intptr_t reinterpretDoubleToIntptr(double value)
{
@@ -595,7 +597,13 @@ namespace JSC {
inline bool JSValue::isCell() const
{
+#ifndef NDEBUG
+ bool r = !JSImmediate::isImmediate(asValue());
+ ASSERT(!r || !(JSImmediate::rawValue(asValue()) & CELL_MASK));
+ return r;
+#else
return !JSImmediate::isImmediate(asValue());
+#endif
}
inline bool JSValue::isInt32() const
diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp
index 473eb77..1d5e639 100644
--- a/JavaScriptCore/runtime/JSString.cpp
+++ b/JavaScriptCore/runtime/JSString.cpp
@@ -150,6 +150,7 @@ JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UStri
if (replacement.size())
builder.append(replacement);
builder.append(UString(string).substr(matchPosition + 1));
+ matchString = 0;
}
JSGlobalData* globalData = &exec->globalData();
diff --git a/JavaScriptCore/runtime/JSValue.cpp b/JavaScriptCore/runtime/JSValue.cpp
index 728cbcf..e752d3f 100644
--- a/JavaScriptCore/runtime/JSValue.cpp
+++ b/JavaScriptCore/runtime/JSValue.cpp
@@ -126,10 +126,10 @@ char* JSValue::description()
snprintf(description, size, "False");
else if (isNull())
snprintf(description, size, "Null");
- else {
- ASSERT(isUndefined());
+ else if (isUndefined())
snprintf(description, size, "Undefined");
- }
+ else
+ snprintf(description, size, "INVALID");
return description;
}
diff --git a/JavaScriptCore/runtime/JSZombie.cpp b/JavaScriptCore/runtime/JSZombie.cpp
index 072d29b..22aabb9 100644
--- a/JavaScriptCore/runtime/JSZombie.cpp
+++ b/JavaScriptCore/runtime/JSZombie.cpp
@@ -37,7 +37,7 @@ Structure* JSZombie::leakedZombieStructure() {
static Structure* structure = 0;
if (!structure) {
Structure::startIgnoringLeaks();
- structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType)).releaseRef();
+ structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0).releaseRef();
Structure::stopIgnoringLeaks();
}
return structure;
diff --git a/JavaScriptCore/runtime/RegExpCache.cpp b/JavaScriptCore/runtime/RegExpCache.cpp
new file mode 100644
index 0000000..192df4d
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpCache.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 University of Szeged
+ * Copyright (C) 2010 Renata Hodovan (hodovan@inf.u-szeged.hu)
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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.
+ */
+
+#include "config.h"
+
+#include "RegExpCache.h"
+
+namespace JSC {
+
+PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, const UString& flags)
+{
+ if (patternString.size() < maxCacheablePatternLength) {
+ pair<HashMap<RegExpKey, RefPtr<RegExp> >::iterator, bool> result = m_cacheMap.add(RegExpKey(flags, patternString), 0);
+ if (!result.second)
+ return result.first->second;
+ }
+ return create(patternString, flags);
+}
+
+PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, const UString& flags)
+{
+ RefPtr<RegExp> regExp;
+
+ if (!flags.isNull())
+ regExp = RegExp::create(m_globalData, patternString, flags);
+ else
+ regExp = RegExp::create(m_globalData, patternString);
+
+ if (patternString.size() >= maxCacheablePatternLength)
+ return regExp;
+
+ ++m_nextKeyToEvict;
+ if (m_nextKeyToEvict == maxCacheableEntries) {
+ m_nextKeyToEvict = 0;
+ m_isFull = true;
+ }
+ if (m_isFull)
+ m_cacheMap.remove(RegExpKey(patternKeyArray[m_nextKeyToEvict].flagsValue, patternKeyArray[m_nextKeyToEvict].pattern));
+
+ RegExpKey key = RegExpKey(flags, patternString);
+ m_cacheMap.set(key, regExp);
+ patternKeyArray[m_nextKeyToEvict].flagsValue = key.flagsValue;
+ patternKeyArray[m_nextKeyToEvict].pattern = patternString.rep();
+ return regExp;
+}
+
+RegExpCache::RegExpCache(JSGlobalData* globalData)
+ : m_globalData(globalData)
+ , m_nextKeyToEvict(-1)
+ , m_isFull(false)
+{
+}
+
+}
diff --git a/JavaScriptCore/runtime/RegExpCache.h b/JavaScriptCore/runtime/RegExpCache.h
new file mode 100644
index 0000000..03b73ac
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpCache.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 University of Szeged
+ * Copyright (C) 2010 Renata Hodovan (hodovan@inf.u-szeged.hu)
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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.
+ */
+
+#include "RegExp.h"
+#include "RegExpKey.h"
+#include "UString.h"
+
+#ifndef RegExpCache_h
+#define RegExpCache_h
+
+namespace JSC {
+
+class RegExpCache {
+public:
+ PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, const UString& flags);
+ PassRefPtr<RegExp> create(const UString& patternString, const UString& flags);
+ RegExpCache(JSGlobalData* globalData);
+
+private:
+ static const unsigned maxCacheablePatternLength = 256;
+ static const int maxCacheableEntries = 256;
+
+ typedef HashMap<RegExpKey, RefPtr<RegExp> > RegExpCacheMap;
+ RegExpKey patternKeyArray[maxCacheableEntries];
+ RegExpCacheMap m_cacheMap;
+ JSGlobalData* m_globalData;
+ int m_nextKeyToEvict;
+ bool m_isFull;
+};
+
+} // namespace JSC
+
+#endif // RegExpCache_h
diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp
index 24476d6..166a021 100644
--- a/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -34,6 +34,7 @@
#include "RegExpObject.h"
#include "RegExpPrototype.h"
#include "RegExp.h"
+#include "RegExpCache.h"
namespace JSC {
@@ -302,7 +303,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args)
UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec);
UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
- RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags);
+ RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags);
if (!regExp->isValid())
return throwError(exec, createSyntaxError(exec, makeString("Invalid regular expression: ", regExp->errorMessage())));
return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
diff --git a/JavaScriptCore/runtime/RegExpKey.h b/JavaScriptCore/runtime/RegExpKey.h
new file mode 100644
index 0000000..e5ab438
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpKey.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2010 University of Szeged
+ * Copyright (C) 2010 Renata Hodovan (hodovan@inf.u-szeged.hu)
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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.
+ */
+
+#include "UString.h"
+
+#ifndef RegExpKey_h
+#define RegExpKey_h
+
+namespace JSC {
+
+struct RegExpKey {
+ int flagsValue;
+ RefPtr<UString::Rep> pattern;
+
+ RegExpKey()
+ : flagsValue(0)
+ {
+ }
+
+ RegExpKey(int flags)
+ : flagsValue(flags)
+ {
+ }
+
+ RegExpKey(int flags, const UString& pattern)
+ : flagsValue(flags)
+ , pattern(pattern.rep())
+ {
+ }
+
+ RegExpKey(int flags, const PassRefPtr<UString::Rep> pattern)
+ : flagsValue(flags)
+ , pattern(pattern)
+ {
+ }
+
+ RegExpKey(const UString& flags, const UString& pattern)
+ : pattern(pattern.rep())
+ {
+ flagsValue = getFlagsValue(flags);
+ }
+
+ int getFlagsValue(const UString flags)
+ {
+ flagsValue = 0;
+ if (flags.find('g') != UString::NotFound)
+ flagsValue += 4;
+ if (flags.find('i') != UString::NotFound)
+ flagsValue += 2;
+ if (flags.find('m') != UString::NotFound)
+ flagsValue += 1;
+ return flagsValue;
+ }
+};
+} // namespace JSC
+
+namespace WTF {
+template<typename T> struct DefaultHash;
+template<typename T> struct RegExpHash;
+
+inline bool operator==(const JSC::RegExpKey& a, const JSC::RegExpKey& b)
+{
+ if (a.flagsValue != b.flagsValue)
+ return false;
+ if (!a.pattern)
+ return !b.pattern;
+ if (!b.pattern)
+ return false;
+ return equal(a.pattern.get(), b.pattern.get());
+}
+
+template<> struct RegExpHash<JSC::RegExpKey> {
+ static unsigned hash(const JSC::RegExpKey& key) { return key.pattern->hash(); }
+ static bool equal(const JSC::RegExpKey& a, const JSC::RegExpKey& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = false;
+};
+
+template<> struct DefaultHash<JSC::RegExpKey> {
+ typedef RegExpHash<JSC::RegExpKey> Hash;
+};
+
+template<> struct HashTraits<JSC::RegExpKey> : GenericHashTraits<JSC::RegExpKey> {
+ static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = -1; }
+ static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == -1; }
+};
+} // namespace WTF
+
+#endif // RegExpKey_h
diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp
index 9d78f59..834412b 100644
--- a/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -33,6 +33,7 @@
#include "PrototypeFunction.h"
#include "RegExpObject.h"
#include "RegExp.h"
+#include "RegExpCache.h"
namespace JSC {
@@ -91,7 +92,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
} else {
UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec);
UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
- regExp = RegExp::create(&exec->globalData(), pattern, flags);
+ regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags);
}
if (!regExp->isValid())
diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp
index 5b90456..8b56d53 100644
--- a/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/JavaScriptCore/runtime/StringPrototype.cpp
@@ -33,6 +33,7 @@
#include "ObjectPrototype.h"
#include "Operations.h"
#include "PropertyNameArray.h"
+#include "RegExpCache.h"
#include "RegExpConstructor.h"
#include "RegExpObject.h"
#include <wtf/ASCIICType.h>
@@ -585,7 +586,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
* If regexp is not an object whose [[Class]] property is "RegExp", it is
* replaced with the result of the expression new RegExp(regexp).
*/
- reg = RegExp::create(&exec->globalData(), a0.toString(exec));
+ reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString::null());
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
@@ -636,7 +637,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
* If regexp is not an object whose [[Class]] property is "RegExp", it is
* replaced with the result of the expression new RegExp(regexp).
*/
- reg = RegExp::create(&exec->globalData(), a0.toString(exec));
+ reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString::null());
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
diff --git a/JavaScriptCore/runtime/SymbolTable.h b/JavaScriptCore/runtime/SymbolTable.h
index f5e2669..2717075 100644
--- a/JavaScriptCore/runtime/SymbolTable.h
+++ b/JavaScriptCore/runtime/SymbolTable.h
@@ -121,8 +121,11 @@ namespace JSC {
typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
- class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable>
- {
+ class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable> {
+ public:
+ static PassRefPtr<SharedSymbolTable> create() { return adoptRef(new SharedSymbolTable); }
+ private:
+ SharedSymbolTable() { }
};
} // namespace JSC
diff --git a/JavaScriptCore/wtf/CMakeLists.txt b/JavaScriptCore/wtf/CMakeLists.txt
index db69117..1119b3c 100644
--- a/JavaScriptCore/wtf/CMakeLists.txt
+++ b/JavaScriptCore/wtf/CMakeLists.txt
@@ -5,6 +5,7 @@ SET(WTF_SOURCES
FastMalloc.cpp
HashTable.cpp
MainThread.cpp
+ MD5.cpp
RandomNumber.cpp
RefCountedLeakCounter.cpp
StringExtras.cpp
diff --git a/JavaScriptCore/wtf/FastMalloc.h b/JavaScriptCore/wtf/FastMalloc.h
index 1ccd6a6..9729bc3 100644
--- a/JavaScriptCore/wtf/FastMalloc.h
+++ b/JavaScriptCore/wtf/FastMalloc.h
@@ -207,7 +207,7 @@ using WTF::fastMallocAllow;
#define WTF_PRIVATE_INLINE inline
#endif
-#if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC)
+#if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC && !PLATFORM(BREWMP))
// The nothrow functions here are actually not all that helpful, because fastMalloc will
// call CRASH() rather than returning 0, and returning 0 is what nothrow is all about.
diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h
index 8c125c1..b92d267 100644
--- a/JavaScriptCore/wtf/Platform.h
+++ b/JavaScriptCore/wtf/Platform.h
@@ -100,7 +100,10 @@
#undef _WIN32
#endif
-
+/* COMPILER(INTEL) - Intel C++ Compiler */
+#if defined(__INTEL_COMPILER)
+#define WTF_COMPILER_INTEL 1
+#endif
/* ==== CPU() - the target CPU architecture ==== */
@@ -982,9 +985,12 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
#define ENABLE_JIT_OPTIMIZE_MOD 1
#endif
#endif
-#if (CPU(X86) && USE(JSVALUE32_64)) || (CPU(X86_64) && USE(JSVALUE64))
+#if (CPU(X86) && USE(JSVALUE32_64)) || (CPU(X86_64) && USE(JSVALUE64)) \
+ || CPU(ARM)
+#if ENABLE(JIT) && !defined(ENABLE_JIT_OPTIMIZE_NATIVE_CALL)
#define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 1
#endif
+#endif
#if ENABLE(JIT)
#ifndef ENABLE_JIT_OPTIMIZE_CALL
@@ -1099,4 +1105,13 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
#define ENABLE_JSC_ZOMBIES 0
+#if !defined(BUILDING_ON_TIGER)
+#define ENABLE_RECURSIVE_PARSE 1
+#endif
+
+/* FIXME: Eventually we should enable this for all platforms and get rid of the define. */
+#if PLATFORM(MAC)
+#define WTF_USE_PLATFORM_STRATEGIES 1
+#endif
+
#endif /* WTF_Platform_h */
diff --git a/JavaScriptCore/wtf/RetainPtr.h b/JavaScriptCore/wtf/RetainPtr.h
index 77f25e0..f5a027e 100644
--- a/JavaScriptCore/wtf/RetainPtr.h
+++ b/JavaScriptCore/wtf/RetainPtr.h
@@ -21,6 +21,7 @@
#ifndef RetainPtr_h
#define RetainPtr_h
+#include "HashTraits.h"
#include "TypeTraits.h"
#include <algorithm>
#include <CoreFoundation/CoreFoundation.h>
@@ -60,6 +61,10 @@ namespace WTF {
RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
+ // Hash table deleted values, which are only constructed and never copied or destroyed.
+ RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
+ bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+
~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); }
template <typename U> RetainPtr(const RetainPtr<U>& o) : m_ptr(o.get()) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
@@ -87,6 +92,8 @@ namespace WTF {
void swap(RetainPtr&);
private:
+ static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+
PtrType m_ptr;
};
@@ -193,6 +200,23 @@ namespace WTF {
{
return a != b.get();
}
+
+ template<typename P> struct HashTraits<RetainPtr<P> > : GenericHashTraits<RetainPtr<P> > {
+ static const bool emptyValueIsZero = true;
+ static void constructDeletedValue(RetainPtr<P>& slot) { new (&slot) RetainPtr<P>(HashTableDeletedValue); }
+ static bool isDeletedValue(const RetainPtr<P>& value) { return value == reinterpret_cast<P*>(-1); }
+ };
+
+ template<typename P> struct PtrHash<RetainPtr<P> > : PtrHash<P*> {
+ using PtrHash<P*>::hash;
+ static unsigned hash(const RetainPtr<P>& key) { return hash(key.get()); }
+ using PtrHash<P*>::equal;
+ static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) { return a == b; }
+ static bool equal(P* a, const RetainPtr<P>& b) { return a == b; }
+ static bool equal(const RetainPtr<P>& a, P* b) { return a == b; }
+ };
+
+ template<typename P> struct DefaultHash<RetainPtr<P> > { typedef PtrHash<RetainPtr<P> > Hash; };
} // namespace WTF
diff --git a/JavaScriptCore/wtf/StringExtras.h b/JavaScriptCore/wtf/StringExtras.h
index e8f2878..8156580 100644
--- a/JavaScriptCore/wtf/StringExtras.h
+++ b/JavaScriptCore/wtf/StringExtras.h
@@ -28,6 +28,7 @@
#include <stdarg.h>
#include <stdio.h>
+#include <string.h>
#if HAVE(STRINGS_H)
#include <strings.h>
diff --git a/JavaScriptCore/wtf/ThreadSafeShared.h b/JavaScriptCore/wtf/ThreadSafeShared.h
index 688747e..33c6612 100644
--- a/JavaScriptCore/wtf/ThreadSafeShared.h
+++ b/JavaScriptCore/wtf/ThreadSafeShared.h
@@ -129,16 +129,16 @@ private:
template<class T> class ThreadSafeShared : public ThreadSafeSharedBase {
public:
- ThreadSafeShared(int initialRefCount = 1)
- : ThreadSafeSharedBase(initialRefCount)
- {
- }
-
void deref()
{
if (derefBase())
delete static_cast<T*>(this);
}
+
+protected:
+ ThreadSafeShared()
+ {
+ }
};
} // namespace WTF
diff --git a/JavaScriptCore/wtf/ThreadSpecific.h b/JavaScriptCore/wtf/ThreadSpecific.h
index 7e5679f..893f561 100644
--- a/JavaScriptCore/wtf/ThreadSpecific.h
+++ b/JavaScriptCore/wtf/ThreadSpecific.h
@@ -47,13 +47,15 @@
#include <pthread.h>
#elif PLATFORM(QT)
#include <QThreadStorage>
+#elif PLATFORM(GTK)
+#include <glib.h>
#elif OS(WINDOWS)
#include <windows.h>
#endif
namespace WTF {
-#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS)
// ThreadSpecificThreadExit should be called each time when a thread is detached.
// This is done automatically for threads created with WTF::createThread.
void ThreadSpecificThreadExit();
@@ -68,7 +70,7 @@ public:
~ThreadSpecific();
private:
-#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS)
friend void ThreadSpecificThreadExit();
#endif
@@ -76,7 +78,7 @@ private:
void set(T*);
void static destroy(void* ptr);
-#if USE(PTHREADS) || PLATFORM(QT) || OS(WINDOWS)
+#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(GTK) || OS(WINDOWS)
struct Data : Noncopyable {
Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
#if PLATFORM(QT)
@@ -85,7 +87,7 @@ private:
T* value;
ThreadSpecific<T>* owner;
-#if !USE(PTHREADS) && !PLATFORM(QT)
+#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK)
void (*destructor)(void*);
#endif
};
@@ -98,6 +100,8 @@ private:
pthread_key_t m_key;
#elif PLATFORM(QT)
QThreadStorage<Data*> m_key;
+#elif PLATFORM(GTK)
+ GStaticPrivate m_key;
#elif OS(WINDOWS)
int m_index;
#endif
@@ -186,6 +190,35 @@ inline void ThreadSpecific<T>::set(T* ptr)
m_key.setLocalData(data);
}
+#elif PLATFORM(GTK)
+
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
+{
+ g_static_private_init(&m_key);
+}
+
+template<typename T>
+inline ThreadSpecific<T>::~ThreadSpecific()
+{
+ g_static_private_free(&m_key);
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::get()
+{
+ Data* data = static_cast<Data*>(g_static_private_get(&m_key));
+ return data ? data->value : 0;
+}
+
+template<typename T>
+inline void ThreadSpecific<T>::set(T* ptr)
+{
+ ASSERT(!get());
+ Data* data = new Data(ptr, this);
+ g_static_private_set(&m_key, data, destroy);
+}
+
#elif OS(WINDOWS)
// TLS_OUT_OF_INDEXES is not defined on WinCE.
@@ -253,6 +286,9 @@ inline void ThreadSpecific<T>::destroy(void* ptr)
// We want get() to keep working while data destructor works, because it can be called indirectly by the destructor.
// Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it.
pthread_setspecific(data->owner->m_key, ptr);
+#elif PLATFORM(GTK)
+ // See comment as above
+ g_static_private_set(&data->owner->m_key, data, 0);
#endif
#if PLATFORM(QT)
// See comment as above
@@ -266,6 +302,8 @@ inline void ThreadSpecific<T>::destroy(void* ptr)
pthread_setspecific(data->owner->m_key, 0);
#elif PLATFORM(QT)
// Do nothing here
+#elif PLATFORM(GTK)
+ g_static_private_set(&data->owner->m_key, 0, 0);
#elif OS(WINDOWS)
TlsSetValue(tlsKeys()[data->owner->m_index], 0);
#else
@@ -285,7 +323,7 @@ inline ThreadSpecific<T>::operator T*()
if (!ptr) {
// Set up thread-specific value's memory pointer before invoking constructor, in case any function it calls
// needs to access the value, to avoid recursion.
- ptr = static_cast<T*>(fastMalloc(sizeof(T)));
+ ptr = static_cast<T*>(fastZeroedMalloc(sizeof(T)));
set(ptr);
new (ptr) T;
}
diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h
index b653001..c833eeb 100644
--- a/JavaScriptCore/wtf/Vector.h
+++ b/JavaScriptCore/wtf/Vector.h
@@ -49,7 +49,7 @@ namespace WTF {
#error WTF_ALIGN macros need alignment control.
#endif
- #if COMPILER(GCC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
+ #if COMPILER(GCC) && !COMPILER(INTEL) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
typedef char __attribute__((__may_alias__)) AlignedBufferChar;
#else
typedef char AlignedBufferChar;
diff --git a/JavaScriptCore/yarr/RegexCompiler.cpp b/JavaScriptCore/yarr/RegexCompiler.cpp
index bcfc188..fa87186 100644
--- a/JavaScriptCore/yarr/RegexCompiler.cpp
+++ b/JavaScriptCore/yarr/RegexCompiler.cpp
@@ -623,7 +623,7 @@ const char* compileRegex(const UString& patternString, RegexPattern& pattern)
constructor.setupOffsets();
- return false;
+ return 0;
};
diff --git a/JavaScriptCore/yarr/RegexJIT.cpp b/JavaScriptCore/yarr/RegexJIT.cpp
index 768a53d..68d3803 100644
--- a/JavaScriptCore/yarr/RegexJIT.cpp
+++ b/JavaScriptCore/yarr/RegexJIT.cpp
@@ -1241,16 +1241,18 @@ class RegexGenerator : private MacroAssembler {
// If we get here, the alternative matched.
if (m_pattern.m_body->m_callFrameSize)
addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
-
+
ASSERT(index != returnRegister);
if (m_pattern.m_body->m_hasFixedSize) {
move(index, returnRegister);
if (alternative->m_minimumSize)
sub32(Imm32(alternative->m_minimumSize), returnRegister);
+
+ store32(returnRegister, output);
} else
- pop(returnRegister);
+ load32(Address(output), returnRegister);
+
store32(index, Address(output, 4));
- store32(returnRegister, output);
generateReturn();
@@ -1334,7 +1336,7 @@ class RegexGenerator : private MacroAssembler {
if (!m_pattern.m_body->m_hasFixedSize) {
move(index, regT0);
sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0);
- poke(regT0, m_pattern.m_body->m_callFrameSize);
+ store32(regT0, Address(output));
}
// Update index if necessary, and loop (without checking).
@@ -1349,9 +1351,9 @@ class RegexGenerator : private MacroAssembler {
if (countCheckedForCurrentAlternative - 1) {
move(index, regT0);
sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0);
- poke(regT0, m_pattern.m_body->m_callFrameSize);
+ store32(regT0, Address(output));
} else
- poke(index, m_pattern.m_body->m_callFrameSize);
+ store32(index, Address(output));
}
// Check if there is sufficent input to run the first alternative again.
jumpIfAvailableInput(incrementForNextIter).linkTo(firstAlternativeInputChecked, this);
@@ -1377,11 +1379,8 @@ class RegexGenerator : private MacroAssembler {
// it has either been incremented by 1 or by (countToCheckForFirstAlternative + 1) ...
// but since we're about to return a failure this doesn't really matter!)
- unsigned frameSize = m_pattern.m_body->m_callFrameSize;
- if (!m_pattern.m_body->m_hasFixedSize)
- ++frameSize;
- if (frameSize)
- addPtr(Imm32(frameSize * sizeof(void*)), stackPointerRegister);
+ if (m_pattern.m_body->m_callFrameSize)
+ addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
move(Imm32(-1), returnRegister);
@@ -1451,9 +1450,8 @@ public:
{
generateEnter();
- // TODO: do I really want this on the stack?
if (!m_pattern.m_body->m_hasFixedSize)
- push(index);
+ store32(index, Address(output));
if (m_pattern.m_body->m_callFrameSize)
subPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);